Format XML Document created with PHP - DOMDocument - php

I am trying to format visually how my XML file looks when it is output. Right now if you go here and view the source you will see what the file looks like.
The PHP I have that creates the file is: (Note, $links_array is an array of urls)
header('Content-Type: text/xml');
$sitemap = new DOMDocument;
// create root element
$root = $sitemap->createElement("urlset");
$sitemap->appendChild($root);
$root_attr = $sitemap->createAttribute('xmlns');
$root->appendChild($root_attr);
$root_attr_text = $sitemap->createTextNode('http://www.sitemaps.org/schemas/sitemap/0.9');
$root_attr->appendChild($root_attr_text);
foreach($links_array as $http_url){
// create child element
$url = $sitemap->createElement("url");
$root->appendChild($url);
$loc = $sitemap->createElement("loc");
$lastmod = $sitemap->createElement("lastmod");
$changefreq = $sitemap->createElement("changefreq");
$url->appendChild($loc);
$url_text = $sitemap->createTextNode($http_url);
$loc->appendChild($url_text);
$url->appendChild($lastmod);
$lastmod_text = $sitemap->createTextNode(date("Y-m-d"));
$lastmod->appendChild($lastmod_text);
$url->appendChild($changefreq);
$changefreq_text = $sitemap->createTextNode("weekly");
$changefreq->appendChild($changefreq_text);
}
$file = "sitemap.xml";
$fh = fopen($file, 'w') or die("Can't open the sitemap file.");
fwrite($fh, $sitemap->saveXML());
fclose($fh);
}
As you can tell by looking at the source, the file isn't as readable as I would like it to be. Is there any way for me to format the nodes?
Thanks,
Levi

Checkout the formatOutput setting in DOMDocument.
$sitemap->formatOutput = true

not just PHP, there is a stylesheet for XML: XSLT, which can format XML into sth looks good.

Related

Adding xml node on top of file or reverse the loop

I am using xml. Reading the xml-document works fine, adding nodes works fine to but I want the node to add on top of the xml file. Is this possible or is this a nogo?
The reason I want this is because when I display the xml file I want the last added node, displayed as the newest one, on top.
I display the xml with this loop:
foreach($xml->xpath("//user[#id='12345678']") as $user){
foreach($user->children() as $action => $data){
echo"<li>";
echo $data->content;
echo $data->date;
echo"</li>";
}
}
If there is a way to reverse the loop or another way I'm fine with that to, it doesn't have to be adding the first node on top. Below are the file how I add the node and the structure of the xml-file.
Does anyone have an idea how to solve this?
addxml.php
<?php
$file = "actielijst.xml";
$fp = fopen($file, "rb") or die("cannot open file");
$str = fread($fp, filesize($file));
$xml = new DOMDocument();
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$xml->loadXML($str) or die("Error");
// get document element
echo "<xmp>OLD:\n". $xml->saveXML() ."</xmp>";
$root = $xml->documentElement;
$content = $xml->createElement("content");
$contentText = $xml->createTextNode("Nieuwe Factuur Mei");
$content->appendChild($contentText);
$date = $xml->createElement("date");
$dateText = $xml->createTextNode("23-12-2010");
$date->appendChild($dateText);
$action = $xml->createElement("action");
$action->appendChild($date);
$action->appendChild($content);
$root->appendChild($action);
$xml->save("actielijst.xml") or die("Error");
?>
actielijst.xml
<?xml version="1.0"?>
<userid>
-------> Insert new action here <------
<action>
<date>23-01-2010</date>
<content>nieuwe factuur</content>
</action>
<action>
<date>23-01-2010</date>
<content>karten op 01-02</content>
</action>
</userid>
You can use xpath to capture every parent node (action in your case) and then reverse the array...
$users_arr = array_reverse($xml->xpath("action"));
Now you can loop through this array!
This will helps
<?php
$file = "actielijst.xml";
$fp = fopen($file, "rb") or die("cannot open file");
$str = fread($fp, filesize($file));
$xml = simplexml_load_string($str);
$action = $xml->addChild('action');
$action->addChild('content','sundar');
$action->addChild('date','23-12-2010');
header('content-type: application/xml');
echo $xml->saveXML();

Adding data from php/mysql query into an XML file

I want to add/display data from querying from the database and add it into an XML file.
Example, I have a table_persons which has a name and age. I create a mysql query to get its name and age. Then simply put the data(name and age of persons) into an XML file.
How would you do that? Or is it possible?
I suggest you use DomDocument and file_put_contents to create your XML file.
Something like this:
// Create XML document
$doc = new DomDocument('1.0', 'UTF-8');
// Create root node
$root = $doc->createElement('persons');
$root = $doc->appendChild($root);
while ($row = mysql_fetch_assoc($result)) {
// add node for each row
$node = $doc->createElement('person');
$node = $root->appendChild($node);
foreach ($row as $column => $value) {
$columnElement = $doc->createElement($column);
$columnElement = $node->appendChild($columnElement);
$columnValue = $doc->createTextNode($value);
$columnValue = $columnElement->appendChild($columnValue);
}
}
// Complete XML document
$doc->formatOutput = true;
$xmlContent = $doc->saveXML();
// Save to file
file_put_contents('persons.xml', $xmlContent);
<?php
[snip] //database code here
$f = fopen('myxml.xml', 'a+');
foreach($row = mysqli_fetch_assoc($resultFromQuery))
{
$str = "<person>
<name>{$row['name']}</name>
<age>{$row['age']}</age>
</person>\n";
fwrite($f, $str);
}
fclose($f);
?>
Assuming you use mysqli, this code works. If not, suit to fit. In the fopen function call, the a+ tells it to open it for reading at writing, placing the pointer at the end of the file.
Best of luck.

SQL data to XML file

Is it possible to save the below output to an XML file as its currently just displayed in the source?
$host = "localhost"; // host name
$user = "#"; // database user name
$pass = "#"; // database password
$database = "#"; // database name
// connecting to database
$connect = #mysql_connect($host,$user,$pass)or die (#mysql_error());
// selecting database
#mysql_select_db($database,$connect) or die (#mysql_error());
// default header(don't delete)
header("Content-Type: text/xml;charset=iso-8859-1");
echo '<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
// mytable = your content table name
$query = #mysql_query("SELECT * FROM urls");
while($row = #mysql_fetch_array($query)){
// [url] = content url
$url = $row['url'];
// [time] = content date
$date = date("Y-m-d", $row['time']);
// NO CHANGES BELOW
echo
'<url>
<loc>' . $url .'</loc>
<lastmod>'. $date .'</lastmod>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
';
}
echo '</urlset>';
I know I can use .htaccess to make the file be seen as an XML format however I want the data to be saved onto an actual file.
You could try changing each echo to append the line to a string variable, for example:
// Instead of
echo '<?xml version="1.0"?>';
echo '<url>';
// etc.
$xml = '<?xml version="1.0"?>';
$xml .= '<url>';
// and so on
Then use one of the file functions to save to a file. file_put_contents is a simple method:
file_put_contents("/path/to/file.xml", $xml);
A more robust solution, if you want to take this further, could be to use the DOM module to build the XML structure:
$document = new DOMDocument("1.0");
$root = $document->createElement("urlset");
$root->setAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");
$document->appendChild($root);
while ($row = mysql_query($query)) {
$item = $document->createElement("url");
$root->append($item);
// etc.
}
echo $document->saveXML();
NOTE: This answer assumes that by "save file" you mean "trigger the Save As dialog in the browser when someone views the page".
text/xml isn't really the correct content-type. You really should at least application/xml for generic XML or the appropriate content type for XML sub-formats such as RSS or docx.
If you want to trigger a file download dialog in the client browser, then you also need to send a content-disposition header that tells the browser that you want it to download the file and give a preferred filename.
There are some issues with your code that need addressing too.
Overuse of # for error suppression. This is a bad idea for a huge variety of reasons. Remove the # operators and handle any generated errors in a more robust way.
Your character encoding heading specifies one character set (latin-1) but your XML preamble specifies a totally different one (UTF-8). That's a recipe for disaster.
Use output buffers
ob_start();
... do everything you actually did before ...
$content = ob_get_contents();
ob_end_clean();
//Write to a file
file_put_contents('filename.xml', $content);
And thats all...
Using fwrite it should be straight forward :
$f = fopen('data.xml', 'w'); //open a file for writing
fwrite($f, $myxmltext); // write some things to it
fclose($f); // close it when finished

Read XML data and write to new file with PHP

I may be over thinking this but are there any extra steps I am missing after reading my XML data into a string and before writing it to a local file?
header('Content-type: text/xml');
//MY URL TO A XML PAGE STYLED WITH XML STYLE SHEET
$url = "http://www.mywebsite.com/somexmlfile.xml";
//SAVE CONTENTS OF PAGE IN XML_DATA
$xml_data = file_get_contents($url);
//REMOVE STYLE SHEET INFO
$search2 = '<?xml-stylesheet href="latest_ob.xsl" type="text/xsl"?>';
$xml_data = str_replace( $search2, "", $xml_data);
//WRITE MY DATA TO A BACKUP FILE AND THEN ECHO TO THE SCREEN FOR A FLASH APP CALLING THE INFO
$myFile = "data_backup.xml";
$fh = fopen($myFile, 'w') or die("can't open file");
$stringData = $xml_data;
fwrite($fh, $stringData);
fclose($fh);
echo $xml_data;
The reason I ask this is when I try opening my backup XML file in Dreamweaver it crashes everytime. I was thinking there could be an encoding issue possible.

Problem with loading remote XML file

I'm trying to load a remote xml file using php.
This is my code:
$doc = new DOMDocument();
$doc->load($this->xml_file);
$file = $doc->getElementsByTagName('file');
$totalFiles = $file->length;
echo $totalFiles;
The remote xml file link is:
http://localhost/script/index.php?act=xml
This is the code in index.php:
$xml = '<?xml version="1.0"?><MultimediaGallery>';
$query = mysql_query('SELECT `id`,`image`,`desc` FROM `'
.confitem('database','prefix').'table` ORDER BY `id` DESC LIMIT '
.$start.','.$limit);
while($result = mysql_fetch_array($query))
{
$img = unserialize($result['image']);
$desc = unserialize($result['desc']);
$xml .= '<file type="photo"><thumb>'
.settings('site','url').'/'.OPATH_APPFOLDER.'/'
.OPATH_UPFOLDER.'/wallpapers/thumbs/'.$img[0].'</thumb><source>'
.settings('site','url')
.'/'.OPATH_APPFOLDER.'/'.OPATH_UPFOLDER
.'/wallpapers/'.$img[0].'</source><description>'
.$desc[$_SESSION['languagecode']].'</description></file>';
}
$xml .= '</MultimediaGallery>';
header("content-type: text/xml");
echo $xml;
When I visit this xml file link direct in the browser .. it's output to me xml file with this style :
<?xml version="1.0"?><MultimediaGallery><file type="photo"><thumb>http://localhost/script/application/data/wallpapers/thumbs/1116205566_42ce0841ab_s.jpg</thumb><source>http://localhost/script/application/data/wallpapers/1116205566_42ce0841ab_s.jpg</source><description>dfdfdfdf</description></file></MultimediaGallery>
When I execute the xml function which uses the dom to load the xml file I get this error:
Warning: DOMDocument::load()
[domdocument.load]: Extra content at
the end of the document in
http://localhost/script/index.php,
line: 2 in
C:\AppServ\www\script\application\libraries\wallpapers\multimedia.class.php
on line 46
Why is this happening?
Update:
I used dom to create the xml instead:
$xml = new DOMDocument('1.0');
$root = $xml->createElement('MultimediaGallery');
$xml->appendChild($root);
$query = mysql_query('SELECT `id`,`image`,`desc` FROM `'.confitem('database','prefix').'backgrounds` ORDER BY `id` DESC LIMIT '.$start.','.$limit);
while($result = mysql_fetch_array($query))
{
$img = unserialize($result['image']);
$desc = unserialize($result['desc']);
$element = $xml->createElement('file');
$root->appendChild($element);
$attr = $xml->createAttribute('type');
$element->appendChild($attr);
$attr_text = $xml->createTextNode('photo');
$attr->appendChild($attr_text);
$thumb = $xml->createElement('thumb');
$element->appendChild($thumb);
$thumb_text = $xml->createTextNode(settings('site','url').'/'.OPATH_APPFOLDER.'/'.OPATH_UPFOLDER.'/wallpapers/thumbs/'.$img[0]);
$thumb->appendChild($thumb_text);
$source = $xml->createElement('source');
$element->appendChild($source);
$source_text = $xml->createTextNode(settings('site','url').'/'.OPATH_APPFOLDER.'/'.OPATH_UPFOLDER.'/wallpapers/'.$img[0]);
$source->appendChild($source_text);
$description = $xml->createElement('description');
$element->appendChild($description);
$description_text = $xml->createTextNode($desc[$_SESSION['languagecode']]);
$description->appendChild($description_text);
}
header("content-type: text/xml");
echo $xml->saveXML();
But it still gives me the same error. I noticed some thing though, I tried to copy my output xml and save it in a file and read it using the dom parser and the result was that it's read successfully.
But when I try parsing the xml output by the php file then it throws an error.
Your XML is not well-formed. E.g there is something wrong with it.
Try to avoid making XML by concatenating strings because this will happen. You can use DomDocument you make XML as well as read it and manipulate it.
Make sure you have no leading or trailing white space in your XML generating script.
You should also be using CDATA

Categories