Studyon Minte9.com
ZCE 5.3

Study

SimpleXML



	// $library = simplexml_load_file("library.xml");
	// $library = new SimpleXMLElement("library.xml", NULL, true);
	// $book['isbn'] / $book->title (attribute or element)
	// $attr->getName() / $subchild->getName() (abstract accesing)
	// xpath queries
	// addAttribute / addChild
	// xmlns (pub:publisher)


* library.xml

	<?xml version="1.0"?>
	<library>
	<book isbn="0345342968">
		<title>Fahrenheit 451</title>
		<author>R. Bradbury</author>
		<publisher>Del Rey</publisher>
	</book>
	<book isbn="0451524934">
		<title>1984</title>
		<author>G. Orwell</author>
		<publisher>Signet</publisher>
	</book>
	</library>


* Parsing (procedural OR oop)

All objects created by SimpleXML are instances of the SimpleXMLElement class. Thus, when parsing a 
document or XML string, you will need to create a new SimpleXMLElement. SimpleXML also supports an 
OOP-centric approach to loading a document.
	
	<?php
		// Load an XML string
		$xmlstr = file_get_contents('library.xml');
		$library = simplexml_load_string($xmlstr);
		
		// Load an XML file
		$library = simplexml_load_file('library.xml');

	
	<?php
		// Load an XML string
		$xmlstr = file_get_contents('library.xml');
		$library = new SimpleXMLElement($xmlstr);
		
		// Load an XML file
		$library = new SimpleXMLElement('library.xml', NULL, true);
			// The third parameter is important, though, because it informs the constructor
			// that the first argument represents the path to a file, rather than a string that contains the 
			// XML data itself


* Accessing (Children and Attributes)

When SimpleXML parses an XML document, it converts all its XML elements, or nodes, to properties of the 
resulting SimpleXMLElement object. In addition, it converts XML attributes to an associative array that may 
be accessed from the property to which they belong. Each of these properties is, in turn, also an instance of 
SimpleXMLElement, thus making it easier to access child nodes regardless of their nesting level.

	<?php
		$library = simplexml_load_file('library.xml');

		foreach($library->book as $book) {
			echo $book['isbn'] . "n";
			echo $book->title . "n";
			echo $book->author . "n";
			echo $book->publisher . "n";
		}

* Accessing (abstract)

There are times when a provider may change the structure of their file so that, while the overall format 
remains the same, your code will be unable to access the proper data if you are forced to hard-code the 
name and nesting level of each node. Thus, SimpleXML provides a means to access children and attributes 
without the need to know their names. In fact, SimpleXML will even tell you their names.

	<?php
		$library = simplexml_load_file('library.xml');

		foreach($library->children() as $child) {
			
			echo "<br>" . $child->getName() . ": ";

			// Get attributes of this element
			foreach($child->attributes() as $attr) {
				echo $attr->getName() . ": " . $attr;
			}

			// Get children
			foreach($child->children() as $subchild) {
				echo $subchild->getName() . ": " . $subchild;
			}
		}


* Queries

The XML Path Language (XPath) is a W3C standardized language that is used to access and search XML 
documents. It is used extensively in Extensible Stylesheet Language Transformations (XSLT) and forms the 
basis of XML Query (XQuery) and XML Pointer (XPointer). Think of it as a query language for retrieving data 
from an XML document.

Using SimpleXMLElement::xpath(), you can run an Xpath query on any SimpleXMLElement object. If used 
on the root element, it will search the entire XML document. If used on a child, it will search the child and 
any children it may have.

	<?php
		$library = simplexml_load_file('library.xml');

		// Search the root element
		$results = $library->xpath('/library/book/title');
		foreach($results as $title) {
			echo $title . "n";
		}

		// Search the first child element
		$results = $library->book[0]->xpath('title');
		foreach($results as $title) {
			echo $title . "n";
		}

* Modify

PHP 5.1.3, however, introduced two new methods to SimpleXML that now give it the power it needs to create
and modify XML documents: SimpleXMLElement::addChild() and SimpleXMLElement::addAttribute().

	<?php
		$library = simplexml_load_file('library.xml');

		$book = $library->addChild('book');
		$book->addAttribute('isbn', '0812550706');
		$book->addChild('title', "Ender's Game");
		$book->addChild('author', 'Orson Scott Card');
		$book->addChild('publisher', 'Tor Science Fiction');

		header('Content-type: text/xml');
		echo $library->asXML();

Called without a parameter, the asXML() method returns an XML string. However asXML() also accepts a file
path as a parameter, which will cause it to save the XML document to the given path and return a Boolean 
value to indicate the operation's success. If a file with the same path already exists, a call to asXML() will 
overwrite it without warning (provided that the user account under which PHP is running has the proper 
permissions).


* Delete

While SimpleXML provides the functionality for adding children and attributes, it does not provide the means 
to remove them. It is possible to remove child elements, though, using the following method.

	<?php
		$library->book[0] = NULL;

This only removes child elements and their attributes, however. It will not remove attributes from the element 
at the book level. Thus, the isbn attribute remains. To effectively remove children and attributes, you must 
export your SimpleXMLElement to DOM.


* Namespaces

The use of XML namespaces allows a provider to associate certain element and attribute names with 
namespaces identified by URIs. This qualifies the elements and attributes, avoiding any potential naming 
conflicts when two elements of the same name exist yet contain different types of data.

	<?xml vesion="1.0"?>
	<library xmlns="http://example.org/library"
		xmlns:meta="http://example.org/book-meta"
		xmlns:pub="http://example.org/publisher"
		xmlns:foo="http://example.org/foo">
	<book meta:isbn="0345342968">
		<title>Fahrenheit 451</title>
		<author>Ray Bradbury</author>
		<pub:publisher>Del Rey</pub:publisher>
	</book>
	</library>

SimpleXML has had the ability to return all namespaces declared in a document.

	<?php
		$library = simplexml_load_file('library2.xml');

		$namespaces = $library->getDocNamespaces();
		foreach($namespaces as $k=>$v) {
			echo "{$k} => {$v}n";
		}

Notice that the foo namespace was listed, but was never actually used. 
A call to SimpleXMLElement::getNamespaces() will return an array that only contains those namespaces 
that are actually used throughout the document. Like getDocNamespaces(), this method accepts a boolean 
value to turn on its recursive behaviour.

	<?php
		$library = simplexml_load_file('library2.xml');

		$namespaces = $library->getNamespaces(true);
		foreach($namespaces as $k=>$v) {
			echo "{$k} => {$v}n";
		}