Parsing XML

In this section, you'll see a few examples of how PHP can parse a valid XML document using the messages.xml file created earlier in this chapter. These examples do not provide earth-shattering functionality, and in fact are simply annotated versions of code found in the PHP Manual. However, these very basic scripts exemplify the stepwise methods used to parse XML files with PHP; for anything beyond this, please investigate on your own. As with everything in this book, it's all about gaining a foundation!

The first example script, called parse.php, will simply open an XML document, parse it, and display back the names of the entities. If your file is not a valid XML document, this script will throw an error, indicating the line number and reason.

First, assign the name of the file to a variable called $filename, because you'll use it more than once. Then, create an array called $depth. The $depth array is used to hold the parser's place as it goes through your XML file in a linear fashion.

 $filename = "messages.xml"; $depth = array(); 

Next, create two functions called startElement() and endElement(). These functions can really be called anything you want, but they are used to find and display the beginning and end of the current element as the parser goes though the XML file, hence the suggested names.

 function startElement($parser, $name, $attributes) {     global $depth;     for ($i = 0; $i < $depth[$parser]; $i++) {         echo " ";     }     echo "$name<br>\n";     $depth[$parser]++; } 

In the startElement() function above, the $depth array is listed as a global variable because its value is used in various places in the script, not just in that particular function. Next, a for loop goes through and, for each element start tag, echoes a bit of white space to the screen, followed by the name of the element. The index value of the $depth array is incremented as it moves on.

Next, the endElement() function simply decrements the index value of the $depth array, as the parser moves through the file:

 function endElement($parser, $name) (     global $depth;     $depth[$parser]--; } 

Neither of these functions do anything on their own; they are set up at the beginning of the PHP script and used during the actual XML parsing process, which you will now write. First, call the xml_parser_create() function to create a new parser. In this case the reference is stored in a variable called $xml_parser.

 $xml_parser = xml_parser_create(); 

Next, use the xml_set_element_handler() function to define the functions that will handle opening and closing tags in the XML document—not surprisingly, these are the startElement() and endElement() functions you just created:

 xml_set_element_handler($xml_parser, "startElement", "endElement"); 

The next step is to open the XML file and start a while loop that reads the data from the XML file you just opened:

 $fp = fopen("$filename", "r") or die("Couldn't open XML file."); while ($data = fread($fp, filesize ($filename))) { 

Inside the while loop, use the xml_parse() function to do the actual parsing of the data stream for the entire length of the file. The die() function uses a couple of XML-related functions to get useful information (the error and the line number) and display it back to you should an error occur.

   //parse the data using the parser we opened above xml_parse($xml_parser, $data, feof($fp)) or die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); 

After closing the while loop, close the file that you opened for reading and free the memory used by the XML parser:

 fclose($fp); xml_parser_free($xml_parser); 

The complete parse.php script looks something like this:

 <? $filename = "messages.xml"; $depth = array(); function startElement($parser, $name, $attributes) {     global $depth;     for ($i = 0; $i < $depth[$parser]; $i++) {         echo " ";     }     echo "$name<br>\n";     $depth[$parser]++; } function endElement($parser, $name) {     global $depth;     $depth[$parser]--; } //create a new parser $xml_parser = xml_parser_create(); //tell php which functions handle opening and closing tags xml_set_element_handler($xml_parser, "startElement", "endElement"); //open the XML file for reading $fp = fopen("$filename", "r") or die("Couldn't open XML file."); //read the XML file while ($data = fread($fp, filesize ($filename))) {     //parse the data using the parser we opened above     xml_parse($xml_parser, $data, feof($fp)) or die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } //close the XML file fclose($fp); //free up memory xml_parser_free($xml_parser); ?> 

If you place this file and the messages.xml document on your Web server and access it with your Web browser, you'll see something like Figure 9.3—all of your XML elements are displayed.

click to expand
Figure 9.3: All of the XML elements in messages.xml

If you change something in messages.xml and break a rule for XML validity, you can invoke the error message in your script. If you do something like delete the ending tag for the MessageAuthor element, you will get a "mismatched tag" error, as shown in Figure 9.4.

click to expand
Figure 9.4: Missing end tag error

The parse.php script shows the absolute basics of reading an XML document and determining the start and end tags for each element. To take this concept further, the next section shows you how to map XML elements to specific HTML markup, eventually displaying the information in presentation formation.

Parse and Display Content from XML Files

You've already seen much of the code for this section in the parse.php file. In this section, the markup.php script will read the messages.xml file and map HTML markup to XML elements, eventually displaying what you'd normally see in a Web browser. As such, we'll go through the new elements step by step, and assume you have a handle on the similar features.

After defining $filename as "messages.xml", set up two arrays which map specific XML elements to both opening and closing HTML markup tags.

 $filename = "messages.xml"; $startTags = array( "MESSAGETITLE" => "<P><strong>", "MESSAGEBODY" => "<p>", "MESSAGEAUTHOR" => "<p>Added by: ", "MESSAGEAUTHORNAME" => "<em>", "MESSAGEAUTHOREMAIL" => "<em>(", "MESSAGEDATE" => "<font size=-1>on " ); $endTags = array( "MESSAGETITLE" => "</strong><br>", "MESSAGEBODY" => "</p>", "MESSAGEAUTHORNAME" => "</em>", "MESSAGEAUTHOREMAIL" => ")</em>", "MESSAGEDATE" => "</font>", }; 

These two arrays are pretty self-explanatory; the $startTags array includes the HTML markup, which will be printed when the XML parser comes across an element whose name matches a key in the array. Similarly, the $endTags array will be used to close up the HTML markup for each mapped XML element. You can see this functionality in the startElement() and endElement() functions:

 function startElement($parser, $name, $attrs) {           global $startTags;           // if XML element is a $startTags key, print its markup           if ($startTags[$name])  {                   echo $startTags[$name];           } } function endElement($parser, $name) {           global $endTags;           // if XML element is a $endTags key, print its markup           if ($endTags[$name])    {                   echo $endTags[$name];           } } 

For example, when the parser comes across the opening MESSAGETITLE XML element, it will print <P><strong>, and when it comes across the ending MESSAGETITLE XML element, it will print </strong><br>. But this leaves the important part—the MESSAGETITTLE content itself—out of the equation! So, create a function called characterData(), which will print the XML content for that element:

 function characterData($parser, $data) {              echo $data; } 

Now comes the series of xml_* PHP functions that make this script work. You've seen these before:

 $xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, "startElement", "endElement"); 

The next function is a new one, and it's used to interpret the content of the XML element, using the characterData() function you defined above:

 xml_set_character_data_handler($xml_parser, "characterData"); 

The script wraps up with the reading/parsing code you've seen before, so that the entire markup.php script looks something like this:

 <? $filename = "messages.xml"; $startTags = array( "MESSAGETITLE" => "<P><strong>", "MESSAGEBODY" => "<p>", "MESSAGEAUTHOR" => "<p>Added by: ", "MESSAGEAUTHORNAME" => "<em>", "MESSAGEAUTHOREMAIL" => "<em>(", "MESSAGEDATE" => "<font size=-1>on " ); $endTags = array( "MESSAGETITLE" => "</strong><br>", "MESSAGEBODY" => "</p>", "MESSAGEAUTHORNAME" => "</em>", "MESSAGEAUTHOREMAIL" => ")</em>", "MESSAGEDATE" => "</font>", ); function startElement($parser, $name, $attrs) {           global $startTags;           // if XML element is a $startTags key, print its markup           if ($startTags[$name])  {                   echo $startTags[$name];           } } function endElement($parser, $name) {           global $endTags;           // if XML element is a $endTags key, print its markup           if ($endTags[$name])    {                   echo $endTags[$name];           } } function characterData($parser, $data) {           echo $data; } //create a new parser $xml_parser = xml_parser_create(); //tell php which functions handle opening and closing tags xml_set_element_handler($xml_parser, "startElement", "endElement"); //tell php which function handles the data inside the tags xml_set_character_data_handler($xml_parser, "characterData"); //open the XML file for reading $fp = fopen("$filename", "r") or die("Couldn't open XML file."); //read the XML file while ($data = fread($fp, filesize ($filename))) {     //parse the data using the parser we opened above     xml_parse($xml_parser, $data, feof($fp)) or die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } //close the XML file fclose($fp); //free up memory xml_parser_free($xml_parser); ?> 

If you place this file and the messages.xml document on your Web server and access it with your Web browser, you'll see something like Figure 9.5, with each element marked up as mapped!

click to expand
Figure 9.5: Mapped XML content

Both the parse.php and markup.php scripts show the absolute basics of reading an XML document and working with its content. To take this concept further, have a look at the examples in the PHP Manual, or at the numerous tutorials available at PHP-related developer Web sites.



PHP Essentials
PHP Essentials, 2nd Edition
ISBN: 1931841349
EAN: 2147483647
Year: 2002
Pages: 74

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net