Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / PHP

Working with XML in PHP

4.92/5 (15 votes)
3 May 2013CPOL3 min read 74.1K   2.1K  
Working with XML in PHP.

Introduction

I had to store some data without using MySQL in a project I am currently working on because of speed and large number of connection which I know MySQL cannot handle. The only idea that came to my head was to use shared memory and XML.

I had never worked with XML on PHP before so my first reaction was to go get some information from the PHP manual but viola very scanty. Google didn’t help much either.

After a few hours (and already feeling like hitting my head on the wall) I got them all working fine, so to save forks like me I decided to share my little experience. This article will help in

  1. Writing XML from scratch
  2. Reading data from XML
  3. Adding node to existing XML
  4. Modifying a node in existing XML
  5. Deleting a node from existing XML

You can just grab the sample codes, they are well commented

Writing XML from scratch (using XMLWriter)

XMLWriter was designed to write well formatted XML from scratch. One of its important methods is startDocument() which lets you state the version and encoding to use (though these are options).

Usage

To write simple XML of this nature:
XML
<?xml version="1.0"?>
<Customer>
<id>1</id>
<name>Oluwafemi</name>
<address>Cresent Drive, TX</address>
</Customer>
Simple Example

This can approached with XMLWriter:

PHP
<?php
//XMLwriter to write XML from scratch - Simple example
$xml = new XMLWriter(); //create a new xmlwriter object
$xml->openMemory(); //using memory for string output
$xml->startDocument(); //create the document tag, you can specify the version and encoding here
$xml->startElement("Customer"); //Create an element
$xml->writeElement("id", "1");
$xml->writeElement("name", "Oluwafemi"); //Write to the element
$xml->writeElement("address", "Cresent Drive, TX");
$xml->endElement(); //End the element
echo $xml->outputMemory(); //done with writing output the xml
?>

This is named “Simple - XMLWriter.php” in the downloads

A little complex example is to write this XML:

XML
<xml version="1.0"?>
<purchase>
<customer>
<id>1</id>
<time>2013-04-19 10:56:03</time>
<total>$350</total>
</customer>
<customer>
<id>2</id>
<time>2013-04-23 13:43:41</time>
<total>$1456</total>
</customer>
</purchase>
Little complex example

This piece of code solves the puzzle:

PHP
<?php
//XMLwriter to write XML from scratch - Little complex example
$xml = new XMLWriter();
$xml->openMemory();
$xml->startDocument();
$xml->startElement("purchase");
$xml->startElement("customer");  //Start of customer with id 1
$xml->writeElement("id", 1);
$xml->writeElement("time", "2013-04-19 10:56:03");
$xml->writeElement("total", "$350");
$xml->endElement();  //End of customer with id 1
$xml->startElement("customer");  //Start of customer with id 2
$xml->writeElement("id", 2);
$xml->writeElement("time", "2013-04-23 13:43:41");
$xml->writeElement("total", "$1456");
$xml->endElement();  //End of customer with id 1
$xml->endElement();
echo $xml->outputMemory();
?>

This is named “Little Complex - XMLWriter.php” in the downloads

An even more complex one is giving attributes to some nodes, for instance, the <product> node in this example:

XML
<?xml version="1.0"?>
<products>
<product pid="314">
<name>Apple</name>
<price>$1.00</price>
<discount>3%</discount>
</product>
<product pid="315">
<name>Mango</name>
<price>$0.90</price>
<discount>3%</discount>
</product>
</products>
More complex example (This XML will be used in various examples that follows)

This can also be achieved with XMLWriter:

PHP
<?php
//XMLwriter to write XML from scratch - Little complex example
    $xml = new XMLWriter();
    $xml->openMemory();
    $xml->startDocument();
        $xml->startElement("products");
            $xml->startElement("product");      //Start of product with pid 314
            $xml->writeAttribute("pid", 314);
                $xml->writeElement("name", "Apple");
                $xml->writeElement("price", "$1.00");
                $xml->writeElement("discount", "3%");
            $xml->endElement();                           //End of product with pid 314
            $xml->startElement("product");      //Start of product with pid 315
            $xml->writeAttribute("pid", 315);
                $xml->writeElement("name", "Mango");
                $xml->writeElement("price", "$0.90");
                $xml->writeElement("discount", "3%");
            $xml->endElement();                          //End of product with pid 315
        $xml->endElement();
    echo $xml->outputMemory();                           //Done with writing, output the xml
?>
This is named “More Complex - XMLWriter.php” in the downloads

Reading / Getting data from an XML (using XMLReader and SimpleXMLElement)

XMLReader is used in getting with I call “node xml” from an entire XML. You can load in the XML either from a URI (file, URL, etc.) by using the open() method or from memory using the xml() method. This illustration will use xml() method all through. There is no big deal about the open() method, just supply the URI containing the XML e.g., open(“c:/…/this.xml”); or open(“http://example.com/this.xml”);.

SimpleXMLElement can be used to extract data from the “node xml” gotten from XMLReader.

To get the total amount spent by the customer whose id is 1 in the Little complex example above

PHP
<?php
.
.
.
    /*     XMLReader starts from here for Little Complex Example - XMLReader
        To get the total amount spent by custormer with id 1
    */
    $rxml = new XMLReader();    //Create new XMLReader Object
    $rxml->xml($nXML);        //Load in the XML
    while($rxml->read() && $rxml->name !== 'customer');
    //Move to the first customer child 
    
    $amountSpent = 0;
    while($rxml->name === 'customer')
    {
        /* The child xml gotten using the readOuterXML() will look thus
        <customer><id>1</id><time>2013-04-19 10:56:03</time><total>$350</total></customer>
        */
        //Read the current child xml into a SimpleXMLElement
        $node = new SimpleXMLElement($rxml->readOuterXML());
        if($node->id == 1)
        //Check if the id node as 1 as it value
        {
            $amountSpent = $node->total;
            break;
        }
        $rxml->next('customer');
        //Move to the next customer child
    }
    
    echo $amountSpent;
?>
This is named “Little Complex Example - XMLReader.php” in the downloads

And to get the name, price, and discount of the product with pid=315 from More complex example above

 

PHP
/*	XMLReader starts from here for More Complex XMLReader
		To get the name, price, and discount of the prouct with attribute pid = 315
	*/
	$rxml = new XMLReader();								//Create new XMLReader Object
	$rxml->xml($nXML);										//Load in the XML
	while($rxml->read() && $rxml->name !== 'product');		//Move to the first product child 
	
	$name = "";
	$price = "";
	$discount = "";
	while($rxml->name === 'product')
	{														/* The child xml gotten using the readOuterXML() will look thus
																<product pid="314"><name>Apple</name><price>$1.00</price><discount>3%</discount></product>
															*/
		if($rxml->getAttribute("pid") == "315")				//Check if the atrribute pid is equals to 315
		{
			$node = new SimpleXMLElement($rxml->readOuterXML());//Read the current child xml into a SimpleXMLElement
			$name = $node->name;
			$price = $node->price;
			$discount = $node->discount;
			break;
		}
		$rxml->next('product');							//Move to the next product child
	}
	
	echo "The product is {$name} and is {$price} with {$discount} as discount";
?>
This is named “More Complex - XMLReader.php” in the downloads

Adding child to an already existing XML (using SimpleXMLElement)

XMLWriter was designed to write fresh XML from start to finish. But say a new product is to be added to the XML More complex example above, you wont want to rewrite the whole XML again, will you? (Imagine the XML now has up to 350,000 product nodes Wink ). SimpleXMLElement can be used to add extra node to an already existing XML. To add Orange with price $3.00, discount 0.3% and pid 328, this code applies
PHP
<?php
.
.
.
//Adding node starts from here
$sXML = new SimpleXMLElement($nXML); //Load the entire xml in
$newchild = $sXML->addChild("product");
//Notice am now using the $newchild object not the $sXML object
$newchild->addAttribute("pid", 328);
$newchild->addChild("name", "Orange");
$newchild->addChild("price", "$3.00");
$newchild->addChild("discount", "0.3%");
echo $sXML->asXML();
//Notice am now back to the $sXML object. The asXML() method is used to output the XML 
?>
This is named “Adding Node.php” in the downloads

Modifying a node in an existing XML (using DomDocument and DOMXPath)

Say the price of Apple changed from $1.00 to $2.00 (how I wish Apple iPad is sold for this, or are they not both apples) and the discount fell to 1%. Then you can modify the XML using DomDocument while using DOMXPath to find the node to modify.

PHP
<?php
.
.
.
    //Modifying Node starts from here
    // Create a new document fragment to hold the new <product> node
    $productId = 314;
    $parent = new DomDocument;
    $parent_node = $parent->createElement('product');
    
    //Add the pid attribute
    //Notice that the createAttribute() method was used on $parent
    $attribute = $parent->createAttribute("pid");
    //but appended to $parent_node
    $attribute->value = $productId;
    $parent_node->appendChild($attribute);
    
    // Add the child elements
    $parent_node->appendChild($parent->createElement('name', "Apple"));
    $parent_node->appendChild($parent->createElement('price', "$2.00"));
    $parent_node->appendChild($parent->createElement('discount', "1%"));

    //Append the $parent_node into $parent
    $parent->appendChild($parent_node);

    // Load the original XML to modify into a new DomDocument
    $dom = new DomDocument;
    $dom->loadXML($nXML);

    // Locate the old product node to modify
    $xpath = new DOMXpath($dom);
    $nodelist = $xpath->query("/products/product[@pid={$productId}]");
    
    $oldnode = $nodelist->item(0);
                
    // Load the $parent document fragment into the $dom
    $newnode = $dom->importNode($parent->documentElement, true);

    // Replace
    $oldnode->parentNode->replaceChild($newnode, $oldnode);
            
    echo $dom->saveXML();
    //Done output XML        
?>
</product>
This is named “Modifying Node.php” in the downloads

Deleting a node in an existing XML (using DomDocument and DOMXPath)

Say we are no longer selling mango and we have to remove it from the XML.

PHP
<?php
.
.
.
//Deleting Node of Mango
//Load the original XML to modify into a new DomDocument
$productId = 315;
$dom = new DomDocument;
$dom->loadXML($nXML);

// Locate the old product node to modify
$xpath = new DOMXpath($dom);
$nodelist = $xpath->query("/products/product[@pid={$productId}]");

$oldnode = $nodelist->item(0);

// Remove
$oldnode->parentNode->removeChild($oldnode);
   
echo $dom->saveXML();//Done output XML  
?>

This is named “Deleting Node.php” in the downloads

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)