This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
format xml string
I'm generating an XML page like so:
header('Content-Type: text/html');
$xmlpage = '<?xml version="1.0" charset="utf-8"?>';
$xmlpage .= '<conv>';
$xmlpage .= '<at>6 January 2012 12:00</at>';
$xmlpage .= '<rate>1.56317</rate>';
$xmlpage .= '<from>';
$xmlpage .= '<code>'.$from.'</code>';
$xmlpage .= '<curr>Pound Sterling</curr>';
$xmlpage .= '<loc>UK</loc>';
$xmlpage .= '<amnt>'.$amnt.'</amnt>';
$xmlpage .= '</from>';
$xmlpage .= '</conv>';
echo $xmlpage;
When viewing the page source, it looks terrible:
<?xml version="1.0" charset="utf-8"?><conv><at>6 January 2012 12:00</at><rate>1.56317</rate><from><code>USD</code><curr>Pound Sterling</curr><loc>UK</loc><amnt>23</amnt></from><to><code>GBP</code><curr>United States Dollar</curr><loc>USA</loc><amnt>14.73</amnt></to></conv>
How can I make this so it's properly formatted and indented?
Add newlines with the \r\n or only \n characters. You'll need to place your strings in double quotes ("") for it to work, so either replace the double-quotes inside the strings with single ones ('), escape the double quotes (\"), add ."\r\n" as a linebreak or use HEREDOC.
Building your XML with a XML generator like the built-in SimpleXML will prevent these sort and numerous other types of problems and is usually far easier than building it by hand with strings.
You could:
Do it yourself by adding whitespace characters to your strings (\n, \t).
Output all your XML with a HEREDOC
You could create or even generate a DOMDocument and use saveXML()
The first two are quick and dirty (heredoc's better). The latter is more robust, but more code.
Use a HEREDOC. it'll be far easier to read than repeated string concatenation, allows tabs/multilines, and does variable interpolation for you:
$xmlpage = <<<EOL
<?xml version="1.0" charset="utf-8"?>
<conv>
<at>6 January 2012 12:00</at>
<rate>1.56317</rate>
<from>
<code>$from</code>
<curr>Pound Sterling</curr>
<loc>UK</loc>
<amnt>$amnt</amnt>
</from>
</conv>
EOL;
Use a stylesheet and an XML viewer to view it.
add a \n after every $xmlpage. You should be able to view it properly after the echo.
e.g.
$xmlpage = "<?xml version="1.0" charset="utf-8"?>\n";
$xmlpage .= "<conv>\n";
$xmlpage .= "<at>6 January 2012 12:00</at>\n";
$xmlpage .= "<rate>1.56317</rate>\n";
The simplest way would be to add the appropriate whitespace to the beginning of the strings, and the newlines to the ends.
$xmlpage = '<?xml version="1.0" charset="utf-8"?>';
$xmlpage .= '<conv>' . "\n";
$xmlpage .= "\t" . '<at>6 January 2012 12:00</at>' . "\n";
$xmlpage .= "\t" . '<rate>1.56317</rate>' . "\n";
$xmlpage .= '<from>' . "\n";
$xmlpage .= "\t" . '<code>'.$from.'</code>' . "\n";
$xmlpage .= "\t" . '<curr>Pound Sterling</curr>' . "\n";
$xmlpage .= "\t" . '<loc>UK</loc>' . "\n";
$xmlpage .= "\t" . '<amnt>'.$amnt.'</amnt>' . "\n";
$xmlpage .= '</from>' . "\n";
$xmlpage .= '</conv>';
Or something along those lines, depending on your desired output.
Here's my prettify function, which formats for output. You can modify it to suit your needs.
function prettifyXML( $xml )
{
// Break our XML up into sections of newlines.
$xml = preg_replace( '/(<[^\/][^>]*?[^\/]>)/', "\n" . '\1', $xml );
$xml = preg_replace( '/(<\/[^\/>]*>|<[^\/>]*?\/>)/', '\1' . "\n", $xml );
$xml = str_replace( "\n\n", "\n", $xml );
$xml_chunks = explode( "\n", $xml );
$indent_depth = 0;
$open_tag_regex = '/<[^\/\?][^>]*>/';
$close_tag_regex = '/(<\/[^>]*>|<[^>]*\/>)/';
// Fix the indenting.
foreach ( $xml_chunks as $index => $xml_chunk )
{
$close_tag_count = preg_match( $close_tag_regex, $xml_chunk );
$open_tag_count = preg_match( $open_tag_regex, $xml_chunk );
if ( $open_tag_count >= $close_tag_count )
{
$temp_indent_depth = $indent_depth;
}
else
{
$temp_indent_depth = $indent_depth - $close_tag_count;
}
$xml_chunks[ $index ] = str_repeat( "\t", $temp_indent_depth ) . $xml_chunk;
$indent_depth += $open_tag_count - $close_tag_count;
}
$xml = implode( "\n", $xml_chunks );
// Add tokens for attributes and values.
$attribute_regex = '/([\w:]+\="[^"]*")/';
$value_regex = '/>([^<]*)</';
$value_span_token = '########';
$attribute_span_token = '########';
$span_close_token = '########';
$xml = preg_replace( $value_regex, '>' . $value_span_token . '\1' . $span_close_token . '<', $xml );
$xml = preg_replace( $attribute_regex, $attribute_span_token . '\1' .$span_close_token, $xml );
$xml = htmlentities( $xml );
// Replace the tokens that we added previously with their HTML counterparts.
$xml = str_replace( $value_span_token, '<span class="value">', $xml );
$xml = str_replace( $attribute_span_token, '<span class="attribute">', $xml );
$xml = str_replace( $span_close_token, '</span>', $xml );
return $xml;
}
It's been relatively well tested to handle edge cases, though it's not highly efficient because it's only for viewing logs.
Related
I a working on a sample project that gives positions of Telecom operators cell towers based on regions on google maps.
I am following the steps from the google maps API how-to
google maps instructions
i am stuck here. I have followed all the instructions and i am also getting XML output on my webpage from the database. Now as per the instructions that i have to follow, i have to save this output to an .XML file to my server for further processing, and adding markers on the google maps. The markers include the Lat - Long values and some information on the cell towers selected: cell-id, Location code and radio type.
I have searched for the solution but i am stuck at - PHP: DOMDocument::save and how to implement in my code.
The code for the same is attached for reference:
function parseToXML($htmlStr) {
$xmlStr = str_replace('<','<',$htmlStr);
$xmlStr = str_replace('>','>',$htmlStr);
$xmlStr = str_replace('"','"',$htmlStr);
$xmlStr=str_replace("'",''',$xmlStr);
$xmlStr = str_replace('&','&',$htmlStr);
return $xmlStr;
}
$t_query = "SELECT `radio_type`, `lac`,`cell-id`,`longitude`,`latitude` FROM `".DBNAME."`.`celltower` WHERE `mcc` = '".$mcc."' AND `mnc` = '".$mnc."'";
$t_query_exec = mysqli_query($con, $t_query);
if($t_num_rows = 0) {
die("Unable to fetch any data..Please try again..!!");
} else {
header("Content-type: text/xml");
//Begin XML file, echo parent node.
echo '<?xml version="1.0" encoding="utf-8"?>';
echo '<root>';
echo '<markers>';
//Iterating through rows, and printing XML nodes for each
while($t_var = mysqli_fetch_assoc($t_query_exec)) {
//Add to XML document node.
echo '<marker ';
echo 'radio_type="' .parseToXML($t_var['radio_type']) . '" ';
echo 'lac="' .parseToXML($t_var['lac']) . '" ';
echo 'cell-id="' .parseToXML($t_var['cell-id']) . '" ';
echo 'longitude="' . $t_var['longitude'] . '" ';
echo 'latitude="' .$t_var['latitude'] . '" ';
echo '/>';
}
echo '</markers>';
echo '</root>';
}
i just need to know that how can i save the output to an .XML file
Thanks in advance.
Just put your XML into a variable and save it with file_put_contents()
$xmlString = '<?xml version="1.0" encoding="utf-8"?>';
$xmlString .= '<root>';
$xmlString .= '<markers>';
//Iterating through rows, and printing XML nodes for each
while($t_var = mysqli_fetch_assoc($t_query_exec)) {
//Add to XML document node.
$xmlString .= '<marker ';
$xmlString .= 'radio_type="' .parseToXML($t_var['radio_type']) . '" ';
$xmlString .= 'lac="' .parseToXML($t_var['lac']) . '" ';
$xmlString .= 'cell-id="' .parseToXML($t_var['cell-id']) . '" ';
$xmlString .= 'longitude="' . $t_var['longitude'] . '" ';
$xmlString .= 'latitude="' .$t_var['latitude'] . '" ';
$xmlString .= '/>';
}
$xmlString .= '</markers>';
$xmlString .= '</root>';
file_put_contents('output.xml', $xmlString);
I am developing a webservice using Nusoap to send xml data, and this time I have to send data with latin characters like 'ó'. However when I put it in the soap client it stops working. Below is a summary of code being develped to test sending xml with latin characters.
This is ths summary of server code being developed:
include_once("nusoap/nusoap.php");
$server = new soap_server();
$server->configureWSDL("PersonImport","urn:PersonImport");
$server->register("PersonImport",array("login" => "xsd:string", 'senha' => 'xsd:string', 'fornecedor' => 'xsd:string'),array("return" => "xsd:string"),"urn:PersonImport","urn:PersonImport#PersonImport");
function PersonImport($login,$senha,$fornecedor) {
//Just for debug purposes
$return = "My login Is <b>".$login . "</b> And My senha Is <b>".$senha."</b> And My fornecedor Is <b>".$fornecedor."</b>.";
(...)(ommited code, xml parsing and response xml generation)
return $return;
}
This is ths summary of client code:
<?php
require_once("nusoap/nusoap.php");
$client = new soapclient("example.com?wsdl");
$xml = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>";
$xml .= "<fornecedor>";
$xml .= "<NAME1>Gian</NAME1>";
$xml .= "<MCOD1>Giancarlo SA</MCOD1>";
$xml .= "<STCD1>80048303000113</STCD1>";
$xml .= "<STCD2>55670185501</STCD2>";
$xml .= "<STCD3>5508150087</STCD3>";
$xml .= "<RG>359730553</RG>";
$xml .= "<STRAS>rua itororó</STRAS>";
$xml .= "<HOUSE_NUM1>81</HOUSE_NUM1>";
$xml .= "<HOUSE_NUM2>301</HOUSE_NUM2>";
$xml .= "<ORT02>Menino Deus</ORT02>";
$xml .= "<PSTLZ>90110290</PSTLZ>";
$xml .= "<REGIO>RS</REGIO>";
$xml .= "<ORT01>Porto Alegre</ORT01>";
$xml .= "<TELF1>32335675</TELF1>";
$xml .= "<TELFX>32335675</TELFX>";
$xml .= "<SMTP_ADDR>teste#teste.com</SMTP_ADDR>";
$xml .= "<ERDAT>2016-10-04</ERDAT>";
$xml .= "<ChangeData>2016-10-04</ChangeData>";
$xml .= "<StartData>2016-10-04</StartData>";
$xml .= "<OffData>2016-10-04</OffData>";
$xml .= "</fornecedor>";
$result = $client->PersonImport("login","password", $xml);
echo $result;
The line
$xml .= "<STRAS>rua itororó</STRAS>";
has a special character. If I remove the 'ó' character it works.
I tried to set encoding on xml:
$xml = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>";
This worked for me when I had to parse xml with SimpleXML Parser, but it didn't work on soap.
I tried to set header of the page for utf8 or ISO-8859-1 like this:
header("Content-type:text/html; charset=UTF-8");
or:
header ('Content-type: text/html; charset=ISO-8859-1');
I tried to use htmlentities, but the entity for 'ó' is '& o a c u t e;' which has the special character '&' and then the same problem happens.
function serialize didn't resolve the problem.
I couldn't find an answer until now on google.
Is it possible to pass latin special characters using nusoap? There must be a way.
Looks like I found a way. Using CDATA I can escape the '&', so I can use htmlentities on strings, like this:
$xml .= "<STRAS><![CDATA[".htmlentities("Rua Itororó")."]]></STRAS>";
I finally got my xml-(pre-)parsing-script ready. It parses and checks each element, and saves a amount of elements to a new xml-file.
My "problem" is that in the new xml-file all is written unformatted and without linebreaks.
while ($xml = $chunk->read()) {
$obj = simplexml_load_string($xml);
// check if ID is in Array
if(!in_array((string)$obj->id, $ids)) {
$chunkCount++;
$xmlData .= '<product>';
foreach($obj as $key => $value) {
$xmlData .= '<'.$key.'>'.$value.'</'.$key.'>';
}
$xmlData .= '</product>\n';
// if $chunkLimit is reached, save to file
if($chunkCount == $chunkLimit) {
$xp = fopen($file = "slices/slice_".$sliceCount.".xml", "w");
fwrite($xp, '<?xml version="1.0" ?>'."");
fwrite($xp, "<item>");
fwrite($xp, $xmlData);
fwrite($xp, "</item>");
fclose($xp);
print "Written ".$file."<br>";
$xmlData = '';
$chunkCount = 0;
$sliceCount++;
}
}
}
How could I get my xml-slices look good, with linebreaks? .. I already tried \nbut it simply writes \n to the new file.
The trick is to use " instead of ' for special characters to be parsed as special.
so
$xmlData .= '</product>\n';
should be
$xmlData .= "</product>\n";
You can also use \t for tabs, if you want indentation!
Use special chars \n and \t for tabulations.
So:
fwrite($xp, "<item>\n");
fwrite($xp, "\t" . $xmlData."\n");
fwrite($xp, "</item>\n");
I see some code like this in PHP
public function fetch()
{
$xml = '';
$xml .= '<' . '?xml version="1.0" encoding="utf-8"?' . '>' . "\n";
$xml .= '<rss version="2.0">';
$xml .= '<channel>';
$xml .= '<title>TEST</title>';
$xml .= '<description>TEST</description>';
foreach ($this->items as $item)
{
$xml .= '<item>';
$xml .= '<title>' . $item['title'] . '</title>';
$xml .= '<description>' . $item['body'] . '</description>';
$xml .= '</item>';
}
$xml .= '</channel>';
$xml .= '</rss>';
return $xml;
}
The code use a lots of stings concat (.=), do you think it is not a good way to do it ?
It look like will case unnecessary memory usage for me.
Those code was a part of "VIEW' of MCV, the function has already get the processed data in a array of "items". And the function is going to make the render.
Will you agree instead of
echo $this->fetch();
using a template file is better ? like this :
include('template.php');
and then in template.php :
<?xml version="1.0" encoding="utf-8">
<rss version="2.0">
<channel>
<title>TEST</title>
<description>TEST</description>
<?
foreach ($this->items as $item){
echo '<item>';
echo '<title>' . $item['title'] . '</title>';
echo '<description>' . $item['body'] . '</description>';
echo '</item>';
}
?>
</channel>
</rss>
I think the second approach would be better. Do you agree? or any other comment ?
Edit :
A user point out that using a template has it's lack too. So, when will you using the the template and when will not ? (those tutorials just always tell me i can use template anyways, i got a little confuse.)
Using a template is not necessarily better since it is an I/O operation (and I/O operation are often costly).
The concatenation in comparison is several times more performant. You could either remove the unnecessary concatenations (like the '<' . '?xml' part) or use HEREDOC / NOWDOC (http://php.net/manual/fr/language.types.string.php).
At the end of the day, it's mostly up to the developper's choice as long as the application is not purely performance-driven.
EDIT: as stated in comments, using an XML reader / writer class would prove more robust and increase maintainability.
This snippet of code use to work perfectly, nothing has changed except now it's giving off errors.
function wrapOutput($str){
header('content-type: text/xml; charset: utf-8');
$o = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
$o .= ' <rss version="2.0"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:amp="http://www.adobe.com/amp/1.0">' . PHP_EOL;
$o .= ' <channel>' . PHP_EOL;
$o .= $str;
$o .= ' </channel>' . PHP_EOL;
$o .= ' </rss>' . PHP_EOL;
return $o;
}
Something is going wrong and turning the xml tags into <'xml version="1.0" encoding="UTF-8"'>
Which results into the following error
XML Parsing Error: not well-formed
Location: http://localhost/mrss.php?feed=test
Line Number 1, Column 2:<'xml version="1.0" encoding="UTF-8"'>
-^
I think the problem is de quotes, beacause XML read like eval(), sou u can try escape \"\" quotes