Working with XML Documents in PHP jQuery

Exclusive offer: get 50% off this eBook here
PHP jQuery Cookbook

PHP jQuery Cookbook — Save 50%

Over 60 simple but highly effective recipes to create interactive web applications using PHP with jQuery

$23.99    $12.00
by Vijay Joshi | December 2010 | Open Source PHP

In this article, by Vijay Joshi, author of PHP jQuery Cookbook, we will cover:

  • Loading XML from files and strings using SimpleXML
  • Accessing elements and attributes using SimpleXML
  • Searching elements using XPath
  • Reading an XML using DOM extension
  • Creating an XML using DOM extension
  • Modifying an XML using DOM extension
  • Parsing XML with jQuery

 

PHP jQuery Cookbook

PHP jQuery Cookbook

Over 60 simple but highly effective recipes to create interactive web applications using PHP with jQuery

  • Create rich and interactive web applications with PHP and jQuery
  • Debug and execute jQuery code on a live site
  • Design interactive forms and menus
  • Another title in the Packt Cookbook range, which will help you get to grips with PHP as well as jQuery
        Read more about this book      

(For more resources on this subject, see here.)

Introduction

Extensible Markup Language—also known as XML—is a structure for representation of data in human readable format. Contrary to its name, it's actually not a language but a markup which focuses on data and its structure. XML is a lot like HTML in syntax except that where HTML is used for presentation of data, XML is used for storing and data interchange.

Moreover, all the tags in an XML are user-defined and can be formatted according to one's will. But an XML must follow the specification recommended by W3C.

With a large increase in distributed applications over the internet, XML is the most widely used method of data interchange between applications. Web services use XML to carry and exchange data between applications. Since XML is platform-independent and is stored in string format, applications using different server-side technologies can communicate with each other using XML.

Consider the following XML document:

From the above document, we can infer that it is a list of websites containing data about the name, URL, and some information about each website.

PHP has several classes and functions available for working with XML documents. You can read, write, modify, and query documents easily using these functions.

In this article, we will discuss SimpleXML functions and DOMDocument class of PHP for manipulating XML documents. You will learn how to read and modify XML files, using SimpleXML as well as DOM API. We will also explore the XPath method, which makes traversing documents a lot easier.

Note that an XML must be well-formed and valid before we can do anything with it. There are many rules that define well-formedness of XML out of which a few are given below:

  • An XML document must have a single root element.
  • There cannot be special characters like <, >, and soon.
  • Each XML tag must have a corresponding closing tag.
  • Tags are case sensitive

To know more about validity of an XML, you can refer to this link:
http://en.wikipedia.org/wiki/XML#Schemas_and_validation

For most of the recipes in this article, we will use an already created XML file. Create a new file, save it as common.xml in the Article3 directory. Put the following contents in this file.

<?xml version="1.0"?>
<books>
<book index="1">
<name year="1892">The Adventures of Sherlock Holmes</name>
<story>
<title>A Scandal in Bohemia</title>
<quote>You see, but you do not observe. The distinction
is clear.</quote>
</story>
<story>
<title>The Red-headed League</title>
<quote>It is quite a three pipe problem, and I beg that you
won't speak to me for fifty minutes.</quote>
</story>
<story>
<title>The Man with the Twisted Lip</title>
<quote>It is, of course, a trifle, but there is nothing so
important as trifles.</quote>
</story>
</book>
<book index="2">
<name year="1927">The Case-book of Sherlock Holmes</name>
<story>
<title>The Adventure of the Three Gables</title>
<quote>I am not the law, but I represent justice so far as
my feeble powers go.</quote>
</story>
<story>
<title>The Problem of Thor Bridge</title>
<quote>We must look for consistency. Where there is a want
of it we must suspect deception.</quote>
</story>
<story>
<title>The Adventure of Shoscombe Old Place</title>
<quote>Dogs don't make mistakes.</quote>
</story>
</book>
<book index="3">
<name year="1893">The Memoirs of Sherlock Holmes</name>
<story>
<title>The Yellow Face</title>
<quote>Any truth is better than indefinite doubt.</quote>
</story>
<story>
<title>The Stockbroker's Clerk</title>
<quote>Results without causes are much more impressive. </quote>
</story>
<story>
<title>The Final Problem</title>
<quote>If I were assured of your eventual destruction I would,
in the interests of the public, cheerfully accept my
own.</quote>
</story>
</book>
</books>

Loading XML from files and strings using SimpleXML

True to its name, SimpleXML functions provide an easy way to access data from XML documents. XML files or strings can be converted into objects, and data can be read from them.

We will see how to load an XML from a file or string using SimpleXML functions. You will also learn how to handle errors in XML documents.

Getting ready

Create a new directory named Article3. This article will contain sub-folders for each recipe. So, create another folder named Recipe1 inside it.

How to do it...

  1. Create a file named index.php in Recipe1 folder. In this file, write the PHP code that will try to load the common.xml file. On loading it successfully, it will display a list of book names. We have also used the libxml functions that will detect any error and will show its detailed description on the screen.

    <?php
    libxml_use_internal_errors(true);
    $objXML = simplexml_load_file('../common.xml');

    if (!$objXML)
    {
    $errors = libxml_get_errors();
    foreach($errors as $error)
    {
    echo $error->message,'<br/>';
    }
    }
    else
    {
    foreach($objXML->book as $book)
    {
    echo $book->name.'<br/>';
    }
    }
    ?>

  2. Open your browser and point it to the index.php file. Because we have already validated the XML file, you will see the following output on the screen:
    The Adventures of Sherlock Holmes
    The Case-book of Sherlock Holmes
    The Memoirs of Sherlock Holmes
  3. Let us corrupt the XML file now. For this, open the common.xml file and delete any node name. Save this file and reload index.php on your browser. You will see a detailed error description on your screen:

How it works...

In the first line, passing a true value to the libxml_use_internal_errors function will suppress any XML errors and will allow us to handle errors from the code itself. The second line tries to load the specified XML using the simplexml_load_file function. If the XML is loaded successfully, it is converted into a SimpleXMLElement object otherwise a false value is returned.

We then check for the return value. If it is false, we use the libxml_get_errors() function to get all the errors in the form of an array. This array contains objects of type LibXMLError. Each of these objects has several properties. In the previous code, we iterated over the errors array and echoed the message property of each object which contains a detailed error message.

If there are no errors in XML, we get a SimpleXMLElement object which has all the XML data loaded in it.

There's more...

Parameters for simplexml_load_file

More parameters are available for the simplexml_load_file method, which are as follows:

  • filename: This is the first parameter that is mandatory. It can be a path to a local XML file or a URL.
  • class_name: You can extend the SimpleXMLElement class. In that case, you can specify that class name here and it will return the object of that class. This parameter is optional.
  • options: This third parameter allows you to specify libxml parameters for more control over how the XML is handled while loading. This is also optional.

simplexml_load_string

Similar to simplexml_load_file is simplexml_load_string, which also creates a SimpleXMLElement on successful execution. If a valid XML string is passed to it we get a SimpleXMLElement object or a false value otherwise.

$objXML = simplexml_load_string('<?xml version="1.0"?><book><name>
Myfavourite book</name></book>');

The above code will return a SimpleXMLElement object with data loaded from the XML string. The second and third parameters of this function are same as that of simplexml_load_file.

Using SimpleXMLElement to create an object

You can also use the constructor of the SimpleXMLElement class to create a new object.

$objXML = new SimpleXMLElement('<?xml version="1.0"?><book><name>
Myfavourite book</name></book>');

More info about SimpleXML and libxml

You can read about SimpleXML in more detail on the PHP site at http://php.net/manual/en/book.simplexml.php and about libxml at http://php.net/manual/en/book.libxml.php.

PHP jQuery Cookbook Over 60 simple but highly effective recipes to create interactive web applications using PHP with jQuery
Published: December 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on this subject, see here.)

Accessing elements and attributes using SimpleXML

This recipe will explain how we can get the values of node and/or attributes from an XML file using SimpleXML methods. We will write an example using our common.xml file.

Getting ready

Create a folder for this recipe in Article3 directory and name it Recipe2.

How to do it...

  1. Create a new file named index.php in Recipe2 folder. In this file, create a select box and create its options, which will be the names of books in the common.xml file. Next, create two buttons that will get the publication year and list of stories in the selected book. Each of these buttons has an ID attribute that will be used to distinguish between clicked buttons. After that, create a paragraph element to display the result.

    <html>
    <head><title>Accessing node and attribute values</title></head>
    <body>
    <p>
    <select id="bookList">
    <option value="">select a book</option>
    <?php
    $objXML = simplexml_load_file('../common.xml');
    foreach($objXML->book as $book)
    {
    echo '<option value="'.$book['index'].'">'.$book->name.'
    </option>';
    }

    ?>
    </select>
    <input type="button" id="year" value="Get Year of publication"/>
    <input type="button" id="stories" value="Get story list"/>
    </p>
    <p id="result"></p>
    </body>
    </html>

  2. We will use jQuery to get the selected values from the form and send an AJAX request to a file that will process the selected values and will send back the result accordingly. For this, we will write some jQuery code, just before closing of &ltbody> tag. Include the jQuery library using the correct path, and then register event handlers for input buttons. On click of a button, handler function will send an AJAX request to a PHP file with values of the selected book and the clicked button. Received response will be inserted into the paragraph with ID result.

    <script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../jquery.js"></script>
    <script type="text/javascript">
    $(document).ready(function ()
    {
    $('input:button').click(function()
    {
    if($('#bookList').val() != '')
    {
    $.get(
    'process.php',
    { id: $('#bookList').val() , action: $(this).attr('id')
    },
    function(data)
    {
    $('#result').html(data);
    });
    }
    });
    });
    </script>

  3. Now, create the process.php file in the same directory. This file gets the values of selected book and clicked button from the $_GET Superglobal. The common.xml file is loaded and depending on the value of action and ID variables in $_GET array, books are iterated upon and a response variable is created that is echoed to the browser.

    <?php
    $bookId = $_GET['id'];
    $action = $_GET['action'];
    $strResponse;
    $objXML = simplexml_load_file('../common.xml');
    foreach($objXML->book as $book)
    {

    if($book['index'] == $bookId)
    {
    if($action == 'year')
    {
    $strResponse = 'This book was published in year:'.
    $book->name['year'];
    }
    else if($action == 'stories')
    {
    $stories = $book->story;
    $strResponse = '<ul>';
    foreach($stories as $story)
    {
    $strResponse.= '<li>'. $story->title. '</li>';;
    }
    $strResponse.= '</ul>';
    }
    else
    {
    $strResponse = 'Nothing to do';
    }
    break;
    }
    }
    echo $strResponse;
    ?>

  4. Run your browser and point it to the index.php file. You will see a combo box and two buttons. Select a book from the combo box and click any of these buttons. The following image shows a list of stories that gets displayed after selecting a book and clicking on the Get story list button.

How it works...

To get the value of a node we can refer it by its name as a property of the SimpleXMLElement object. In the index.php file, we created a SimpleXMLElement object from the common.xml file by loading it through the simplexml_load_file method. Since there are multiple book nodes, we get an array of these in our object on which we can loop like a normal array. Similarly, attributes of a node can be fetched like values from arrays, using the attribute name as an index of an associative array.

For each book, we created an option element with its value set to the index attribute and text set to the value of name node. The way we selected these values shows us how easy it is to fetch values using SimpleXML methods.

The jQuery code registers event handlers for each of the two buttons as shown in the previous screenshot. Clicking on a button gets the value of the selected book and the clicked button and sends it to the process.php file, using jQuery's $.get() method.

The values sent by jQuery are available in $_GET superglobal. These values are stored in PHP variables; $bookId and $action. Then we load the XML file and we have a SimpleXMLElement object available to us in the form of $objXML.

To determine the selected book, we can iterate over each book element and check if its index attribute matches the $bookId variable. When a match is found we check the value of $action variable. If $action is "year", we get the year attribute from the book's name that is stored in the $strResponse variable.

If $action is set to "stories", we get the array of the story object from the current $book object. Then we iterate over this array and create an unordered list for each story name and store it in $strResponse.

Finally, we echo the $strResponse variable to the browser where it is filled in a paragraph by jQuery.

There's more...

Modifying an XML with SimpleXML

Values of node in an existing XML can also be modified using SimpleXML functions. For example, if we have to change the name of the first book in our common.xml file, we can do so by using the following code:

$objXML->book[0]->name = 'New name for book';
$result = $objXML->asXML();

If no parameter is passed to asXML() method, it will return the modified XML in the form of a string, false in case of failure. A filename can also be passed to asXML() in which case it will write the resulting XML to that file.

Adding elements to an XML

New elements can also be added to an XML as shown in the following code:

$objXML->book[0]->addChild('remark','Stories in this novel were
narrated by Sherlock Holmes himself');
$objXML->book[0]->remark->addAttribute('totalStories','13');
$result = $objXML->asXML();

This code will add a remark node as the first book element and also add a totalStories attribute to it.

Do not forget that the resulting XML will be stored in $result variable and not in the original XML file, though you can save it to original XML also by specifying the filename to asXML, as explained in the previous section.

Searching elements using XPath

XPath or the XML Path is used to navigate an XML document. It is basically a query language that provides a standard set of expressions and functions for traversing a document tree. XPath operates on a document tree and can be used for functions, such as searching, comparing, and so on in a document.

PHP has built-in support for using XPath. This recipe will explain some concepts of XPath and how they can be used to get information from XML.

Using the common.xml file we will write a simple example that will demonstrate the capabilities of XPath.

Getting ready

Like earlier recipes, create a separate folder named Recipe3 inside the Article3 directory.

How to do it...

  1. Create an HTML file and name it index.html. Create four buttons that will be used to show different usage of XPath. Also, create an empty DIV element for displaying the result. Also, define some CSS in the &lthead> section for better display.

    <html>
    <head>
    <title>Using XPath</title>
    <style type="text/css">
    ul{border:1px solid black;padding:5px;
    list-style:none;width:550px;}
    label{font-weight:bold;}
    li{ padding:5px;}
    </style>
    </head>
    <body>
    <input type="button" value="Show all books" id="all"/>
    <input type="button" value="Show stories with quotes"
    id="total"/>
    <input type="button" value="Get last book" id="last"/>
    <input type="button" value="Books with year <1900" id="year"/>

    <div id="result"></div>
    </body>
    </html>

  2. Include the jQuery library and write the jQuery code that will send an AJAX request to a PHP file, process.php. The request will contain the ID of the clicked button for processing on the server side. Response from the PHP script will be inserted into the DIV element.

    <script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../jquery.js"></script>
    <script type="text/javascript">
    $(document).ready(function ()
    {
    $('input:button').click(function()
    {
    $.get(
    'process.php',
    { action: $(this).attr('id')},
    function(data)
    {
    $('#result').html(data);
    });
    });
    });
    </script>

  3. Switching to the server side now, create a PHP file, process.php, in the same directory. This file will load the XML file and will perform appropriate actions depending on the value of the clicked button. It will use the xpath method to search the document and echo the result back to the browser. This response will be inserted into a page by jQuery.

    <?php
    $objXML = simplexml_load_file('../common.xml');
    if (!$objXML)
    {
    echo 'Error loading xml';
    }
    else
    {
    $response = '';
    $action = $_GET['action'];
    switch($action)
    {
    case 'all':
    $book = $objXML->xpath('//book/name');
    $response.= '<ul>';
    foreach ($book as $item)
    {
    $response.= '<li>';
    $response.= $item[0].' ('.$item['year'].')';
    $response.= '</li>';
    }
    $response.= '</ul>';
    break;
    case 'total':
    $response.= '<ul>';
    $stories = $objXML->xpath('//story');
    foreach ($stories as $story)
    {
    $response.= '<li>';
    $response.= '<label>'.$story->title.'</label>
    <br/><em>'.$story->quote.'</em>';
    $response.= '</li>';
    }
    $response.= '</ul>';
    break;

    case 'last':
    $lastElement = $objXML->xpath('//book[last()]');
    echo '<strong>'.$lastElement[0]->name.'
    ('.$lastElement[0]->name['year'].')</strong>';
    break;

    case 'year':
    $book = $objXML->xpath('//book/name[@year<1900]');
    $response.= '<ul>';
    foreach($book as $item)
    {
    $response.= '<li>';
    $response.= $item.' ('.$item['year'].')';
    $response.= '</li>';
    }
    $response.= '</ul>';
    break;
    }
    echo $response;
    }
    ?>

  4. Run the index.php file and click on any buttons. The AJAX request will be fired, which will then go to process.php and the result will be displayed on the page. For example, clicking on the last button will show the books that have year value less than 1900.

How it works...

We have defined four buttons here. The first button for getting the names and years of all books, the second one for displaying list of all the stories and quotes regardless of book, the third one is for getting the name and year of the last book and the fourth button for displaying all those books that have the value of year attribute less than 1900.

We have also provided four different IDs to each of these buttons that include all, total, last, and year respectively.

Clicking a button sends that button's ID in an AJAX request to process.php file where ID of the clicked button is retrieved and stored in a variable called $action. We have already loaded the common.xml file in $objXML variable. Next is a switch statement that executes the case matching the ID.

SimpleXML provides the xpath method for running XPath queries on a loaded document. xpath method takes an XPath query as a parameter and returns an array of SimpleXML elements on successful execution, false on failure.

Expression //book will select all book elements in the document, regardless of their position.

Expression //book/name selects all name elements that are children of book elements in the whole document.

//book[last()] selects the last book element in the document.

Expression //book/name[@year&lt1900] looks like a complex one but is actually not the case. Just try breaking it in parts. @ refers to an attribute. Hence, this expression will select all the name elements under book elements that have a name attribute with year value less then 1900. In this case, only two books qualify—the first and the last one. The second book has year 1927, hence it does not qualify for selection.

We then format the results by putting some HTML tags around them and return the result back to the browser.

There's more...

More info about XPath

Here are some online resources where you can learn more about the XPath syntax and its usage:

PHP jQuery Cookbook Over 60 simple but highly effective recipes to create interactive web applications using PHP with jQuery
Published: December 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on this subject, see here.)

Reading an XML using DOM extension

In this recipe, you will see the use of PHP's DOM extension to read an XML and extract information from it. We will create an example where we will display a list of books.

Clicking a book name will reveal the list of stories in that book.

Getting ready

Create a folder Recipe4 in the Articler3 directory and make sure you have common.xml file accessible.

How to do it...

  1. Create an index.php file in the Recipe4 folder. In the HTML markup, write the PHP code that will load the XML using DOM methods. From the loaded XML, create h1 sections that will contain the book name and its publication year.
  2. Under each h1, create an unordered list of stories in that book. Note that in the &lthead> section, we have hidden ul using display property. Therefore, on the page only book names will be visible.

    <html>
    <head>
    <title>Using DOM</title>
    <style type="text/css">
    h1{ cursor:pointer;font-size:20px;}
    ul{ display:none; list-style:none;margin:0pt;padding:0pt;}
    </style>
    </head>
    <body>
    <?php
    $objXML = new DOMDocument();
    $objXML->load('../common.xml', LIBXML_NOBLANKS);
    $books = $objXML->getElementsByTagName('book');
    foreach($books as $book)
    {
    echo '<h1>'.$book->firstChild->nodeValue.'
    ('.$book->firstChild->attributes->item(0)->value.')</h1>';
    $stories = $book->getElementsByTagName('story');
    echo '<ul>';
    foreach($stories as $story)
    {
    echo '<li>'.$story->firstChild->nodeValue.'</li>';
    }
    echo '</ul>';
    }
    ?>
    </body>
    </html>

  3. To spice up our example, we will write some jQuery code that will be used to show the list of stories in each book. An event handler will be attached to each book name that will show or hide stories.
  4. <script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../jquery.js"></script>
    <script type="text/javascript">
    $(document).ready(function ()
    {
    $('h1').click(function()
    {
    $(this).next('ul').toggle('fast');
    });
    });
    </script>

  5. Run the file in your browser and you will be presented with the list of books. Clicking a book name will toggle the list of stories in that book with animation.

How it works...

First, we create an object $objXML of the DOMDocument class. This class provides a number of properties and methods that can be used to manipulate an XML file. Names of nodes, their values, attributes, and so on, can be extracted from an XML file.

Then, we use the load method on the $objXML. load() method takes two parameters. First is the file name and the second parameter is libxml option constants. The second parameter is optional. We pass common.xml as the first parameter and LIBXML_NOBLANKS as the second one. We also pass LIBXML_NOBLANKS because we do not want any blank nodes to appear.

Because we want to access all the book nodes, we use the getElementsByTagName method and pass a book to it that returns a DOMNodeList object. A foreach loop has been used to iterate in this collection. There are several methods available to objects of the DOMNode class. We have used some of them here.

The firstChild property gives us the immediate first child which is book node in our case. nodeValue gives us the value inside the book tag, which is the name of book. We wrap it in an h1 element.

To access the attribute, we use the attributes property. Attributes gives a map of all the attributes. We can navigate in this attribute collection using the item property. We retrieved the value of attribute at 0th position and that gives us the value of the year attribute.

Similarly, to get the list of stories for a book, we use getElementsByTagName again and then iterated in it for value of each book title.

Finally, we wrap it into an unordered list.

After the DOM is ready on the browser, the jQuery code attaches a click event handler to each h1 element on the page. Clicking on an h1 element toggles its next ul element.

There's more...

Getting child nodes

We can also check if a node has child nodes and can also fetch them. In the above example, to get the child nodes of a book use the following code:

if($book->hasChildNodes())
{
$children = $book->childNodes;
}

nodeType, nodeName, and nodeValue

When you are not familiar with the XML structure or if it is inconsistent, you can determine the name and values of nodes and attributes at run time itself.

$node->nodeType
$node->nodeName
$node->nodeValue

nodeType may return different values depending on node. These values are libxml constants. Some common values for nodeType are as follows:

  • XML_ELEMENT_NODE
  • XML_ATTRIBUTE_NODE
  • XML_TEXT_NODE
  • XML_CDATA_SECTION_NODE

Using Xpath

Creating an XML using DOM extension

DOM extension gives us the ability to create whole new documents using its numerous functions. In this recipe you will learn how to create new XML documents using DOM functions. As you know we have multiple book elements in our common.xml file, we will create a similar book element with name and story elements using DOM methods.

Getting ready

Create a new folder Recipe5 in the Article3 directory.

How to do it…

  1. Create a file and name it index.php in the Recipe5 folder.
  2. Write the PHP code that will create a new XML document, then create some elements and add these to the new document. Some of these elements will have text as well as attributes and their values. Finally, this XML will be saved on the disk.

    <?php
    $objXML = new DOMDocument('1.0', 'utf-8'); /* <?xml
    version="1.0" encoding="UTF-8" ?> */
    $books = $objXML->createElement('books');//books

    $book = $objXML->createElement('book');
    $attrIndex = new DOMAttr("index", "4");
    $book->appendChild($attrIndex);
    $bookName = $objXML->createElement('name','The case book of
    sherlock holmes');
    $attrYear = new DOMAttr("year", "1894");
    $bookName->appendChild($attrYear);

    $book->appendChild($bookName);

    $story = $objXML->createElement('story');
    $title = $objXML->createElement('title', 'Tha case of ....');
    $quote = $objXML->createElement('quote', 'Yet another quote');

    $story->appendChild($title);
    $story->appendChild($quote);

    $book->appendChild($story);
    $books->appendChild($book);

    $objXML->appendChild($books);

    if($objXML->save('new.xml') != FALSE)
    {
    echo 'XML file generated successfully.';
    }
    else
    {
    echo 'An error occured.';
    }
    ?>

  3. Now run the file in your browser. If the code executed successfully, you will see some text telling you that the XML file has been generated. Look up in the Recipe5 folder and you will find the newly generated XML file. This file will have the same structure as the common.xml file.

    <?xml version="1.0" encoding="utf-8"?>
    <books>
    <book index="4">
    <name year="1894">The case book of sherlock holmes</name>
    <story>
    <title>Tha case of ....</title>
    <quote>Yet another quote</quote>
    </story>
    </book>
    </books>

How it works...

The constructor of DOMDocument class creates a new DOMDocument object. There are two optional parameters that can be passed to it. The first parameter indicates the version of XML specification and its value is 1.0 by default and the second parameter denotes the encoding of the document.

To create a new node, createElement() method is used. It creates a new object of DOMElement class. createElement() accepts two parameters out of which the second is optional. The first parameter is the name of node and the second is the text value inside a node.

To create an attribute, we can create an object of DOMAttr class. Similar to createElement, it also has two parameters: attribute name and its value.

Elements and attributes thus created are standalone at this moment and are not a part of the document. To insert them into the document, we can call the appendChild method. This method takes an element as a parameter and appends it to the calling object.

In the previous example, we created new elements with createElement and appended them to the document according to the required format.

When we are done with creating elements, we saved the resulting XML to a file using the save() method.

Modifying an XML using DOM extension

Apart from creating a new XML from scratch as in the previous recipe, we can modify existing XML files too. We can add and remove elements from them.

In this recipe, we will create an example that will allow you to add new stories for a particular book. You will be able to add a title and quote for the selected book.

Getting ready

Create a new folder Recipe6 in the Article3 directory.

How to do it...

  1. Create a new file named index.php. Next, create a form that has a list of books and two input fields for entering story name and a quote. Also, create a button that will be used to add the new story and the quote to the XML file.

     

    <html>
    <head>
    <title>Modifying xml with</title>
    <style type="text/css">
    ul{border:1px solid black;padding:5px;
    list-style:none;width:350px;}
    label{float:left;width:100px;}
    </style>
    </head>
    <body>
    <ul>
    <li>
    <label for="bookList">Book:</label>
    <select id="bookList">
    <option value="">select a book</option>
    <?php
    $objXML = new DOMDocument();
    $objXML->load('../common.xml', LIBXML_NOBLANKS);
    $books = $objXML->getElementsByTagName('book');
    foreach($books as $book)
    {
    echo '<option value="'.$book->attributes->
    item(0)->value.'">'.$book->firstChild->nodeValue.'</option>';
    }
    ?>
    </select>
    </li>
    <li>
    <label for="storyName">Story Name</label>
    <input type="text" id="storyName" value=""/>
    </li>
    <li>
    <label for="quote">Quote</label>
    <textarea id="quote"></textarea>
    </li>
    <li>
    <input type="button" id="add" value="Add new story"/>
    </li>
    </ul>
    </body>
    </html>

  2. Now write the jQuery code that will invoke on the click of the button. jQuery will collect the values filled in the form and will send them to a PHP file, process.php, through an AJAX post request for further processing. The response received from PHP file will be displayed next to the button.

    <script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../jquery.js"></script>
    <script type="text/javascript">
    $(document).ready(function ()
    {
    $('#add').click(function()
    {
    $.post(
    'process.php',
    { bookId: $('#bookList').val() , storyTitle:
    $('#storyName').val(), quote: $('#quote').val() },
    function(data)
    {
    $('#add').after(data);
    });
    });
    });
    </script>

  3. We turn to the PHP script now where the actual magic will take place. Create a file in the same folder and name it process.php. This file will take the values out from $_POST. After that, it will load the common.xml file. The script will find the selected book. When the selected book has been found, it will create new elements, fill them with respective values, and then save them back to the XML.

    <?php
    $bookId = $_POST['bookId'];
    $title = $_POST['storyTitle'];
    $quote = $_POST['quote'];
    $objXML = new DOMDocument();
    $objXML->load('../common.xml', LIBXML_NOBLANKS);
    $books = $objXML->getElementsByTagName('book');
    foreach($books as $book)
    {
    if($book->attributes->item(0)->value == $bookId)
    {
    $story = $objXML->createElement('story');
    $title = $objXML->createElement('title', $title);
    $quote = $objXML->createElement('quote', $quote);
    $story->appendChild($title);
    $story->appendChild($quote);
    $book->appendChild($story);
    break;
    }
    }
    if($objXML->save('../common.xml') != FALSE)
    {
    echo 'New story added successfully.';
    }
    else
    {
    echo 'An error occured.';
    }
    ?>

  4. Run the index.php file and you will be presented with a form. Select a book from the select box, fill in the values for story name, and quote in the textboxes and click on Add new story. On successful submission, you will see a message next to the button. Open the XML file with an editor and you will see that a new story has been inserted into the appropriate book.

How it works...

When the values are filled in the form and the button is clicked, jQuery sends the filled values to the process.php file. First, we get the values from $_POST array. Now DOMDocument class is used to load the XML file. We then use function getElementsByTagName to get all the book elements and then loop through them using foreach loop. Our main task here is to identify which book has been selected and also to modify that book node. Using the attributes property, we can compare the index attribute of a book with variable $bookId to find out the selected book. Once the book is found, we can break out of the loop.

Now that we have found the selected book, we can use DOM functions to add new elements. In the previous example we created three elements: story, title, and quote, and assigned the received values to title and quote.

To add these newly-created elements to the document tree, we use the appendChild method that we have used in the previous recipe. We appended the $title and $quote objects to $story objects and finally appended the $story object to $book object.

To change the modified object to a real XML string, we can use either of two methods: save and saveXML. save() method saves to a file whereas saveXML() returns XML as a string.

We can then echo the appropriate message that is displayed in the browser. Now, you can also check the value by opening the XML file that you have written.

There's more...

Deleting nodes

Opposite to createElement() method is the removeChild() method, which is used to remove elements from a document.

$objXML = new DOMDocument();
$objXML->load('new.xml');
$book = $objXML->getElementsByTagName('book')->item(0);
$book->parentNode->removeChild($book);
$objXML->save('new.xml');

The above code will remove the first book element (and all its children) from the document. If you wish to call the removeChild method from the root node itself, you can do this quite easily. You just need to replace the line:

$book->parentNode->removeChild($book);

with the following line:

$objXML->documentElement->removeChild($book);

Parsing XML with jQuery

jQuery itself can be used to parse an XML document on the client side. We can fetch an XML file using jQuery's AJAX methods and then process it on the browser itself and get data from it.

We will recreate the same example that we wrote in the recipe Reading an XML using DOM extension. Contrary to that recipe where we used DOM methods on the server side, we will use jQuery's selector functions to traverse through the XML.

Getting ready

Create a new folder under Article3 directory and name it Recipe7. Also copy the common.xml file to this folder.

How to do it...

  1. Create a file named index.html in the Recipe7 folder. In this file, simply declare some styles for h1 and ul elements that will be created later through jQuery. Create a DIV element in which we will insert the HTML.

    <html>
    <head>
    <title>Reading xml through jQuery</title></head>
    <style type="text/css">
    h1{ cursor:pointer;font-size:20px;}
    ul{ display:none; list-style:none;margin:0pt;padding:0pt;}
    </style>
    <body>
    <div id="result"></div>
    </body>
    </html>

  2. Include the jQuery file. Next bind click handler for h1 elements using live method. After that send an AJAX request to get the common.xml file. When the file is fetched, write success event handler to traverse through it and create HTML in the desired format. Finally, insert this HTML to the DIV element on the page.

    <script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../jquery.js"></script>
    <script type="text/javascript">
    $(document).ready(function ()
    {
    $('h1').live('click',function()
    {
    $(this).next('ul').toggle('fast');
    });

    $.ajax(
    {
    url: 'common.xml',
    type: 'GET',
    dataType: 'xml',
    success: function(xml)
    {
    var str = '';
    $(xml).find('book').each(function()
    {
    var book = $(this);
    str+= '<h1>' + book.find('name').text() + '</h1>';
    str+= '<ul>';
    book.find('story').each(function()
    {
    str+= '<li>';
    str+= $(this).find('title').text();
    str+= '</li>';
    });
    str+= '</ul>';
    });
    $('#result').html(str);
    }
    });
    });
    </script>

  3. Run the file in the browser and you will see names of all the books in the XML file. Click on any of the titles to show or hide the story list for that book.

How it works...

After the page has been loaded, the common.xml file is fetched through an AJAX GET request. Note the dataType property; we have set it to xml. Now jQuery knows that the response is going to be an XML file. So, when jQuery receives the XML string it converts it into a document object.

Now, we can apply all the jQuery's selector functions to it and extract the data. We used the find method to get all the book elements. Using each() we iterated in each book and again iterated for stories in each book. During this whole process, we also wrapped book names into h1 elements and story names into list items.

When we are done looping, we have an HTML string that we insert into the page. Since we had already used live method for h1 elements, clicking the book names will toggle the list of stories.

Remember that the live method is used to attach event handlers to elements that will be created in future.

There's more...

The delegate() method

delegate() is another method similar to live—the difference being that it also takes selector elements as parameters and filters them against a set of elements that trigger the event.

$('div').delegate("span", "click", function(){
$(this).toggleClass("hover");
});

If a DIV is clicked then the code will check whether this event has been fired by clicking on a span element inside the DIV. toggleClass will execute only when a span inside a DIV is clicked. delegate() has done the filtering in this case.

Summary

In the above article we have covered:

  • Loading XML from files and strings using SimpleXML
  • Accessing elements and attributes using SimpleXML
  • Searching elements using XPath
  • Reading an XML using DOM extension
  • Creating an XML using DOM extension
  • Modifying an XML using DOM extension
  • Parsing XML with jQuery

Further resources on this subject:


About the Author :


Vijay Joshi

Vijay Joshi is a web developer who lives in New Delhi, India, with his wife and daughter. Coming from a small town named Pithoragarh, Uttarakhand in the Himalayas, he fell in love with coding while in college and then again with PHP and JavaScript/jQuery since his early coding days. He believes that if you are passionate and enjoy your work, it becomes more of a hobby thatis not boring and never feels like a job.

After freelancing for a few years, he co-founded a web development firm called Developers Lab along with two of his friends in New Delhi where they build products for the travel industry and create custom web applications.

Vijay is also author of PHP jQuery Cookbook, published by Packt, and technical reviewer of PHP AJAX Cookbook and jQuery UI 1.8: The User Interface Library for jQuery.

When not coding, he likes to read, spend time with his family, blog occasionally at http://www.vijayjoshi.org, and dreams about getting back in shape.

Books From Packt


Drupal 7
Drupal 7

PHP 5 E-commerce Development
PHP 5 E-commerce Development

Expert PHP 5 Tools
Expert PHP 5 Tools

PHP 5 CMS Framework Development - 2nd Edition
PHP 5 CMS Framework Development - 2nd Edition

jQuery 1.4 Animation Techniques: Beginners Guide
jQuery 1.4 Animation Techniques: Beginners Guide

CMS Design Using PHP and jQuery
CMS Design Using PHP and jQuery

jQuery Plugin Development Beginner's Guide
jQuery Plugin Development Beginner's Guide

jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software