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
- Writing XML from scratch
- Reading data from XML
- Adding node to existing XML
- Modifying a node in existing XML
- 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:
="1.0"
<Customer>
<id>1</id>
<name>Oluwafemi</name>
<address>Cresent Drive, TX</address>
</Customer>
Simple Example
This can approached with XMLWriter:
<?php
$xml = new XMLWriter();
$xml->openMemory();
$xml->startDocument();
$xml->startElement("Customer");
$xml->writeElement("id", "1");
$xml->writeElement("name", "Oluwafemi");
$xml->writeElement("address", "Cresent Drive, TX");
$xml->endElement();
echo $xml->outputMemory();
?>
This is named “Simple - XMLWriter.php” in the downloads
A little complex example is to write this 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
$xml = new XMLWriter();
$xml->openMemory();
$xml->startDocument();
$xml->startElement("purchase");
$xml->startElement("customer");
$xml->writeElement("id", 1);
$xml->writeElement("time", "2013-04-19 10:56:03");
$xml->writeElement("total", "$350");
$xml->endElement();
$xml->startElement("customer");
$xml->writeElement("id", 2);
$xml->writeElement("time", "2013-04-23 13:43:41");
$xml->writeElement("total", "$1456");
$xml->endElement();
$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:
="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
$xml = new XMLWriter();
$xml->openMemory();
$xml->startDocument();
$xml->startElement("products");
$xml->startElement("product");
$xml->writeAttribute("pid", 314);
$xml->writeElement("name", "Apple");
$xml->writeElement("price", "$1.00");
$xml->writeElement("discount", "3%");
$xml->endElement();
$xml->startElement("product");
$xml->writeAttribute("pid", 315);
$xml->writeElement("name", "Mango");
$xml->writeElement("price", "$0.90");
$xml->writeElement("discount", "3%");
$xml->endElement();
$xml->endElement();
echo $xml->outputMemory();
?>
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
.
.
.
$rxml = new XMLReader();
$rxml->xml($nXML);
while($rxml->read() && $rxml->name !== 'customer');
$amountSpent = 0;
while($rxml->name === 'customer')
{
$node = new SimpleXMLElement($rxml->readOuterXML());
if($node->id == 1)
{
$amountSpent = $node->total;
break;
}
$rxml->next('customer');
}
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
$rxml = new XMLReader();
$rxml->xml($nXML);
while($rxml->read() && $rxml->name !== 'product');
$name = "";
$price = "";
$discount = "";
while($rxml->name === 'product')
{
if($rxml->getAttribute("pid") == "315")
{
$node = new SimpleXMLElement($rxml->readOuterXML());
$name = $node->name;
$price = $node->price;
$discount = $node->discount;
break;
}
$rxml->next('product');
}
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
). 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
.
.
.
$sXML = new SimpleXMLElement($nXML);
$newchild = $sXML->addChild("product");
$newchild->addAttribute("pid", 328);
$newchild->addChild("name", "Orange");
$newchild->addChild("price", "$3.00");
$newchild->addChild("discount", "0.3%");
echo $sXML->asXML();
?>
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
.
.
.
$productId = 314;
$parent = new DomDocument;
$parent_node = $parent->createElement('product');
$attribute = $parent->createAttribute("pid");
$attribute->value = $productId;
$parent_node->appendChild($attribute);
$parent_node->appendChild($parent->createElement('name', "Apple"));
$parent_node->appendChild($parent->createElement('price', "$2.00"));
$parent_node->appendChild($parent->createElement('discount', "1%"));
$parent->appendChild($parent_node);
$dom = new DomDocument;
$dom->loadXML($nXML);
$xpath = new DOMXpath($dom);
$nodelist = $xpath->query("/products/product[@pid={$productId}]");
$oldnode = $nodelist->item(0);
$newnode = $dom->importNode($parent->documentElement, true);
$oldnode->parentNode->replaceChild($newnode, $oldnode);
echo $dom->saveXML();
?>
</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
.
.
.
$productId = 315;
$dom = new DomDocument;
$dom->loadXML($nXML);
$xpath = new DOMXpath($dom);
$nodelist = $xpath->query("/products/product[@pid={$productId}]");
$oldnode = $nodelist->item(0);
$oldnode->parentNode->removeChild($oldnode);
echo $dom->saveXML();
?>
This is named “Deleting Node.php” in the downloads