PHP DomXPath: Read Complex XML files easily.

XPath allows traversing through XML elements and attributes very easily. For complex XMLs, using XPath can significantly reduce the complexity of coding.

Good Tutorial of XPath can be viewed on W3C schools here. Reference on DomXPath can be viewed here.

XPath is useful if someone needs to extract a specific node from an entire XML, rather than parsing the entire XML by running a query. Below I will explain how to use DomDocument and DomXPath to read XML. At first I will start with a simple XML, and then more complex.

Here’s a basic XML called ‘test.xml’:

<xml version="1.0" encoding="ISO-8859-1">
<library>
	<book isbn="781">
		<name>SCJP 1.5</name>
		<info><![CDATA[Sun Certified Java Programmer book]]></info>
	</book>
        <book isbn="980">
		<name>jQuery How To</name>
		<info><![CDATA[jQuery Reference Book]]></info>
	</book>
<library>

Few Details: A couple of DomXPath query syntax is:

// get all book element which has info attribute and is a child of library 
query("//library/book[@info]") 

// get all name element which is a child of book which is a child of library (library is the root node)
query("/library/book/name'); 

// note: above i use single slash before library to specify its a root node

For full specs, please check out W3C’s page on XPath syntax

To register a namespace in DomXPath of PHP, use the following:

$xpath->registerNamespace('localName', namespaceURI');

Below is a way to parse it, At first load XML File on DomDocument and initialize DomXPath and then run the query method.

$dom = new DomDocument("1.0", "ISO-8859-1");
$dom->load('test.xml');
$xpath = new DomXPath($dom);

Lets say, I want to get all the names of book, then just do the following:

$bookList  = array();
$bookNodes = $xpath->query('//book/name'); // selects all name element
for($i=0;$i<$bookNodes->length;$i++) {
 $bookList[] = $bookNodes->item($i)->nodeValue;
}

// below is print_r of bookList
array(2) {
  [0]=>
  string(8) "SCJP 1.5"
  [1]=>
  string(18) "jQuery is Awesome!"
}

OK, simple enough. The above example doesn’t demonstrate how XPath makes life easier, so, lets parse YouTube’s featured RSS Playlist, which has namespace and a whole lot of elements. To keep it simple, I am only going to fetch the recently added Video’s Title and their corresponding URL.

From the RSS file, it can be seen that URL is stored “href” attribute of ‘link’ the element which has attribute type as text/html. Below I show the snippet of ‘link’ element and title from the XML.


 ... 
  
    YouTube Symphony Orchestra @ Carnegie Hall - Act One
    ...
    
   ...
  
 ...

OK, so we need to get the following:

  1. The node value of ‘title’ element which has attribute type=’text’ and which is inside entry and entry is inside feed.
  2. The attribute value of ‘href’ which is of link element inside entry, and which is inside feed.

Below is the full code of how to read YouTube’s RSS

// initialize and the file into load DomDocument
$youTubeDom = new DomDocument();
$youTubeDom->load('http://gdata.youtube.com/feeds/api/standardfeeds/recently_featured');

// intialize an DomXPath object
$xPath 		= new DomXPath($youTubeDom);

// register the namespace on YouTube (its declared on feed element)
$xPath->registerNamespace('yte', 'http://www.w3.org/2005/Atom');

// now run the 2 queries, add the suffix of that namespace because feed, entry etc. belong to that namespace
$linkNodes 	= $xPath->query("/yte:feed/yte:entry/yte:link[@type='text/html']");
$titleNodes     = $xPath->query("/yte:feed/yte:entry/yte:title[@type='text']");


$recentList	= array();
for($i=0;$i<$titleNodes->length;$i++) {
	$recentList[$i] = array(
		'title' => $titleNodes->item($i)->nodeValue ,
		'url'	=> $linkNodes->item($i)->getAttribute('href')
	);
	
}

And Thats it. Here’s a var_dump of the $recentList


array(25) {
  [0]=>
  array(2) {
    ["title"]=>
    string(52) "YouTube Symphony Orchestra @ Carnegie Hall - Act One"
    ["url"]=>
    string(42) "http://www.youtube.com/watch?v=ueJcRmfweSM"
  }
  [1]=>
  array(2) {
    ["title"]=>
    string(38) ""The Internet Symphony" Global Mash Up"
    ["url"]=>
    string(42) "http://www.youtube.com/watch?v=oC4FAyg64OI"
  }
  [2]=>
  array(2) {
    ["title"]=>
    string(49) "Harmony: The Road to Carnegie Hall Teaser Trailer"
    ["url"]=>
    string(42) "http://m.youtube.com/details?v=oC4FAyg64OI"
  }
  [3]=>
  array(2) {
    ["title"]=>
    string(44) "The YouTube Symphony Orchestra Summit Begins"
    ["url"]=>
    string(42) "http://www.youtube.com/watch?v=wBZviTce94Q"
  }
  [4]=>
  array(2) {
    ["title"]=>
    string(47) "4/13@A.M. YouTubeSymphonyOrchestra Vlog by Eiko"
    ["url"]=>
    string(42) "http://m.youtube.com/details?v=wBZviTce94Q"
  }
  [5]=>
  array(2) {
    ["title"]=>
    string(50) ""Internet Symphony, Eroica" Rehearsal with Tan Dun"
    ["url"]=>
    string(42) "http://www.youtube.com/watch?v=lwVtmH9k-SI"
  }
  // ...... shortened .... 
  
}

I hope this explains how XPath simplifies reading XML files.

PHP Shipping Modules (Canada Post)

Over the last month I have been working on an e-commerce store for our company and realized most of the shipping modules out there are quite complex to use. So, I decided to create a simple Canada Post PHP Class.

Canada Post’s specification requires parsing of XML files to retrieve values, hence I have used PHP-5’s new features like DomDocument, DomXPath and stream functions which will only work with PHP-5 (you would need additional libraries to run it in PHP-4)

The class provided is called class.canadapost.php and I below I will provide instructions on how to use it.

(note: To use Canada Post, Port 30000 must be opened.)

Instructions on How to use the class

At first make sure you include the class using require or include..

include 'path/to/class/class.canadapost.php';

Then Initialize the class and set your information (your as in the store’s postal code, and canada posts’ merchant CPCID) and the customer Information.

$cPost = new CanadaPost();

/* Set your manufacturer CPCID, postal code by calling the function setManufacturer and passing in associative array 
 * format shown below, pass the total Cost of the item to be shipped in itemsPrice.
 */
$cPost->setManufacturer( array (
      'merchantCPCID' => CPC_DEMO_XML, // use your merchantCPCID
      'fromPostalCode' => YOUR_POSTAL_CODE, // use your postal code from where the item will be shipped
      'turnAroundTime' => 24,
      'itemsPrice' => 14 // put the total cost of item to be shipped.
    )
); 

/* Then set the Customer address in the format shown below, again in associative array format.
 *  Note: you dont need to pass the city and provOrState, they are actually optional. You only need the Postal Code 
 *  and country. 
 */
$cPost->setCustomer( array (
     'city' => 'Brampton', [CUSTOMER_CITY]
     'provOrState' => 'Ontario', [CUSTOMER_STATE_PROVINCE]
     'country' => CA, [2 Digit Code, see Canada Post Specs for more Info]
     'postalCode' => 'L1JK9' [CUSTOMER_POSTAL_OR_ZIP_CODE]
   )
);

I have developed the Class by keeping in mind that we could have several stores in different location, from where we could be shipping items. However, if you have just one store, then you don’t have to call the function setManufacturer every time, instead you can modify the class.canadapost.php’s constructor and hardcode the items there. So, then, after initializing the class, all you need to do is call the setPrice function to set the total Price.

$cPost->setPrice(15);

Now, add the Products you want to ship. Weights are in KG and dimension should be in CM. In the quantity, pass the
number of same products you wish to ship.

$cPost->addProduct(  array (
   'quantity' => 1,
   'weight'=> 2,
   'length' => 3,
   'width' => 1,
   'height' => 8,
  'description' => 'some Description about Product'
  )
 );

/** To add additional product, just call the same function i.e. addProduct again passing information about product as shown above **/

Now, the final part. To get the rates. You can either receive the entire XML response from Canada Post and do the parsing yourself, or you could ask the function to return you the response in associative array format, which would make it easier for you to fetch the information.

To receive in XML, do the following:

$responseXML = $cPost->getRates(); // returns in XML format. 

To receive in Associative Array, do the following:

$responseArray = $cPost->getRates('array');

If any error happens, the function getRates( ) would return false, and you can get the Error message from the function getErrorMessage( ), as shown below:

$rXML = $cPost->getRates(); // or $rXML= $cPost->getRates('array);
if( $rXML === false ) {
  echo $cPost->getErrorMessage();
}

When you receive the response in associative format, here’s a var_dump how the array returns information:

array(2) {
  ["product"]=>
  array(3) {
    [0]=>
    array(7) {
      ["name"]=>
      string(16) "Priority Courier"
      ["rate"]=>
      string(5) "16.26"
      ["shippingDate"]=>
      string(10) "2008-09-29"
      ["deliveryDate"]=>
      string(10) "2008-09-30"
      ["deliveryDayOfWeek"]=>
      string(1) "3"
      ["nextDayAM"]=>
      string(4) "true"
      ["packingID"]=>
      string(3) "P_0"
    }
    [1]=>
    array(7) {
      ["name"]=>
      string(9) "Expedited"
      ["rate"]=>
      string(4) "7.34"
      ["shippingDate"]=>
      string(10) "2008-09-29"
      ["deliveryDate"]=>
      string(10) "2008-09-30"
      ["deliveryDayOfWeek"]=>
      string(1) "3"
      ["nextDayAM"]=>
      string(5) "false"
      ["packingID"]=>
      string(3) "P_0"
    }
    [2]=>
    array(7) {
      ["name"]=>
      string(7) "Regular"
      ["rate"]=>
      string(4) "7.34"
      ["shippingDate"]=>
      string(10) "2008-09-29"
      ["deliveryDate"]=>
      string(10) "2008-10-01"
      ["deliveryDayOfWeek"]=>
      string(1) "4"
      ["nextDayAM"]=>
      string(5) "false"
      ["packingID"]=>
      string(3) "P_0"
    }
  }
  ["shippingOptions"]=>
  array(3) {
    ["insurance"]=>
    string(2) "No"
    ["deliveryConfirmation"]=>
    string(3) "Yes"
    ["signature"]=>
    string(2) "No"
  }
}

As seen above, the response contains array of 2 elements, products and shippingOptions, and within products contains array of the different shipping rates available. Within shippingOptions, contains the shipping insurance, and other features. Insurance options can be selected from your Canada Posts account’s page on the Canada Post Server.

I have attached 2 files, class.canadapost.php and estimate_shipping.php. Once again make sure you have port 30000 opened for it to function. Please rename the files from *.txt to *.php

Download from Github

PHP 5 XMLReader: Reading XML with Namespace (Part 2)

This is a continuation of previous article, where I wrote on how to use PHP’5 DOM to read XML Files easily. But, for large files, its better to use XMLReader. Unlike DomDocument, XMLReader does not load the entire File on memory. It reads an XML file one node at a time. I hardly use XMLReader because it requires writing a lot of codes, but for extremely large XML Files, its better to use it. Full reference on XMLReader can be viewed here. It requires PHP 5.2.

The following are the functions I use:

  1. open – opens XML File
  2. read – reads node of XML
  3. getAttribute – gets the attribute of a node
  4. moveToNextAttribute – moves to next Attribute
  5. next – moves to next node

Here’s a Basic XML File called ‘test.xml’:

<xml version="1.0" encoding="ISO-8859-1">
<library>
	<book isbn="781">
		<name>SCJP 1.5</name>
		<info><![CDATA[Sun Certified Java Programmer book]]></info>
	</book>
        <book isbn="980">
		<name>jQuery How To</name>
		<info><![CDATA[jQuery Reference Book]]></info>
	</book>
<library>

Below is a way to read it:

At first initialize and open the XML file

$xmlReader = new XMLReader();
// open the file for reading
$xmlReader->open('test.xml')

Now keep reading nodes until the end has been reached, which done by a while loop:

while($xmlReader->read()) { 

}

Below is the full code:

$bookList = array();
$i=0;
$xmlReader = new XMLReader();
$xmlReader->open('test.xml');
while($xmlReader->read()) {
        // check to ensure nodeType is an Element not attribute or #Text  
	if($xmlReader->nodeType == XMLReader::ELEMENT) {
		if($xmlReader->localName == 'book') {
			$bookList[$i]['book_isbn'] = $xmlReader->getAttribute('isbn');
		}
		if($xmlReader->localName == 'name') {
			// move to its textnode / child
			$xmlReader->read(); 
			$bookList[$i]['name'] = $xmlReader->value;
		}
		if($xmlReader->localName == 'info') {
			// move to its textnode / child
			$xmlReader->read(); 
			$bookList[$i]['info'] = $xmlReader->value;
			$i++;
		}
		
	}
}

Here’s a var_dump of $bookList

array(2) {
  [3]=>
  array(3) {
    ["book_isbn"]=>
    string(3) "781"
    ["name"]=>
    string(8) "SCJP 1.5"
    ["info"]=>
    string(34) "Sun Certified Java Programmer book"
  }
  [4]=>
  array(3) {
    ["book_isbn"]=>
    string(3) "194"
    ["name"]=>
    string(18) "jQuery is Awesome!"
    ["info"]=>
    string(21) "jQuery Reference Book"
  }
}

That’s about it. It requires writing a lot of codes, but it’s useful for large (by large I mean extremely large) XML files.

However, when the XML files is very complex (and not extremely large), I find both DomDocument or XMLReader are not ideal solution. I rather use XPath (DomXPath), which I will hopefully write in my next article.

PHP 5 DOM and XMLReader: Reading XML with Namespace (Part 1)

PHP-5’s DOM and XMLReader provides the ability to read XML files easily. The good thing about PHP-5’s DOM (mainly DomDocument, DomNodeList, DomNode) is that it implements the standard DOM features as specified by W3C. W3C’s reference on DOM can be viewed here. So, if someone has used DOM before (say on JavaScript), then it would be easy for him/her to grasp PHP-5’s DOM.

The following are the functions of PHP5’s DOM I commonly use:

  1. getElementsByTagName
  2. getAttribute
  3. childNodes
  4. nodeName
  5. nodeValue
  6. getElementsByTagNameNS

Here’s a Simple XML File called test.xml:



 
   SCJP 1.5
   
 
 
   jQuery is Awesome!
   
 	


Below I will explain how to read the XML. At first load the file on DomDocument

$dom = new DomDocument();
$dom->load('test.xml');

So, $dom now has the XML file loaded, now using getElementsByTagName I will get the list of elements/nodes called ‘book’

$bookElemList = $dom->getElementsByTagName('book');

bookElemList is an object of DomNodeList and it contains List of DomNode of ‘book’ tags/elements. It has a instance variable ‘length’ which returns the number of DomNodes (items) in it, and it has a method called item (index), which returns the item based on the index passed on it. Below, I parse through bookElemList and store contents of ‘book’ in an assoc array. To get access to an Attribute, I use getAttribute method as shown below

$bookList = array();
// run a for loop to iterate through all bookElemList index.
for($i=0;$i<$bookElemList->length;$i++) {
	$bookList[$i] = array (
          // get Attribute of book Element as store it in book_isbn
	  'book_isbn' => $bookElemList->item($i)->getAttribute('isbn'),
          // get 'name' element inside bookElemList at $i index.
	  'name'      => $bookElemList->item($i)->getElementsByTagName('name')->item(0)->nodeValue,
	  'info'      => $bookElemList->item($i)->getElementsByTagName('info')->item(0)->nodeValue
	);

}

Instead of getting name and info separately I could have easily used childNodes method to access the elements like below: (Note that below I had to use nodeType to check if the node is Element or not, this is required because Blank spaces on XML is considered as a text node by DOM. If you want to avoid checking nodeType, then remove whitespaces from XML before reading it). Values of NodeType can be viewed at W3C’s page

$bookList = array();
for($i=0;$i<$bookElemList->length;$i++) {
  $bookList[$i]['book_isbn'] = $bookElemList->item($i)->getAttribute('isbn');
 
 foreach($bookElemList->item($i)->childNodes as $eachChild) {
  if( $eachChild->nodeType == 1 )  // ensure nodeType is Element
   $bookList[$i][$eachChild->nodeName] = $eachChild->nodeValue;
 }
}

But, I prefer to manually get the contents, because in most cases, I only need the values/texts of few elements on the XML, so if instead I use childNodes, it means I would be consuming memory for large XML files which has many elements/tags.

Here’s a print_r of how $bookList looks like:

Array
(
    [0] => Array
        (
            [book_isbn] => 781
            [name] => SCJP 1.5
            [info] => Sun Certified Java Programmer book
        )

    [1] => Array
        (
            [book_isbn] => 194
            [name] => jQuery is Awesome!
            [info] => jQuery Reference Book
        )

)

The above was a very simple XML. Now, lets parse an XML a bit complex and which has namespaces.An XML Namespace is used to avoid conflicts on XML Elements/Tags by using a prefix. Brief info on XML Namespaces can be viewed here.

I chose to read reading an XML featured on JWPlayer’s setup wizard. It can be viewed here JWPlayer’s Rss XML

Here’s the XML:


	
		Example media RSS playlist for the JW Player
		http://www.longtailvideo.com

		
			Big Buck Bunny - FLV Video
			http://www.bigbuckbunny.org/

			Big Buck Bunny is a short animated film by the Blender Institute, part of the Blender Foundation. Like the foundation's previous film Elephants Dream, the film is made using free and open source software.
			the Peach Open Movie Project
			
		

		
			Big Buck Bunny - MP3 Audio with thumb
			http://www.bigbuckbunny.org/

			Big Buck Bunny is a short animated film by the Blender Institute, part of the Blender Foundation. Like the foundation's previous film Elephants Dream, the film is made using free and open source software.
			the Peach Open Movie Project
			
			
		

		
			Big Buck Bunny - PNG Image with start

			http://www.bigbuckbunny.org/
			Big Buck Bunny is a short animated film by the Blender Institute, part of the Blender Foundation. Like the foundation's previous film Elephants Dream, the film is made using free and open source software.
			
				the Peach Open Movie Project
				
			
		

	


Here’s the first tag from the File which declares the XML Namespace


The Namespace is defined on the first line, i.e. xmlns:media (so ‘media’ is the localname of that Element on this XML File, while its namespace is ‘http://search.yahoo.com/mrss/’)

To read a node with a namespace, the following method can be used:

$dom->getElementByTagNameNS('namespaceURI', 'local_Name_of_Node');

The code below explains how to read the above XML

// load the file on the DOM
$dom = new DomDocument();
$dom->load('http://www.longtailvideo.com/jw/upload/mrss.xml');

$itemList 		= array();

// get the list of Items.
$itemElemList 	= $dom->getElementsByTagName('item');
for($i=0;$i<$itemElemList->length;$i++) {
	$itemList[$i] = array (
		'title'       => $itemElemList->item($i)->getElementsByTagName('title')->item(0)->nodeValue,
		'link'        => $itemElemList->item($i)->getElementsByTagName('link')->item(0)->nodeValue,
		'description' => $itemElemList->item($i)->getElementsByTagName('description')->item(0)->nodeValue,			
		'credit'      => $itemElemList->item($i)->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'credit')->item(0)->nodeValue,
		'content_url' => $itemElemList->item($i)->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'content')->item(0)->getAttribute('url'),
	);

}

Here’s a print_r of how itemList looks like:

Array
(
    [0] => Array
        (
            [title] => Big Buck Bunny - FLV Video
            [link] => http://www.bigbuckbunny.org/
            [description] => Big Buck Bunny is a short animated film by the Blender Institute, part of the Blender Foundation. Like the foundation's previous film Elephants Dream, the film is made using free and open source software.
            [credit] => the Peach Open Movie Project
            [content_url] => http://www.longtailvideo.com/jw/upload/bunny.flv
        )

    [1] => Array
        (
            [title] => Big Buck Bunny - MP3 Audio with thumb
            [link] => http://www.bigbuckbunny.org/
            [description] => Big Buck Bunny is a short animated film by the Blender Institute, part of the Blender Foundation. Like the foundation's previous film Elephants Dream, the film is made using free and open source software.
            [credit] => the Peach Open Movie Project
            [content_url] => http://www.longtailvideo.com/jw/upload/bunny.mp3
        )

    [2] => Array
        (
            [title] => Big Buck Bunny - PNG Image with start
            [link] => http://www.bigbuckbunny.org/
            [description] => Big Buck Bunny is a short animated film by the Blender Institute, part of the Blender Foundation. Like the foundation's previous film Elephants Dream, the film is made using free and open source software.
            [credit] => the Peach Open Movie Project
            [content_url] => http://www.longtailvideo.com/jw/upload/bunny.png
        )

)

So far I explained reading XML by loading on DomDocument. An important thing to realize is that when an XML is loaded on DomDocument, the entire XML is converted into a DomDocument, thus giving the ability to parse through each Nodes on the XML.

But, if the XML is very large, then loading them via DomDocument is unwise, because it means using a lot of memory (loading entire file on Memory), so, PHP-5 provides a Class: XMLReader. In part 2 of this article, I explain how to use XMLReader.

PHP-5 DomDocument: Creating a Basic XML

DomDocument is a powerful library of PHP-5 to create XML. In this article, I will try to explain the basics of DomDocument and then will create a couple of simple XML files.

First, lets have a look at a simple XML file:
Taken from W3C’s example:

<?xml version="1.0" encoding="ISO-8859-1"?>
>note>
	<to>Tove>/to>
	<from>Jani>/from>
	<heading>Reminder>/heading>
	<desc>Don't forget me this weekend!</desc>
</note>

We see an XML version and character encoding at the first line, followed by XML Tags/Elements. I am going to create the above XML using DomDocument

In PHP, at first let’s create an instance of DomDocument and initialize it, and set its version and character encoding

// 1st param takes version and 2nd param takes encoding;
$dom = new DomDocument("1.0", "ISO-8859-1");

// it can also be set later, like below, if you decide not to declare at first line:
$dom->version  = "1.0";
$dom->encoding = "ISO-8859-1";

To create a Node, the following method is used:

$dom->createElement('NODE_NAME');
// OR
$dom->createElement('NODE_NAME', 'NODE_VALUE');

To set a node as a child node of another node:

$dom->appendChild( 'PREVIOUSLY_CREATED_NODE' );

Now, we are going to create Nodes:

// we create a XML Node and store it in a variable called noteElem;
$noteElem  = $dom->createElement('note'); 

// createElement takes 2 param also, with 1st param takes the node Name, and 2nd param is node Value
$toElem    = $dom->createElement('to', 'Tove');

// now, we add $toElem as a child of $noteElem
$noteElem->appendChild( $toElem );

//we don't need to create a new variable for each node, we can do the following to quicken the steps:
$noteElem->appendChild ( $dom->createElement('from', 'Jani') );
$noteElem->appendChild ( $dom->createElement('heading', 'Reminder') );
$noteElem->appendChild ( $dom->createElement('desc', 'Dont forget me this weekend!') );

So, $noteElem, now has all its child added properly. So we add $noteElem to $dom and then we can save it as File or output as XML like below:

// add $noteElem to the main dom
$dom->appendChild( $noteElem );

// $dom has entire XML, but, it's not clearly formatted, i.e there's no space or new lines in between tags, so I do this:
$dom->formatOutput = true; // this adds spaces, new lines and makes the XML more readable format. 

// now $dom has all the entire XML properly, we can output it like below, 
$xmlString = $dom->saveXML(); // $xmlString contains the entire String

// or we can save it as XML
$dom->save('filename.xml'); // returns true/false upon failure or success 

The above was a very simple XML, with no Attributes or CDATA/PCDATA on any element, so, lets say we have the following XML below:

<?xml version="1.0" encoding="ISO-8859-1"?>
<library>
 <book isbn="781">
   <name>SCJP 1.5</name>
   <info><![CDATA[Sun Certified Java Programmer book]]></info>
  </book>
</library>

To set Attribute of any Element, use:

$dom->setAttribute('name', 'value');

To create a CDATA, use:

$dom->createCDATASection('The CData for the Node');

Below, I will create the above XML

$dom 	  = new DomDocument("1.0", "ISO-8859-1");
$library  = $dom->createElement('library');

//1st item
$bookElem = $dom->createElement('book');
// set it's attribute
$bookElem->setAttribute('isbn', '781');
$bookElem->appendChild( $dom->createElement('name', 'SCJP 1.5') );

//create infoElement and append a CDATA as its child
$infoElem = $dom->createElement('info');
$infoElem->appendChid( $dom->createCDATASection('Sun Certified Java Programmer book') );

$bookElem->appendChild( $infoElem );
$library->appendChild( $bookElem );
$dom->appendChild( $library );

$xmlData  = $dom->saveXML();

Sometimes you may want to have comments in an XML, use:

$dom->createComment('some comment data');

I think thats about it. One important thing to know that DomDocument can be used to create HTML files. It have several functions like saveHTML, please read the PHP 5’s official Documentation to know more.