JAXLXml – Strophe style XML Builder : Working with Jaxl – A Networking Library in PHP – Part 2

Prior to Jaxl v3.x, the most ugliest piece of code inside Jaxl library was handling of XML packets. If you are working with XMPP protocol which is all about sending and receiving XML packets, it can become a nightmare if you don’t have a proper XML manipulation library in your toolkit. For Jaxl v3.x, first thing I decided to write was JAXLXml class, which is a custom XML packet implementation with no external dependencies and is an extension over the ideas from Strophe.Builder class written by Jack Moffitt.

JAXLXml is generic enough to find a place inside any PHP application that requires easy and elegant XML packet creation. In this blog post, I will give an exhaustive overview of how to create XML packets using JAXLXml class.

JAXLXml Constructor
Depending upon the need, there are several different ways of initializing a JAXLXml object:

  • $xml_obj = new JAXLXml($name, $ns, $attrs, $text);
  • $xml_obj = new JAXLXml($name, $ns, $attrs);
  • $xml_obj = new JAXLXml($name, $ns, $text);
  • $xml_obj = new JAXLXml($name, $attrs, $text);
  • $xml_obj = new JAXLXml($name, $attrs);
  • $xml_obj = new JAXLXml($name, $ns);
  • $xml_obj = new JAXLXml($name);

where:

  • $name – the XML node name
  • $ns – the XML namespace
  • $attrs – Key-Value (KV) pair of XML attributes
  • $text – XML content

Here are a few examples for each constructor style shown above:

JAXLXml will sanitize attributes and text values as shown below:

Manipulating Attributes, Child Nodes and Content
Below is an exhaustive list of methods available over initialized JAXLXml object $xml_obj for manipulating attributes, child nodes and content:

  • c($name, $ns=null, $attrs=array(), $text=null) : Append a child node at current rover and update the rover to point at newly added child node. Rover is nothing but a pointer indicating the level in the XML tree where this and other methods will perform. When an JAXLXml instance is initialized, rover points to the top level node.
  • cnode($node) : Append a child node given by $node (a JAXLXml object) at current rover and update the rover to point at newly added child node.
  • t($text, $append=FALSE) : Update text of the node pointed by current rover
  • top() : Move rover back to the top in the XML tree
  • up() : Move rover one step up the XML tree
  • attrs($attrs) : Merge new attributes specified as KV pair $attrs with existing attributes at the current rover.
  • match_attrs($attrs) : Accepts a KV pair of attributes $attrs, return bool if all keys exist and have same value as specified in the passed KV pair.
  • exists($name, $ns=null, $attrs=array()) : Checks if a child with $name exist. If found, return matching child as JAXLXml object otherwise false. If multiple children exist with same name, this function will return on first matching child
  • update($name, $ns=null, $attrs=array(), $text=null) : Update $ns, $attrs and $text (all at once) of an existing child node $name
  • to_string($parent_ns=null) : Return string representation of JAXLXml object

Method Chaining
The best thing one will find while working with JAXLXml class is that all the above methods are chain-able i.e. Any complex XML structure can be built with a single line of code.

Here is an example building a fairly nested XML structure in a single line of code:

XML Parsing in PHP, XPATH way – The best I know so far

If you are a PHP developer, you surely must have done XML parsing at some stage or the other. Over the years I myself have implemented XML Parsing in atleast 3-4 different ways. Finally I have stuck to this approach which I personally find far more better than the rest, Not only because it’s quite simple but also because it’s extendable. By extendable I mean, you don’t have to touch your code if the XML structure changes at a later stage or if you need to parse a new node at a later stage in the project. In this blog post we will try to parse my twitter timeline, using the XPATH way. To start with let’s see how a my twitter timeline look like:

XML Source:
http://twitter.com/statuses/user_timeline/imoracle.xml
You may want to open this XML structure in a separate window of your browser for reference, as we walk through various XML parsing techniques.

Data Requirement:
Before we proceed to parse this twitter timeline, lets decide what all data do we want to extract out of the XML. Each <status></status> node consists of two parts. Information about the tweet and information about the user.

Lets finalize the following list of nodes which we want about the tweets and also their corresponding XPATH’s:

  1. id: ../statuses/status/id
  2. text: ../statuses/status/text
  3. source: ../statuses/status/source

Further lets zero out on list of nodes we want about the user details:

  1. id: ../statuses/status/user/id
  2. name: ../statuses/status/user/name
  3. screen_name: ../statuses/status/user/screen_name

XML Parsing:
Let us create a file called xpath.php, which will contain xpath of various nodes which we have finalized above. The xpath.php file will look like:

xpath.php

<?php

  $user_status = array(
                      'status_id' => '../statuses/status/id',
                      'status_text' => '../statuses/status/text',
                      'status_source' => '../statuses/status/source',
                      'user_id' => '../statuses/status/user/id',
                      'user_name' => '../statuses/status/user/name',
                      'user_screen_name' => '../statuses/status/user/screen_name'
                      );

?>

parser.php

<?php

  // include the xpath file
  require_once("xpath.php");

  // read the xml source as string
  $str = file_get_contents("imoracle.xml");

  // load the string as xml object
  $xml = simplexml_load_string($str);

  // initialize the return array
  $result = array();

  // parse the xml nodes
  foreach($user_status as $key => $xpath) {
    $values = $xml->xpath("{$xpath}");
    foreach($values as $value) {
      $result[$key][] = (string)$value;
    }
  }

  // print the return array
  print_r($result);

?>

Results:
If we try to print out this $result on a browser screen, here is how the result will look like:

Array
(
    [status_id] => Array
        (
            [0] => 2499838341
            [1] => 2499780899
            [2] => 2499724163
            [3] => 2499607183
        )

    [status_text] => Array
        (
            [0] => 13 Beautiful WordPress Showcase Sites
            [1] => 55 Really Creative And Unique Blog Design Showcase
            [2] => Need PHP symfony developer to complete tvguide.com clone
            [3] => 22 Open Source PHP Frameworks To Shorten Your Development Time
        )

    [status_source] => Array
        (
            [0] => <a href="http://apiwiki.twitter.com/">API</a>
            [1] => <a href="http://apiwiki.twitter.com/">API</a>
            [2] => <a href="http://apiwiki.twitter.com/">API</a>
            [3] => <a href="http://apiwiki.twitter.com/">API</a>
        )

    [user_id] => Array
        (
            [0] => 14574588
            [1] => 14574588
            [2] => 14574588
            [3] => 14574588
        )

    [user_name] => Array
        (
            [0] => Abhinav Singh
            [1] => Abhinav Singh
            [2] => Abhinav Singh
            [3] => Abhinav Singh
        )

    [user_screen_name] => Array
        (
            [0] => imoracle
            [1] => imoracle
            [2] => imoracle
            [3] => imoracle
        )

)

The Best Part:
The best part of this approach is that, suppose in future our project demands extraction of the following nodes too:

  1. truncated: ../statuses/status/truncated
  2. favorited: ../statuses/status/truncated ../statuses/status/favorited
  3. location: ../statuses/status/user/location
  4. description: ../statuses/status/user/description

All we need to do is, simply add these xpaths in xpath.php file, without having to change the parser.php file. In case of a project you may want to create a function or a class out of the parser.php file so that you can request data from that.

Download the source code from here:
http://abhinavsingh.googlecode.com/files/xml-parser-xpath-way.rar

If you liked the post, do not forget to leave a comment and follow me on twitter.
Do let me know of better methods if you know any. Happy XML Parsing!