As is the case with other matters, you will need to check with your server administration to find out the ways in which the PHP installation accesses XML, because there is more than one way. The approach shown here requires you to define functions for handling different categories of tags. The categories are starting tags, ending tags, and character data tags. The action of the functions is to output to the browser fragments of HTML. This is not unlike what you did with PHP and ASP in previous chapters. However, the requirements of handling XML mean the tasks are divided differently. You need to think about what action is to be triggered by the start of an element, the contents of an element, and then close of an element.
The assumption is that the XML documents contain tags of the following structure:
<contact> <name>John Doe </name> <email>john.doe@xxx.yyy</email> </contact>
The XML file could contain other tags, but these are the only ones recognized by this PHP script. The PHP script, shown in Table 17.1, will produce an HTML table, with a new row for each contact.
<html><head><title>PHP xml SAX test </title> | HTML starting tags |
<style type="text/css"> | Style section |
td {font-family: Arial; font-size: smaller} | Style for table elements |
h2 {font-family: Comic Sans MS} | Style for type h2 heading |
</style> | End of style section |
</head> | End of head section |
<body> | Start of body |
<h2>Address book </h2><p> | Heading |
<table border="1"><tr><td>Name</td><td>E-mail</td></tr> | Start of table |
<? | Start of PHP |
$file="D:\inetpub\wwwroot\jeanine\ xmlstuff\contactsnoref.xml"; | Address for xml file |
$currenttag=""; | Variable holding current tag |
function startElement($parser,$name, $attrs) { | Function definition. This function will be cited later |
global $currenttag; | Will use the global variable |
$currenttag=$name; | Sets $currenttag to be the $name passed as argument for call of function |
switch($name) { | Switch statement |
case "CONTACT": | For the contact case… |
print("<tr>"); | Start a new row |
break; | Break out of the switch statement |
case "NAME": | For the name case… |
print("<td>"); | Start a new table datum (new column) |
break; | Break out of the switch statement |
case "EMAIL": | For the e-mail case |
print("<td>"); | Start a new table datum |
break; | Break out of the switch statement |
default: | All other cases… (this line and the next could be omitted, but is a placeholder in case you need to add something later) |
break; | Break out of switch |
} | End of switch |
} | End of function |
function endElement($parser,$name) { | Start of function. This function will be cited later |
global $currenttag; | Will use global variable |
switch ($name) { | Switch statement |
case "CONTACT": | For contact case |
print("</tr>"); | End row of table |
break; | Break out of switch |
case "NAME": | For name case |
print ("</td>"); | End table datum |
break; | Break out of switch |
case "EMAIL": | For e-mail case |
print("</td>"); | End table datum |
break; | Break out of switch |
default: | Default case |
break; | Break out of switch |
} | End of switch |
$currenttag=""; | Reset variable to empty |
} | End of function definition |
function characterData($parser,$data){ | Definition of function. This function is cited later |
global $currenttag; | Will use global variable |
switch($currenttag){ | The global variable $currenttag is what guides the cases |
case "NAME": | For name case |
print("<b>" . $data . "</b>"); | Output character data; namely, the contents of the tag in bold |
break; | Break out of switch |
case "EMAIL": | For the e-mail case |
print($data); | Output the contents of the tag |
break; | Break out of switch |
default: | Default case |
break; | Break out of switch |
} | End of switch |
} | End of function |
$xml_parser=xml_parser_create(); | Calls one of the built-in PHP functions for handling XML to define a parser object |
xml_set_element_handler($xml_parser, "startElement","endElement"); | Calls another of the built-in PHP functions to specify how starting and ending elements are to be handling by citing the functions just defined |
xml_set_character_data_handler($xml_parser,"characterData"); | Calls yet another of the built-in PHP functions to specify how character data is to be handled |
if (!($fp=fopen($file,"r"))) { | Error handling: if the XML file cannot be located |
die("Cannot locate XML data file: $file"); | The die command ends the PHP script |
} | Ends if clause |
while ($data=fread($fp,4096)) | Starts a while statement that reads the file. The parameter specifies a maximum number of characters |
{ if (!xml_parse($xml_parser,$data, feof($fp))) { | If the XML contents end prematurely |
die(sprintf("XML error: %s at %d", ($xml_parser)), | Signal error and close PHP scriptxml_error_string(xml_get_error_code |
xml_get_current_line_number($xml_parser))); } | Continuation with output of line with error |
} | |
xml_parser_free($xml_parser); | Release the object created for doing the parsing |
?> | End PHP |
</table></body></html> | Closing HTML tags |
The code contains switch statements. These are the PHP versions of case conditional statements. In the PHP version, it is necessary to use a break command to exit the switch statement at the end of the particular case when you do not want to drop in to the following case. Notice that the $currenttag variable is set in one function and used in another.