Will string concat case performant issue in PHP? - php

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.

Related

saving an output to .xml format

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);

Issues with API's XML PHP parsing

I am using an API however the way that they setup their returned XML is incorrect so I am needing to come up with a solution for parsing it. i am unable to convert to JSON (my preferred return method) because they don't support it. Below I have listed my XML and PHP.
XML Returned by API
<?xml version="1.0" encoding="utf-8"?>
<interface-response>
<Domain>example.com</Domain>
<Code>211</Code>
<Domain>example.net</Domain>
<Code>210</Code>
<Domain>example.org</Domain>
<Code>211</Code>
</interface-response>
Each Code is for the previous domain. I have no idea how to tie these two together and still be able to loop through all of the results returned. There will essentially be one Domain and one Code returned for each Top Level Domain, so a lot of results.
PHP code so far:
<?php
$xml = new SimpleXMLElement($data);
$html .= '<table>';
foreach($xml->children() as $children){
$html .= '<tr>';
$html .= '<td>'.$xml->Domain.'</td>';
if($xml->Code == 211){
$html .= '<td>This domain is not avaliable.</td>';
}elseif($xml->Code == 210){
$html .= '<td>This domain is avaliable.</td>';
}else{
$html .= '<td>I have no idea.</td>';
}
$html .= '<tr>';
}
$html .= '</table>';
echo $html;
?>
If you don't want to deal with crappy XML (I'm not saying XML is crappy in general, but this one is) you could consider something like this:
<?php
$responses = [];
$responses['210'] = 'This domain is avaliable.';
$responses['211'] = 'This domain is not avaliable.';
$xml = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<interface-response>
<Domain>example.com</Domain>
<Code>211</Code>
<Domain>example.net</Domain>
<Code>210</Code>
<Domain>example.org</Domain>
<Code>211</Code>
</interface-response>
XML;
$data = (array) simplexml_load_string($xml);
$c = count($data['Domain']);
for($i = 0; $i < $c; $i++)
{
echo $data['Domain'][$i], PHP_EOL;
echo array_key_exists($data['Code'][$i], $responses) ? $responses[$data['Code'][$i]] : 'I have no idea', PHP_EOL;
}
Output
example.com
This domain is not avaliable.
example.net
This domain is avaliable.
example.org
This domain is not avaliable.

XML Parsing Error: not well-formed, opening xml tags

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

XML source generated by PHP is messy [duplicate]

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.

Google Chrome rendering XML as text for RSS feed

I have this script to generate an XML file for an RSS feed. Works great in every browser except Chrome. Chrome just renders the XML as text. Something to do with header("Content-Type: application/rss+xml; charset=ISO-8859-1"); possibly?
This is the code I'm using:
<?php
$linkUp = "http://localhost/sites/myBlog/";
header("Content-Type: application/rss+xml; charset=ISO-8859-1");
$rssfeed = '<?xml version="1.0" encoding="ISO-8859-1"?>';
$rssfeed .= '<rss version="2.0">';
$rssfeed .= '<channel>';
$rssfeed .= '<title>Mytitle</title>';
$rssfeed .= '<link>' . $linkUp . '</link>';
$rssfeed .= '<description>Mydescription</description>';
$rssfeed .= '<language>en-us</language>';
$rssfeed .= '<copyright>© ' . strftime('%Y') . ' . " " . ' . $linkUp . '</copyright>';
$query = "SELECT * FROM rss";
$result = $db->query($query);
while($row = $db->fetch_array($result)) {
$rssfeed .= '<item>';
$rssfeed .= '<title>' . $row['rss_title'] . '</title>';
$rssfeed .= '<description>' . $row['rss_description'] . '</description>';
$rssfeed .= '<link>' . $row['rss_link'] . '</link>';
$rssfeed .= '<pubDate>' . date("D, d M Y H:i:s O", strtotime($date)) . '</pubDate>';
$rssfeed .= '</item>';
}
$rssfeed .= '</channel>';
$rssfeed .= '</rss>';
echo $rssfeed;
?>
This is a known bug in chrome that has yet to be fixed, chrome does not display xml rss feeds with any formatting whatsoever.
Update: There is now an RSS subscription / reader extension for Chrome.
I had this same problem and I used "application/xml" and it fixed it right up. Chrome doesn't like "application/rss+xml".
Bottom line, RSS support isnt used by "majority" of users, and as such they are only implementing it as an extension, for now. The extension is available here:
RSS SubscriptionExtension
There's a detailed discussion of this on the closing comment for the bug - you can read the developer notes here:
Comment 149
Try changing the header to text/xml and see if it helps:
header("Content-Type: text/xml; charset=ISO-8859-1");
try the chrome extension "XML Tree"
Short answer: add "view-source:{feedurl}"
Note that when the url ends with .xml and is recognized as a feed by chrome, Chrome annoyingly opens a Save File dialog. But many feed urls don't end with an extension (i.e. .xml), such as:
http://feeds.feedburner.com/ScottHanselman
At root, that url is still a regular, xml feed, but for us coders who just want to see the real xml, Chrome and the others in this case show you a human readable display of the feed (very annoying!).
So the answer to both of these problems is contained in the comment above given by Arne Roomann-Kurrik. He should have put it as an answer, because it works!
view-source:http://feeds.feedburner.com/ScottHanselman
You don't even need "http://".

Categories