July 23rd, 2004

SimpleXML and Xpath in Php5

0 comments on 3031 words

I’m assuming if you’re reading this article that you know what XML is and the options it offers. If not, then I would suggest you visit “Xml.com”:http://www.xml.com or “w3”:http://www.w3.org/XML/ among other helpful resources. Without further delay, lets get into SimpleXML and how to perform some basic operations using this simple, but powerful extension.

Lets start by looking at this simple xml document called applications.xml.

Photoshop Adobe Dreamweaver Macromedia Illustrator Adobe

Now this is a fairly simple document, and SimpleXML can breeze through this. Lets look at how its done.

Lets look at how simpleXML transforms XML documents.

Would output and Array of objects like so:

SimpleXMLElement Object ( [app] => Array ( [0] => SimpleXMLElement Object ( [name] => Photoshop [creator] => Adobe )

        [1] => SimpleXMLElement Object
            (
                [name] => Dreamweaver
                [creator] => Macromedia
            )

        [2] => SimpleXMLElement Object
            (
                [name] => Illustrator
                [creator] => Adobe
            )

    )

)

Now assuming we only wanted to load this document and print its contents to the page without any filtering we could use the following.

name . ”
”; echo ‘Application Creator: ’ . $app->creator . ”

”; } ?>

Will output :

Application Name: Photoshop Application Creator: Adobe

Application Name: Dreamweaver Application Creator: Macromedia

Application Name: Illustrator Application Creator: Adobe

That seems simple enough, what if we only wanted to print the second applications name? Since the data is handled as an object array, this is very easy.

app[1]->name; ?>

h3. Working with Attributes

Now that we know how to parse simple xml documents, what about working with attributes? Lets reformat our xml file a bit and add some attributes.

Photoshop Adobe Dreamweaver Macromedia Illustrator Adobe

Now assuming we wanted to print the name of the application and the id we would apply the following technique.

foreach($apps as $app) { echo $app->name . ‘:’ . $app[‘id’] . “\n”; } ?>

Woud output:

Photoshop:1 Dreamweaver:2 Illustrator:3

“Continue to Next Page: Xpath - Xml’s SQL >>”:http://www.isolated-designs.net/core/article/25/simplexml-and-xpath-in-php5/?pg=2

[page]

h2. Xpath: Xml’s SQL

Now if we really wanted to get into real world examples and apply logic to our output then we can use “Xpath”:http://www.w3.org/TR/xpath . Xpath is an extremley powerful way to ‘query’ an xml document. Xpath is a language eployed by many Xml Technologies such as XSLT, XPointer, and XForms as a way to seek out information(or, more precisely, nodes) in an XML document. Xpath is the scout of the XML world.

The Location Step A ‘location step’ in Xpath allows you to locate a node in the xml document. These steps are primarily what you will use when working with Xpath expressions. There are three parts of a location step.

  • Axis - Axis deal with relationships. It defines the relationship of the nodes you are targeting with respect to the context node.
  • Node Test - The Node test focuses on identification. Within the nodes that were selected by the Axis, the node test identifies the specific nodes that can meet certain conditions.
  • Predictate - A filter that allows you to optionally filter out some of the unwanted nodes that are returned by the axis and node test.

The location step:

@axis:nodetest[predictate]@

Xpath by itself is a rather hefty topic, and I don’t want to bloat this article with all of the lingo, but if you would like more information, then feel free to visit the following websites. “Zvon.org”:http://www.zvon.org/xxl/XPathTutorial/General/examples.html “VbXml.com”:http://www.vbxml.com/xsl/tutorials/intro/default.asp “Xml.com Tips”:http://www.xml.com/pub/a/2002/08/14/xpath_tips.html

Using SimpleXML with Xpath

Again we are going to be using our applications.xml document. Now lets assume we want to select the Application who’s id was 2. We would apply the following code.

==

xpath(“//app[@id = 2]”); //Select the app who’s id is equal to 2 echo $dw[0]->name; ?>

==

Now we can use a variety of logical operators. Lets assume we wanted to select the nodes who’s id was not equal to 2.

==

xpath(“//app[@id != 2]”);

foreach($nodes as $node) { echo $node->name . “\n”; } ?>

==

Operators that can be used:

  • < Less Than
  • > Creater Than
  • >= Greater than or Equal to
  • <= Less than or Equal to
  • = Equals
  • != Not Equal

Targeting nodes using 'and'

==

xpath(“//app[creator = ‘Adobe’ and name=’Photoshop’]”); foreach($nodes as $node) { echo $node->name . “\n”; }

//Returns Photoshop //Note that && or & will not work ?>

==

Targeting nodes with ‘or’

==

xpath(“//app[creator = ‘Adobe’ or name=’Dreamweaver’]”); foreach($nodes as $node) { echo $node->name . “\n”; } /* Will return: Photoshop Dreamweaver Illustrator

Note that || or | will not work */

?>

Counting returned nodes using Php’s count() function :

xpath(“//app[@type = ‘design’]”)); //Returns 2

//Count the app nodes who’s name child is equal to ‘Photoshop’ $nodes = count($apps->xpath(“//app[name = ‘Photoshop’]”)); //Returns 1

//Note that Xpath also has a built in count function which I could not get to work, Will post more on this later. ?>

Conditional Testing

xpath(“//app[name = ‘Photoshop’]”)) { echo $photoshop[0]->asXML(); } else { echo ‘Not Found!’; } /* Returns Photoshop Adobe */ $apps = simplexml_load_string($xml); if($photoshop = $apps->xpath(“//app[name = ‘foo’]”)) { echo $photoshop[0]->asXML(); } else { echo ‘Not Found!’; } /* Returns: Not Found! */ ?> == h3. Editing Nodes and Attributes using SimpleXML Not only can you read and filter XML documents, you can also edit the xml data as well. == xpath(“//app[name=’Photoshop’]”); //Set the name text to Photoshop CS $ps_nodes[0]->name = ‘Photoshop CS’; //Set the apps type attribute $ps_nodes[0][‘type’] = ‘Photography and Design’; //Print the Results as XML echo $apps->asXML(); /* Returns Photoshop CS Adobe Dreamweaver Macromedia Illustrator Adobe */ ?>

This might not prove to be much use unless you can write that infromation back to the file in which it came from. Unfortunatley simplexml_load_file can’t be used as a filepointer and also simpleXML doesn’t provide a method for saving documents. If you’d like to save the xml back to a a file you will need to use the fopen() and fwrite functions.

We could append this to the above statements to save our edited file.

asXML()); fclose($fp); ?>

==

“Continue to Next Page: Using Xpath Functions with SimpleXML >>”:http://www.isolated-designs.net/core/article/25/simplexml-and-xpath-in-php5/?pg=3

[page]

h2. Using XPath Functions with SimpleXML

For a complete list of the Xpath functions visit “W3Schools”:http://www.w3schools.com/xpath/xpath_functions.asp Note that not all Xpath functions will work with SimpleXML. I’ll be listing the functions below that I have tested and prove to work.

The following examples are basic usage of some common functions in XPath and SimpleXML.

Using the _starts-with()_ function

==

starts-with(str, substr)
Returns true if argument 1 starts with artument 2
== == xpath(“app[starts-with(name, ‘Photo’)]”); echo $photoshop[0]->name . “\n”; echo $photoshop[0]->creator; /*Returns Photoshop Adobe Using print_r($photoshop) returns: Array ( [0] => SimpleXMLElement Object ( [name] => Photoshop [creator] => Adobe ) ) //See example below for more information on this */ ?> == From the above example note that the statements below will not work, and thus are not the same as using the statements above. == xpath(“//app/name[starts-with(., ‘Photo’)]”); print_r($nodes); /* Returns Array ( [0] => SimpleXMLElement Object ( [0] => Photoshop ) ) */ foreach($nodes as $node) { echo $node->asXML(); //Returns Photoshop echo $node->name; //Nothing echo $node->name[0]; //Nothing echo $node[0]; //Nothing echo $node[0]->name; //Nothing echo $name[0]; //Nothing echo $name; //Nothing echo $node[0][0]; //Nothing } ?>
contains(str, substr)
Returns true if the first argument contains the second argument

xpath(“//app[contains(@type, ‘dev’)]”); print_r($nodes);

/* RETURNS Array ( [0] => SimpleXMLElement Object ( [name] => Dreamweaver [creator] => Macromedia )

) */ ?>

==

This article will be appended to shortly

Note: Due to the way TextPattern formats articles, some of the html formatting will be wrong. For instance “n” should be “*slash* n” and also the & symbol is being replaced.

Sorry, comments are closed for this article.