Creating/Writing an XML file in PHP? - php

I currently have a script written in PHP where I connect to a database in phpMyAdmin, and then parse all of the table values into an XML document.
Here is how the script works:
$xmlBody .= "<XML>";
$sql_news = mysql_query("SELECT * FROM news_table");
$xmlBody .= "<News_Table>";
//this while loop churns out the values of our "news_table" table
while($row_news = mysql_fetch_array($sql_news)){
// Set DB variables into local variables for easier use
$id_news = $row_news["news_id"];
$author_news = $row_news["news_author"];
$time_news = $row_news["news_time"];
$title_news = $row_news["news_title"];
$content_news = $row_news["news_content"];
$desc_news = $row_news["news_description"];
$image_news = $row_news["news_image"];
$xmlBody .= '
<News_Table_Entry>
<DataID>' . $id_news . '</DataID>
<DataAuthor>' . $author_news . '</DataAuthor>
<DataTime>' . $time_news . '</DataTime>
<DataTitle>' . $title_news . '</DataTitle>
<DataContent>' . $content_news . '</DataContent>
<DataDesc>' . $desc_news . '</DataDesc>
<DataImage>' . $image_news . '</DataImage>
</News_Table_Entry>';
} // End while loop
$xmlBody .= "</News_Table>";
mysql_close(); // close the mysql database connection
$xmlBody .= "</XML>";
echo $xmlBody;
?>
How do I create and output this as an external XML file? I've successfully got this script working, but using all of the methods for writing out to XML isn't working. Using the
echo 'Wrote: ' . $doc->save("/tmp/test.xml") . ' bytes'; // Wrote: 72 bytes
Function isn't working, along with the fwrite function as well. I've been working at trying to figure this out for a few days, but none of the solutions I've been told to try out have worked. Any help or insight would be greatly appreciated!

According to your code, you're already building the XML content yourself. XML files are just regular text files, so in this case you don't need any of the special XML functions that validate and render. Instead, you can simply save your text to the .xml file:
file_put_contents('/tmp/test.xml', $xmlBody);
file_put_contents allows you to forego all the fopen/fwrite functions, so it's the easiest way to write content to disk.
On the other hand, if you do want to learn to build a structured XML document with all the bells and whistles of consistency, look up SimpleXML or XMLWriter. A little more overhead that way, but doing all the markup by hand can be unwieldy, especially when one typo can invalidate your whole document.

This will help you
$xml_msg_in = fopen('/tmp/test.xml',"w");
fwrite($xml_msg_in,$xmlBody);
fclose($xml_msg_in);

Have you tried file_put_contents('/path/to/output.xml', $xmlBody);

Just to understand, does your echo $xmlBody; line at least work as expected?
And if you are trying to use the XML file somewhere without success, then note you're missing the XML header as the first line of the XML file.
<?xml version="1.0"?>
Note that depending on the data in your database, this header may need to specify a wider encoding such as UTF-16. But you should choose what character sets you want to allow in that database.
<?xml version="1.0" encoding="UTF-16"?>
And what is the trailing ?> at the end of your code sample?

Related

Laravel: Parsing XML with SimpleXML namespace issue [duplicate]

This question has two parts.
Part 1. Yesterday I had some code which would echo the entire content of the XML from an RSS feed. Then I deleted it from my php document, saved over it, and I am totally kicking myself.
I believe the syntax went something like this:
$xml = simplexml_load_file($url);
echo $xml;
I tried that again and it is not working, so apparently I forgot the correct syntax and could use your help, dear stackoverflow question answerers.
I keep trying to figure out what I was doing and I am unable to find an example on Google or the PHP site. I tried the print_r($url); command, and it gives me what appears to be an atomized version of the feed. I want the whole string, warts and all. I realize that I could just type the RSS link into the window and see it, but it was helpful to have it on my PHP page as I am coding and noding.
Part 2 The main reason I wanted to reconstruct this is because I am trying to parse nodes off a blog RSS in order to display it on a webpage hosted on a private domain. I posted a dummy blog and discovered an awkward formatting glitch when I failed to add a title to one of the dummy posts.
So what does one do in this situation? I tried a little:
if(entry->title == "")
{$entryTitle = "untitled";}
That did not work at all.
Here's my entire php script for the handling of the blog:
<?php
/*create variables*/
$subtitle ="";
$entryTitle="";
$html = "";
$pubDate ="";
/*Store RSS feed address in new variable*/
$url = "http://www.blogger.com/feeds/6552111825067891333/posts/default";
/*Retrieve BLOG XML and store it in PHP object*/
$xml = simplexml_load_file($url);
print_r($xml);
/*Parse blog subtitle into HTML and echo it on the page*/
$subtitle .= "<h2 class='blog'>" . $xml->subtitle . "</h2><br />";
echo $subtitle;
/*Go through all the entries and parse them into HTML*/
foreach($xml->entry as $entry){
/*retrieve publication date*/
$xmlDate = $entry->published;
/*Convert XML timestamp into PHP timestamp*/
$phpDate = new DateTime(substr($xmlDate,0,19));
/*Format PHP timestamp to something humans understand*/
$pubDate .= $phpDate->format('l\, F j\, Y h:i A');
if ($entry->title == "")
{
$entryTitle .= "Untitled";
}
echo $entry->title;
/*Pick through each entry and parse each XML tree node into an HTML ready blog post*/
$html .= "<h3 class='blog'>".$entry->title . "<span class='pubDate'> | " .$pubDate . "</span></h3><p class='blog'>" . $entry->content . "</p>";
/*Print the HTML to the web page*/
echo $html;
/*Set the variables back to empty strings so they do not repeat data upon reiteration*/
$html = "";
$pubDate = "";
}
?>
According to the php manual:
$xml = new SimpleXMLElement($string);
.
.
.
then if you want to echo the result:
echo $xml->asXML();
or save the xml to a file:
$xml->asXML('blog.xml');
References
http://php.net/manual/fr/simplexmlelement.asxml.php
http://spotlesswebdesign.com/blog.php?id=14
Part 1
This is still not exactly what I wanted, but rather a very tidy and organized way of echoing the xml data:
$url = "http://www.blogger.com/feeds/6552111825067891333/posts/default";
$xml = simplexml_load_file($url);
echo '<pre>';
print_r($xml);
Part 2
I had to get firephp running so I could see exactly what elements php was encountering when it reached an entry without a blog title. Ultimately it is an empty array. Therefore, the simple:
if(empty($entry->title))
works perfectly. For string comparison, I found that you can simply cast it as a string. For my purposes, that was unnecessary.
The simplexml_load_file returns an SimpleXMLElement, so:
print_r($xml);
will show its minor objects and arrays.
After your tweaks you can call $xml->asXML("filename.xml"); as #Tim Withers pointed out.
Part 1: echo $xml->asXML(); - http://www.php.net/manual/en/simplexmlelement.asxml.php
Part 2: php SimpleXML check if a child exists
$html .= "<h3 class='blog'>".($entry->title!=null?$entry->title:'No Title')
. "<span class='pubDate'> | " .$pubDate . "</span></h3><p class='blog'>"
. $entry->content . "</p>";
Note I would probably load the url like this:
$feedUrl = 'http://www.blogger.com/feeds/6552111825067891333/posts/default';
$rawFeed = file_get_contents($feedUrl);
$xml = new SimpleXmlElement($rawFeed);
Based on your comment in regards to part 1, I am not sure if the XML is being loaded completely. If you try loading it this way, it should display all the XML data.

PHP encoding problems

After a webhook (XML) trigger, I have a PHP code doing the following treatment:
$xmlData = fopen('php://input' , 'rb');
while (!feof($xmlData)) { $xmlString .= fread($xmlData, 4096); }
fclose($xmlData);
file_put_contents('orders/order' . date('m-d-y') . '-' . time() . '.xml', $xmlString, FILE_APPEND);
And I also transfer this info to a database:
$xml = new SimpleXMLElement($xmlString);
$address1 = trim($xml->{'billing-address'}->address1);
$sql="INSERT INTO `Customers`(`address1`)
VALUES
('$address1')";
My problem is that character is not properly transported for the xml file and the database.
Original statement:
São Paulo
XML file saved on the server:
<?xml version="1.0" encoding="UTF-8"?>
<address1>São Paulo</address1>
Information on database (utf8_general_ci):
São Paulo
Everything seems to be proper set to UTF-8 but I still have this character problems.
When you establish database connection run the query:
SET NAMES 'utf8
That should help. Also make sure the data coming from your "web hook" is in that format.
I think the php functions you are using are not intended to manage multibytes string. Try putting
mb_internal_encoding("UTF-8");
at the beginning of your php code and have a look to the Multibyte String Functions page on php.net to understand if you need to change some function in favour of its corresponding multibyte version.
As a last chance you might try to iconv the string before inserting it to the database:
$address1 = trim($xml->{'billing-address'}->address1);
$address1 = iconv(iconv_get_encoding($string), "UTF-8", $address1);

Ampersands in database

I am trying to write a php function that goes to my database and pulls a list of URLS and arranges them into an xml structure and creates an xml file.
Problem is, Some of these urls will contain an ampersand that ARE HTML encoded. So, the database is good, but currently, when my function tries to grab these URLS, the script will stop at the ampersands and not finish.
One example link from database:
http://www.mysite.com/myfile.php?select=on&league_id=8&sport=15
function buildXML($con) {
//build xml file
$sql = "SELECT * FROM url_links";
$res = mysql_query($sql,$con);
$gameArray = array ();
while ($row = mysql_fetch_array($res))
{
array_push($row['form_link']);
}
$xml = '<?xml version="1.0" encoding="utf-8"?><channel>';
foreach ($gameArray as $link)
{
$xml .= "<item><link>".$link."</link></item>";
}
$xml .= '</channel>';
file_put_contents('../xml/full_rankings.xml',$xml);
}
mysql_close($con);
session_write_close();
If i need to alter the links in the database, that can be done.
You can use PHP's html_entity_decode() on the $link to convert & back to &.
In your XML, you could also wrap the link in <![CDATA[]]> to allow it to contain the characters.
$xml .= "<item><link><![CDATA[" . html_entity_decode($link) . "]]></link></item>";
UPDATE
Just noticed you're actually not putting anything into the $gameArray:
array_push($row['form_link']);
Try:
$gameArray[] = $row['form_link'];
* #Musa looks to have noticed it first, for due credit.
Look at this line
array_push($row['form_link']);
you never put anything in the $gameArray array, it should be
array_push($gameArray, $row['form_link']);
You need to use htmlspecialchars_decode. It will decode any encoded special characters in string passed to it.
This is most likely what you are looking for:
http://www.php.net/manual/en/function.mysql-real-escape-string.php
Read the documentation, there are examples at the bottom of the page...
'&' in oracleSQL and MySQL are used in queries as a logical operator which is why it is tossing an error.
You may also want to decode the HTML...

Cache PHP Output

I have a file called api.php which is loaded using parameters, for example:
api.php?name=NAME&format=xml
which would return a xml page with some data, or
api.php?name=NAME&format=JSON would return the same data in json format.
The xml page is generated using this:
function generate_valid_xml_from_array($array, $node_block='xboxapi', $node_name='game') {
$xml = '<?xml version="1.0" encoding="UTF-8" ?>' . "\n";
$xml .= '<' . $node_block . '>' . "\n";
$xml .= generate_xml_from_array($array, $node_name);
$xml .= '</' . $node_block . '>' . "\n";
return $xml;
}
$xml = generate_valid_xml_from_array($array);
header('Content-type: text/xml');
print $xml;
and the json is returned using this:
header('Content-type: application/json');
echo json_encode($data);
How would i set the returned data to be cached for 1 hour, and then updated hourly on request?
I have been scratching my head with this one for a while now
You can use a filesystem cache for your needs. Here is a link to an article describing the creation of a simple cache class:
http://devgrow.com/simple-cache-class/
Another possibility would be to use the Zend Cache classes from the Zend Framework, for more information look at the introduction chapter of the component in the Zend Framework manual:
http://framework.zend.com/manual/en/zend.cache.introduction.html
And if you Google for 'PHP cache class' you will get a lot of other possibilities you can check.
You could store it in a file or in your database together with information about the creation time. If someone queries it you check if the creation time is more than 60 minutes in the past. If not return your cached value, if it is too old rebuild your value, save it and return it afterwards.

php and simpleXml - how to change node contents

I'm trying to change the contents of a node in an XML file using simpleXML. I know that the variable for the new node-contents contains the right stuff, but for some reason the file isn't changed when it is saved. I'm probably missing something basic, because I'm new to simpleXML. Here is the whole php script:
<?php
$doc=$_REQUEST["book"];
$div1=$_REQUEST["div1"];
$div2=$_REQUEST["div2"];
if ($div1=="") $div1=$_REQUEST["chapter"];
if ($div2=="") $div2=$_REQUEST["verse"];
$div3=$_REQUEST["div3"];
$textresponse=$_REQUEST["xmltext"];
$strippedresponse = "<?xml version='1.0'?>" . stripslashes($textresponse);
echo("Saved changes to " . $doc . " " . $div1 . "." . $div2 ."<br />");
$fileName="/home/ocp/public_html/sites/default/docs/drafts/".$doc.".xml";
$xmlDoc = simplexml_load_file($fileName);
$backupFileName="/home/ocp/public_html/sites/default/docs/backups/".$doc." ".date("Y-m-d H.i.s").".xml";
file_put_contents($backupFileName, $xmlDoc->asXML());
$backupSize = filesize($backupFileName);
echo("Backup {$backupFileName} created:".$backupSize." bytes<br />");
if ($doc) {
if ($div1) {
if ($div2) {
$newVerse = simplexml_load_string($strippedresponse);
$oldVerse = $xmlDoc->xpath("//div[#number='".$div1."']/div[#number='".$div2."']");
$oldVerse = $newVerse;
$newDoc = $xmlDoc->asXml();
file_put_contents($fileName, $newDoc);
$newSize = filesize($fileName);
echo("New file is ".$newSize." bytes <br />");
}
}
}
?>
I'll venture to say that this code certainly doesn't do what you want it to:
$newVerse = simplexml_load_string($strippedresponse);
$oldVerse = $xmlDoc->xpath("//div[#number='".$div1."']/div[#number='".$div2."']");
$oldVerse = $newVerse;
Changing the value of a PHP variable has no side-effects. In other word, nothing happens when you do $a = $b; except in some specific cases, and it's not one of them.
I don't know what you really want to achieve with this code. If you want to replace the (X)HTML inside a specific <div/> you will need to use DOM and create a DOMDocumentFragment, use appendXML() to populate it then substitute it to your old <div/>. Either that or create a new DOMDocument, loadXML() then importNode() to your old document and replaceChild() your old div.
SimpleXMLElement::xpath returns an array of SimpleXMLElement objects. Copies, not references. So $oldVerse = $newVerse; does not change $xmlDoc in any way.
SimpleXML is sufficient to read XML, for manipulation you might want to choose a more powerful alternative from http://www.php.net/manual/de/refs.xml.php, e.g. DOM.

Categories