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
You can just grab the sample codes, they are well commented
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).
startDocument()
<?xml version="1.0"?> <Customer> <id>1</id> <name>Oluwafemi</name> <address>Cresent Drive, TX</address> </Customer>
This can approached with XMLWriter:
<?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 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>
This piece of code solves the puzzle:
<?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:
<product>
<?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>
This can also be achieved with XMLWriter:
<?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 ?>
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”);.
open()
xml()
open(“c:/…/this.xml”);
open(“http://example.com/this.xml”);
SimpleXMLElement can be used to extract data from the “node xml” gotten from XMLReader.
XMLReader
To get the total amount spent by the customer whose id is 1 in the Little complex example above
<?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; ?>
And to get the name, price, and discount of the product with pid=315 from More complex example above
/* 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"; ?>
<?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 ?>
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.
DomDocument
DOMXPath
<?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>
Say we are no longer selling mango and we have to remove it from the XML.
<?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