November 9th, 2009
PHP5 : SimpleXML Study Notes - 2

XML Summer School by psd @ flickr
Below are some of the notes I made while preparing for the Zend PHP5 exam. They are a quick memory jog of how SimpleXML works and its limitations.
The SimpleXML extension provides easier access to XML files. It is simpler to use but also much more limited than the DOM XML extension. If your document makes use of XML namespaces (ns:foo) then it is better NOT to use SimpleXML as it will become anything but simple.
SimpleXML only supports XML 1.0. If fed an XML 1.1 document it will show “Unsupported version ‘1.1′” warnings, but will continue and attempt to read the file.
Removing elements is not really supported and the opportunities for modification are limited. SimpleXML is best used for straightforward reading and using of XML files.
1. Documentation
http://php.net/manual/en/book.simplexml.php
2. Demo XML file
This example XML catalog.xml file looks really familiar.
<?xml version="1.0"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
<description>A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.</description>
</book>
</catalog>
3. Loading an XML file
There are four approaches to loading an XML file using SimpleXML.
3.1 Loading from a string
<?php
$xml = file_get_contents("catalog.xml");
$simple_xml_obj = simplexml_load_string($xml);
if ($simple_xml_obj !== FALSE) {
var_dump($simple_xml_obj);
} else {
echo "Invalid XML file" . PHP_EOL;
}
?>
3.2 Loading the XML file directly
<?php
$simple_xml_obj = simplexml_load_file("catalog.xml");
if ($simple_xml_obj !== FALSE) {
var_dump($simple_xml_obj);
} else {
echo "Invalid XML file" . PHP_EOL;
}
?>
3.3 Loading from a string using the SimpleXML constructor
If creating an SimpleXML instance from a string we need to be wary of possible exceptions.
<?php
$xml = file_get_contents("catalog.xml");
try {
$simple_xml_obj = new SimpleXMLElement($xml);
var_dump($simple_xml_obj);
}
catch (Exception $e) {
echo "Oops: " . $e->getMessage() . PHP_EOL;
}
?>
3.4 Loading the XML file directly with the class constructor
By setting the third parameter of the constructor (data_is_url) to true we can ask the class to directly load the XML file.
<?php
$filename = "catalog.xml";
try
{
$simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
var_dump($simple_xml_obj);
}
catch (Exception $e)
{
echo "Oops: " . $e->getMessage() . PHP_EOL;
}
?>
4. Usage examples
The benefit of SimpleXML over other solutions is that it makes accessing elements of the XML file EASY.
4.1 Stepping through the XML file by name
If you are familiar with the XML file and know the names of the elements you can refer directly to them in your code:
<?php
$filename = "catalog.xml";
$simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
foreach($simple_xml_obj->book as $book)
{
// Access attributes through a named array
echo "Book ID: {$book['id']}" . PHP_EOL;
// Access sub elements using ->
echo "Book Author: {$book->author}" . PHP_EOL;
echo "Book Title: {$book->title}" . PHP_EOL;
echo "Book Genre: {$book->genre}" . PHP_EOL;
echo "Book Price: {$book->price}" . PHP_EOL;
echo "Book Published date: {$book->publish_date}" . PHP_EOL;
echo "Book Description: {$book->description}" . PHP_EOL;
}
?>
4.2 Discovering the contents of the XML file
The children() method will returns an itterator of SimpleXMLElement elements containing each of the children. If used from the top node, this will allow you to step through the entire XML file. The attributes() method returns an iterator of key, value pairs containing all the attributes of the current XML tag.
<?php
/* Discover the contents of an XML file recursivly
*
* @param $input A SimpleXMLElement to discover
* @param $depth (optional) recursive dept, used for spacing
* @returns
*/
function DiscoverXML($xml,$depth = 0)
{
$spacing = str_repeat(' ',$depth);
// Show the name of the current node
echo $spacing . '<' . $xml->getName() . '>' ;
// Show the value of the current node, do this by casting the
// current element to a string.
echo trim((string) $xml);
// Show the attributes of the current node
foreach($xml->attributes() as $name => $value)
echo $spacing . " Atrribute {$name} = {$value}" . PHP_EOL;
// Go deeper and discover any child nodes
foreach($xml->children() as $child)
DiscoverXML($child,$depth+1);
// Close the current tag
echo $spacing . '</' . $xml->getName() . '>' . PHP_EOL;
}
$filename = "catalog.xml";
$simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
DiscoverXML($simple_xml_obj);
?>
4.3 Changing elements
Existing elements can be simply modified by assigning them a new value.
<?php
$filename = "catalog.xml";
$simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
$simple_xml_obj->book[0]->title = "Hello World";
$simple_xml_obj->book[1]->title = "Vampire Mania";
var_dump($simple_xml_obj);
?>
4.4 Adding a new element
<?php
$filename = "catalog.xml";
$simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
$book = $simple_xml_obj->addChild('book');
$book->addAttribute('id','1234');
$book->addChild('author','Vars Unlimited');
$book->addChild('title','PHP through the ages');
$book->addChild('genre','historical');
$book->addChild('price','10.95');
$book->addChild('publish date','2010-1-1');
$book->addChild('description','One of the finest examples of rewriting history');
var_dump($simple_xml_obj);
?>
4.5 Using XPath
XPath, the XML Path Language, is a query language for selecting nodes from an XML document. In the code below we locate all the prices. Note the ‘element/sub element/sub sub element’ notation.
<?php
$filename = "catalog.xml";
$simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
$search_result = $simple_xml_obj->xpath('/catalog/book/price');
foreach($search_result as $price)
echo $price . PHP_EOL;
?>
XPath is a query language — it allows you to select nodes based on criteria. For example, to only pick the books more expensive than $6 :
<?php
$filename = "catalog.xml";
$simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
$search_result = $simple_xml_obj->xpath('/catalog/book[price>6]/price');
foreach($search_result as $price)
echo $price . PHP_EOL;
?>
4.6 Exporting XML
To export the in memory contents of a SimpleXMLElement we can use the ‘asXML’ method:
<?php
$filename = "catalog.xml";
$simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
echo $simple_xml_obj->asXML();
?>
It is also possible to write the XML to disk by passing a file name:
<?php
$filename = "catalog.xml";
$simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
if (!$simple_xml_obj->asXML('/tmp/out.xml'))
echo "Unable to save the XML file!" . PHP_EOL;
?>



January 8th, 2010 at 8:01 pm
Very good note for PHP 5 certification exam preparing indeed. anymore notes?
January 18th, 2010 at 3:34 pm
Hi Tim,
Sorry — most of my remaining notes were quite unreadable scribles
I did try to put together the “ultimate” PHP5 class (containing as many PHP OO features as possible) which is still languishing in a draft post. I will put that post online too.
Martijn