<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://commons.oreilly.com/wiki/skins/common/feed.css?97"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/XML&amp;action=history&amp;feed=atom</id>
		<title>PHP Cookbook/XML - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/XML&amp;action=history&amp;feed=atom"/>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/XML&amp;action=history"/>
		<updated>2013-05-21T19:01:27Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.11.0</generator>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/XML&amp;diff=7324&amp;oldid=prev</id>
		<title>Docbook2Wiki: Initial conversion from Docbook</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/XML&amp;diff=7324&amp;oldid=prev"/>
				<updated>2008-03-07T13:36:04Z</updated>
		
		<summary type="html">&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 13:36, 7 March 2008&lt;/td&gt;
			&lt;/tr&gt;
		&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 4:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 4:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;== Introduction ==&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;== Introduction ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;nowiki&amp;gt;&lt;/del&gt;Recently, XML has gained &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;''&lt;/del&gt;popularity&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;'' &lt;/del&gt;as a data-exchange and message-passing format. As web services become more widespread, XML plays an even more important role in a developer's life. With the help of a few extensions, PHP lets you read and write XML for every occasion. &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;An italicized apostrophe:&amp;lt;/nowiki&amp;gt;''&amp;lt;nowiki&amp;gt;foo'&amp;lt;/nowiki&amp;gt;'' A reserved tag name: &amp;amp;lt;references&amp;gt; Not reserved: &amp;lt;reference&amp;gt; Reserved: &amp;amp;lt;ref&amp;gt; Not reserved: &amp;lt;refs&amp;gt; Tag names starting with &amp;quot;B&amp;quot;: &amp;lt;Boo&amp;gt; and &amp;amp;lt;B&amp;gt;. A comment: &amp;amp;lt;!-- yep --&amp;gt; Inadvertant Wiki character reference: &amp;amp;#149;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Recently, XML has gained popularity as a data-exchange and message-passing format. As web services become more widespread, XML plays an even more important role in a developer's life. With the help of a few extensions, PHP lets you read and write XML for every occasion.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;XML provides developers with a structured way to mark up data with tags arranged in a tree-like hierarchy. One perspective on XML is to treat it as CSV on steroids. You can use XML to store records broken into a series of fields. But, instead of merely separating each field with a comma, you can include a field name, type, and attributes alongside the data.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;XML provides developers with a structured way to mark up data with tags arranged in a tree-like hierarchy. One perspective on XML is to treat it as CSV on steroids. You can use XML to store records broken into a series of fields. But, instead of merely separating each field with a comma, you can include a field name, type, and attributes alongside the data.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Docbook2Wiki</name></author>	</entry>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/XML&amp;diff=3127&amp;oldid=prev</id>
		<title>Evanlenz: 1 revision(s)</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/XML&amp;diff=3127&amp;oldid=prev"/>
				<updated>2008-03-06T22:30:09Z</updated>
		
		<summary type="html">&lt;p&gt;1 revision(s)&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 22:30, 6 March 2008&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/table&gt;</summary>
		<author><name>Evanlenz</name></author>	</entry>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/XML&amp;diff=3126&amp;oldid=prev</id>
		<title>Docbook2Wiki: Initial conversion from Docbook</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/XML&amp;diff=3126&amp;oldid=prev"/>
				<updated>2008-03-06T22:28:45Z</updated>
		
		<summary type="html">&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{PHP Cookbook/TOC}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;Recently, XML has gained ''popularity'' as a data-exchange and message-passing format. As web services become more widespread, XML plays an even more important role in a developer's life. With the help of a few extensions, PHP lets you read and write XML for every occasion. An italicized apostrophe:&amp;lt;/nowiki&amp;gt;''&amp;lt;nowiki&amp;gt;foo'&amp;lt;/nowiki&amp;gt;'' A reserved tag name: &amp;amp;lt;references&amp;gt; Not reserved: &amp;lt;reference&amp;gt; Reserved: &amp;amp;lt;ref&amp;gt; Not reserved: &amp;lt;refs&amp;gt; Tag names starting with &amp;quot;B&amp;quot;: &amp;lt;Boo&amp;gt; and &amp;amp;lt;B&amp;gt;. A comment: &amp;amp;lt;!-- yep --&amp;gt; Inadvertant Wiki character reference: &amp;amp;#149;&lt;br /&gt;
&lt;br /&gt;
XML provides developers with a structured way to mark up data with tags arranged in a tree-like hierarchy. One perspective on XML is to treat it as CSV on steroids. You can use XML to store records broken into a series of fields. But, instead of merely separating each field with a comma, you can include a field name, type, and attributes alongside the data.&lt;br /&gt;
&lt;br /&gt;
Another view of XML is as a document representation language. For instance, the ''PHP Cookbook'' was written using XML. The book is divided into chapters; each chapter into recipes; and each recipe into Problem, Solution, and Discussion sections. Within any individual section, we further subdivide the text into paragraphs, tables, figures, and examples. An article on a web page can similarly be divided into the page title and headline, the authors of the piece, the story itself, and any sidebars, related links, and additional content.&lt;br /&gt;
&lt;br /&gt;
XML text looks similar to HTML. Both use tags bracketed by &amp;lt;tt&amp;gt;&amp;lt;&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;&amp;gt;&amp;lt;/tt&amp;gt; for marking up text. But XML is both stricter and looser than HTML. It's stricter because all container tags must be properly closed. No opening elements are allowed without a corresponding closing tag. It's looser because you're not forced to use a set list of tags, such as &amp;lt;tt&amp;gt;&amp;lt;a&amp;gt;&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;lt;img&amp;gt;&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;&amp;amp;lt;h1&amp;gt;&amp;lt;/tt&amp;gt;. Instead, you have the freedom to choose a series of tag names that best describe your data.&lt;br /&gt;
&lt;br /&gt;
Other key differences between XML and HTML are case-sensitivity, attribute quoting, and whitespace. In HTML, &amp;lt;tt&amp;gt;&amp;amp;lt;B&amp;gt;&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;&amp;amp;lt;b&amp;gt;&amp;lt;/tt&amp;gt; are the same bold tag; in XML, they're two different tags. In HTML, you can often omit quotation marks around attributes; XML, however, requires them. So, you must always write:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;element attribute=&amp;quot;value&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, HTML parsers generally ignore whitespace, so a run of 20 consecutive spaces is treated the same as one space. XML parsers preserve whitespace, unless explicitly instructed otherwise. Because all elements must be closed, empty elements must end with &amp;lt;tt&amp;gt;/&amp;gt;&amp;lt;/tt&amp;gt;. For instance in HTML, the line break is &amp;lt;tt&amp;gt;&amp;amp;lt;br&amp;gt;&amp;lt;/tt&amp;gt;, while in XML, it's written as &amp;lt;tt&amp;gt;&amp;amp;lt;br /&amp;gt;&amp;lt;/tt&amp;gt;.&amp;lt;ref&amp;gt;This is why &amp;lt;tt&amp;gt;nl2br( )&amp;lt;/tt&amp;gt; outputs &amp;lt;tt&amp;gt;&amp;amp;lt;br /&amp;gt;&amp;lt;/tt&amp;gt;; its output is XML-compatible.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is another restriction on XML documents. Since XML documents can be parsed into a tree of elements, the outermost element is known as the ''root element'' . Just as a tree has only one trunk, an XML document must have exactly one root element. In the previous book example, this means chapters must be bundled inside a book tag. If you want to place multiple books inside a document, you need to package them inside a bookcase or another container. This limitation applies only to the document root. Again, just like trees can have multiple branches off of the trunk, it's legal to store multiple books inside a bookcase.&lt;br /&gt;
&lt;br /&gt;
This chapter doesn't aim to teach you XML; for an introduction to XML, see ''Learning XML'', by Erik T. Ray. A solid nuts-and-bolts guide to all aspects of XML is ''XML in a Nutshell'', by Elliotte Rusty Harold and W. Scott Means. Both books are published by O'Reilly &amp;amp; Associates.&lt;br /&gt;
&lt;br /&gt;
Now that we've covered the rules, here's an example: if you are a librarian and want to convert your card catalog to XML, start with this basic set of XML tags:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;book&amp;gt;&lt;br /&gt;
     &amp;lt;title&amp;gt;PHP Cookbook&amp;lt;/title&amp;gt;&lt;br /&gt;
     &amp;lt;author&amp;gt;Sklar, David and Trachtenberg, Adam&amp;lt;/author&amp;gt;&lt;br /&gt;
     &amp;lt;subject&amp;gt;PHP&amp;lt;/subject&amp;gt;&lt;br /&gt;
 &amp;lt;/book&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From there, you can add new elements or modify existing ones. For example, &amp;lt;tt&amp;gt;&amp;lt;author&amp;gt;&amp;lt;/tt&amp;gt; can be divided into first and last name, or you can allow for multiple records so two authors aren't placed in one field.&lt;br /&gt;
&lt;br /&gt;
The first three recipes in this chapter cover writing and reading XML. [[PHP Cookbook/XML#Generating XML Manually|Recipe 12.2]] shows how to write XML without additional tools. To use the DOM XML extension to write XML in a standardized fashion, see [[PHP Cookbook/XML#Generating XML with the DOM|Recipe 12.3]]. Reading XML using DOM is the topic of [[PHP Cookbook/XML#Parsing XML with the DOM|Recipe 12.4]].&lt;br /&gt;
&lt;br /&gt;
But XML isn't an end by itself. Once you've gathered all your XML, the real question is &amp;quot;What do you do with it?&amp;quot; With an event-based parser, as described in [[PHP Cookbook/XML#Parsing XML with SAX|Recipe 12.5]], you can make element tags trigger actions, such as storing data into easily manipulated structures or reformatting the text.&lt;br /&gt;
&lt;br /&gt;
With XSLT, you can take a XSL stylesheet and turn XML into viewable output. By separating content from presentation, you can make one stylesheet for web browsers, another for PDAs, and a third for cell phones, all without changing the content itself. This is the subject of [[PHP Cookbook/XML#Transforming XML with XSLT|Recipe 12.6]].&lt;br /&gt;
&lt;br /&gt;
You can use a protocol such as XML-RPC or SOAP to exchange XML messages between yourself and a server, or to act as a server yourself. You can thus put your card catalog on the Internet and allow other programmers to query the catalog and retrieve book records in a format that's easy for them to parse and display in their applications. Another use would be to set up an RSS feed that gets updated whenever the library gets a new book in stock. XML-RPC clients and servers are the subjects of [[PHP Cookbook/XML#Sending XML-RPC Requests|Recipe 12.7]] and [[PHP Cookbook/XML#Receiving XML-RPC Requests|Recipe 12.8]], respectively. [[PHP Cookbook/XML#Sending SOAP Requests|Recipe 12.9]] and [[PHP Cookbook/XML#Receiving SOAP Requests|Recipe 12.10]] cover SOAP clients and servers. WDDX, a data exchange format that originated with the ColdFusion language, is the topic of [[PHP Cookbook/XML#Exchanging Data with WDDX|Recipe 12.11]]. Reading RSS feeds, a popular XML-based headline syndication format, is covered in [[PHP Cookbook/XML#Reading RSS Feeds|Recipe 12.12]].&lt;br /&gt;
&lt;br /&gt;
As with many bleeding-edge technologies, some of PHP's XML tools are not feature-complete and bug-free. However, XML is an area of active development in the PHP community; new features are added and bugs are fixed on a regular basis. As a result, many XML functions documented here are still experimental. Sometimes, all that means is that the function is 99% complete, but there may be a few small bugs lying around. Other times, it means that the name or the behavior of the function could be completely changed. If a function is in a highly unstable state, we mention it in the recipe.&lt;br /&gt;
&lt;br /&gt;
We've documented the functions as they're currently planned to work in PHP 4.3. Because XML is such an important area, it made no sense to omit these recipes from the book. Also, we wanted to make sure that the latest functions are used in our examples. This can, however, lead to small problems if the function names and prototypes change. If you find that a recipe isn't working as you'd expect it to, please check the online PHP manual or the errata section of the catalog page for the ''PHP Cookbook'', ''http://www.oreilly.com/catalog/phpckbk''.&lt;br /&gt;
&lt;br /&gt;
== Generating XML Manually ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to generate XML. For instance, you want to provide an XML version of your data for another program to parse.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Loop through your data and print it out surrounded by the correct XML tags:&lt;br /&gt;
&lt;br /&gt;
 header('Content-Type: text/xml');&lt;br /&gt;
 print '&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;' . &amp;quot;\n&amp;quot;;&lt;br /&gt;
 print &amp;quot;&amp;lt;shows&amp;gt;\n&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 $shows = array(array('name'     =&amp;gt; 'Simpsons',&lt;br /&gt;
                      'channel'  =&amp;gt; 'FOX', &lt;br /&gt;
                      'start'    =&amp;gt; '8:00 PM',&lt;br /&gt;
                      'duration' =&amp;gt; '30'),&lt;br /&gt;
 &lt;br /&gt;
                array('name'     =&amp;gt; 'Law &amp;amp; Order', &lt;br /&gt;
                      'channel'  =&amp;gt; 'NBC',&lt;br /&gt;
                      'start'    =&amp;gt; '8:00 PM',&lt;br /&gt;
                      'duration' =&amp;gt; '60'));&lt;br /&gt;
 &lt;br /&gt;
 foreach ($shows as $show) {&lt;br /&gt;
     print &amp;quot;    &amp;lt;show&amp;gt;\n&amp;quot;;&lt;br /&gt;
     foreach($show as $tag =&amp;gt; $data) {&lt;br /&gt;
         print &amp;quot;        &amp;lt;$tag&amp;gt;&amp;quot; . htmlspecialchars($data) . &amp;quot;&amp;lt;/$tag&amp;gt;\n&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
     print &amp;quot;    &amp;lt;/show&amp;gt;\n&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 print &amp;quot;&amp;lt;/shows&amp;gt;\n&amp;quot;;  &lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
Printing out XML manually mostly involves lots of &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt; loops as you iterate through arrays. However, there are a few tricky details. First, you need to call &amp;lt;tt&amp;gt;header( )&amp;lt;/tt&amp;gt; to set the correct &amp;lt;tt&amp;gt;Content-Type&amp;lt;/tt&amp;gt; header for the document. Since you're sending XML instead of HTML, it should be &amp;lt;tt&amp;gt;text/xml&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Next, depending on your settings for the &amp;lt;tt&amp;gt;short_open_tag&amp;lt;/tt&amp;gt; configuration directive, trying to print the XML declaration may accidentally turn on PHP processing. Since the &amp;lt;tt&amp;gt;&amp;lt;?&amp;lt;/tt&amp;gt; of &amp;lt;tt&amp;gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;/tt&amp;gt; is the short PHP open tag, to print the declaration to the browser you need to either disable the directive or print the line from within PHP. We do the latter in the Solution.&lt;br /&gt;
&lt;br /&gt;
Last, entities must be escaped. For example, the &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt; in the show &amp;lt;tt&amp;gt;Law &amp;amp; Order&amp;lt;/tt&amp;gt; needs to be &amp;lt;tt&amp;gt;&amp;amp;amp;amp;&amp;lt;/tt&amp;gt;. Call &amp;lt;tt&amp;gt;htmlspecialchars( )&amp;lt;/tt&amp;gt; to escape your data.&lt;br /&gt;
&lt;br /&gt;
The output from the example in the Solution is:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;shows&amp;gt;&lt;br /&gt;
     &amp;lt;show&amp;gt;&lt;br /&gt;
         &amp;lt;name&amp;gt;Simpsons&amp;lt;/name&amp;gt;&lt;br /&gt;
         &amp;lt;channel&amp;gt;FOX&amp;lt;/channel&amp;gt;&lt;br /&gt;
         &amp;lt;start&amp;gt;8:00 PM&amp;lt;/start&amp;gt;&lt;br /&gt;
         &amp;lt;duration&amp;gt;30&amp;lt;/duration&amp;gt;&lt;br /&gt;
     &amp;lt;/show&amp;gt;&lt;br /&gt;
     &amp;lt;show&amp;gt;&lt;br /&gt;
         &amp;lt;name&amp;gt;Law &amp;amp;amp;amp; Order&amp;lt;/name&amp;gt;&lt;br /&gt;
         &amp;lt;channel&amp;gt;NBC&amp;lt;/channel&amp;gt;&lt;br /&gt;
         &amp;lt;start&amp;gt;8:00 PM&amp;lt;/start&amp;gt;&lt;br /&gt;
         &amp;lt;duration&amp;gt;60&amp;lt;/duration&amp;gt;&lt;br /&gt;
     &amp;lt;/show&amp;gt;&lt;br /&gt;
 &amp;lt;/shows&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/XML#Generating XML with the DOM|Recipe 12.3]] for generating XML using DOM; [[PHP Cookbook/XML#Parsing XML with the DOM|Recipe 12.4]] for reading XML with DOM; documentation on &amp;lt;tt&amp;gt;htmlspecialchars( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/htmlspecialchars''.&lt;br /&gt;
&lt;br /&gt;
== Generating XML with the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to generate XML but want to do it in an organized way instead of using &amp;lt;tt&amp;gt;print&amp;lt;/tt&amp;gt; and loops.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use PHP's DOM XML extension to create a DOM object; then, call &amp;lt;tt&amp;gt;dump_mem( )&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;dump_file( )&amp;lt;/tt&amp;gt; to generate a well-formed XML document:&lt;br /&gt;
&lt;br /&gt;
 // create a new document&lt;br /&gt;
 $dom = domxml_new_doc('1.0');&lt;br /&gt;
 &lt;br /&gt;
 // create the root element, &amp;lt;book&amp;gt;, and append it to the document&lt;br /&gt;
 $book = $dom-&amp;gt;append_child($dom-&amp;gt;create_element('book'));&lt;br /&gt;
 &lt;br /&gt;
 // create the title element and append it to $book&lt;br /&gt;
 $title = $book-&amp;gt;append_child($dom-&amp;gt;create_element('title'));&lt;br /&gt;
 &lt;br /&gt;
 // set the text and the cover attribute for $title&lt;br /&gt;
 $title-&amp;gt;append_child($dom-&amp;gt;create_text_node('PHP Cookbook'));&lt;br /&gt;
 $title-&amp;gt;set_attribute('cover', 'soft');&lt;br /&gt;
 &lt;br /&gt;
 // create and append author elements to $book&lt;br /&gt;
 $sklar = $book-&amp;gt;append_child($dom-&amp;gt;create_element('author'));&lt;br /&gt;
 // create and append the text for each element&lt;br /&gt;
 $sklar-&amp;gt;append_child($dom-&amp;gt;create_text_node('Sklar'));&lt;br /&gt;
 &lt;br /&gt;
 $trachtenberg = $book-&amp;gt;append_child($dom-&amp;gt;create_element('author'));&lt;br /&gt;
 $trachtenberg-&amp;gt;append_child($dom-&amp;gt;create_text_node('Trachtenberg'));&lt;br /&gt;
 &lt;br /&gt;
 // print a nicely formatted version of the DOM document as XML&lt;br /&gt;
 echo $dom-&amp;gt;dump_mem(true);&lt;br /&gt;
 '''&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;'''&lt;br /&gt;
                '''&amp;lt;book&amp;gt;'''&lt;br /&gt;
                '''  &amp;lt;title cover=&amp;quot;soft&amp;quot;&amp;gt;PHP Cookbook&amp;lt;/title&amp;gt;'''&lt;br /&gt;
                '''  &amp;lt;author&amp;gt;Sklar&amp;lt;/author&amp;gt;'''&lt;br /&gt;
                '''  &amp;lt;author&amp;gt;Trachtenberg&amp;lt;/author&amp;gt;'''&lt;br /&gt;
                '''&amp;lt;/book&amp;gt;'''&lt;br /&gt;
             &lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
A single element is known as a ''node'' . Nodes can be of a dozen different types, but the three most popular are elements, attributes, and text. Given this:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;book cover=&amp;quot;soft&amp;quot;&amp;gt;PHP Cookbook&amp;lt;/book&amp;gt;&lt;br /&gt;
&lt;br /&gt;
PHP's DOM XML functions refer to &amp;lt;tt&amp;gt;book&amp;lt;/tt&amp;gt; as type &amp;lt;tt&amp;gt;XML_ELEMENT_NODE&amp;lt;/tt&amp;gt; , &amp;lt;tt&amp;gt;cover=&amp;quot;soft&amp;quot;&amp;lt;/tt&amp;gt; maps to an &amp;lt;tt&amp;gt;XML_ATTRIBUTE_NODE&amp;lt;/tt&amp;gt; , and &amp;lt;tt&amp;gt;PHP Cookbook&amp;lt;/tt&amp;gt; is a &amp;lt;tt&amp;gt;XML_TEXT_NODE&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For DOM parsing, PHP uses libxml, developed for the Gnome project. You can download it from ''http://www.xmlsoft.org''. To activate it, configure PHP with &amp;lt;tt&amp;gt;--with-dom&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The revamped PHP 4.3 DOM XML functions follow a pattern. You create an object as either an element or a text node, add and set any attributes you want, and then append it to the tree in the spot it belongs.&lt;br /&gt;
&lt;br /&gt;
Before creating elements, create a new document, passing the XML version as the sole argument:&lt;br /&gt;
&lt;br /&gt;
 $dom = domxml_new_doc('1.0');&lt;br /&gt;
&lt;br /&gt;
Now create new elements belonging to the document. Despite being associated with a specific document, nodes don't join the document tree until appended:&lt;br /&gt;
&lt;br /&gt;
 $book_element = $dom-&amp;gt;create_element('book');&lt;br /&gt;
 $book = $dom-&amp;gt;append_child($book_element);&lt;br /&gt;
&lt;br /&gt;
Here a new &amp;lt;tt&amp;gt;book&amp;lt;/tt&amp;gt; element is created and assigned to the object &amp;lt;tt&amp;gt;$book_element&amp;lt;/tt&amp;gt;. To create the document root, append &amp;lt;tt&amp;gt;$book_element&amp;lt;/tt&amp;gt; as a child of the &amp;lt;tt&amp;gt;$dom&amp;lt;/tt&amp;gt; document. The result, &amp;lt;tt&amp;gt;$book&amp;lt;/tt&amp;gt;, refers to the specific element and its location within the DOM object.&lt;br /&gt;
&lt;br /&gt;
All nodes are created by calling a method on &amp;lt;tt&amp;gt;$dom&amp;lt;/tt&amp;gt;. Once a node is created, it can be appended to any element in the tree. The element from which we call the &amp;lt;tt&amp;gt;append_child( )&amp;lt;/tt&amp;gt; method determines the location in the tree where the node is placed. In the previous case, &amp;lt;tt&amp;gt;$book_element&amp;lt;/tt&amp;gt; is appended to &amp;lt;tt&amp;gt;$dom&amp;lt;/tt&amp;gt;. The element appended to &amp;lt;tt&amp;gt;$dom&amp;lt;/tt&amp;gt; is the top-level node, or the ''root node''.&lt;br /&gt;
&lt;br /&gt;
You can also append a new child element to &amp;lt;tt&amp;gt;$book&amp;lt;/tt&amp;gt;. Since &amp;lt;tt&amp;gt;$book&amp;lt;/tt&amp;gt; is a child of &amp;lt;tt&amp;gt;$dom&amp;lt;/tt&amp;gt;, the new element is, by extension, a grandchild of &amp;lt;tt&amp;gt;$dom&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 $title_element = $dom-&amp;gt;create_element('title');&lt;br /&gt;
 $title = $book-&amp;gt;append_child($title_element);&lt;br /&gt;
&lt;br /&gt;
By calling &amp;lt;tt&amp;gt;$book-&amp;gt;append_child( )&amp;lt;/tt&amp;gt;, this code places the &amp;lt;tt&amp;gt;$title_element&amp;lt;/tt&amp;gt; element under the &amp;lt;tt&amp;gt;$book&amp;lt;/tt&amp;gt; element.&lt;br /&gt;
&lt;br /&gt;
To add the text inside the &amp;lt;tt&amp;gt;&amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/tt&amp;gt; tags, create a text node using &amp;lt;tt&amp;gt;create_text_node( )&amp;lt;/tt&amp;gt; and append it to &amp;lt;tt&amp;gt;$title&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 $text_node = $dom-&amp;gt;create_text_node('PHP Cookbook');&lt;br /&gt;
 $title-&amp;gt;append_child($text_node);&lt;br /&gt;
&lt;br /&gt;
Since &amp;lt;tt&amp;gt;$title&amp;lt;/tt&amp;gt; is already added to the document, there's no need to reappend it to &amp;lt;tt&amp;gt;$book&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The order in which you append children to nodes isn't important. The following four lines, which first append the text node to &amp;lt;tt&amp;gt;$title_element&amp;lt;/tt&amp;gt; and then to &amp;lt;tt&amp;gt;$book&amp;lt;/tt&amp;gt;, are equivalent to the previous code:&lt;br /&gt;
&lt;br /&gt;
 $title_element = $dom-&amp;gt;create_element('title');&lt;br /&gt;
 $text_node = $dom-&amp;gt;create_text_node('PHP Cookbook');&lt;br /&gt;
 &lt;br /&gt;
 $title_element-&amp;gt;append_child($text_node);&lt;br /&gt;
 $book-&amp;gt;append_child($title_element);&lt;br /&gt;
&lt;br /&gt;
To add an attribute, call &amp;lt;tt&amp;gt;set_attribute( )&amp;lt;/tt&amp;gt; upon a node, passing the attribute name and value as arguments:&lt;br /&gt;
&lt;br /&gt;
 $title-&amp;gt;set_attribute('cover', 'soft');&lt;br /&gt;
&lt;br /&gt;
If you print the title element now, it looks like this:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;title cover=&amp;quot;soft&amp;quot;&amp;gt;PHP Cookbook&amp;lt;/title&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you're finished, you can output the document as a string or to a file:&lt;br /&gt;
&lt;br /&gt;
 // put the string representation of the XML document in $books&lt;br /&gt;
 $books = $dom-&amp;gt;dump_mem( );&lt;br /&gt;
 &lt;br /&gt;
 // write the XML document to books.xml&lt;br /&gt;
 $dom-&amp;gt;dump_file('books.xml', false, true);&lt;br /&gt;
&lt;br /&gt;
The only parameter &amp;lt;tt&amp;gt;dump_mem( )&amp;lt;/tt&amp;gt; takes is an optional boolean value. An empty value or &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt; means &amp;quot;return the string as one long line.&amp;quot; A &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; value causes the XML to be nicely formatted with child nodes indented, like this:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;book&amp;gt;&lt;br /&gt;
   &amp;lt;title cover=&amp;quot;soft&amp;quot;&amp;gt;PHP Cookbook&amp;lt;/title&amp;gt;&lt;br /&gt;
 &amp;lt;/book&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass up to three values to &amp;lt;tt&amp;gt;dump_file( )&amp;lt;/tt&amp;gt; . The first one, which is mandatory, is the filename. The second is whether the file should be compressed with ''gzip''. The final value is the same pretty formatting option as &amp;lt;tt&amp;gt;dump_mem( )&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/XML#Generating XML Manually|Recipe 12.2]] for writing XML without DOM; [[PHP Cookbook/XML#Parsing XML with the DOM|Recipe 12.4]] for parsing XML with DOM; documentation on &amp;lt;tt&amp;gt;domxml_new_dom( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/domxml-new-dom'' and the DOM functions in general at ''http://www.php.net/domxml''; more information about the underlying DOM C library at ''http://xmlsoft.org/''.&lt;br /&gt;
&lt;br /&gt;
== Parsing XML with the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to parse an XML file using the DOM API. This puts the file into a tree, which you can process using DOM functions. With the DOM, it's easy to search for and retrieve elements that fit a certain set of criteria.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use PHP's DOM XML extension. Here's how to read XML from a file:&lt;br /&gt;
&lt;br /&gt;
 $dom = domxml_open_file('books.xml');&lt;br /&gt;
&lt;br /&gt;
Here's how to read XML from a variable:&lt;br /&gt;
&lt;br /&gt;
 $dom = domxml_open_mem($books);&lt;br /&gt;
&lt;br /&gt;
You can also get just a single node. Here's how to get the root node:&lt;br /&gt;
&lt;br /&gt;
 $root = $dom-&amp;gt;document_element( );&lt;br /&gt;
&lt;br /&gt;
Here's how to do a depth-first recursion to process all the nodes in a document:&lt;br /&gt;
&lt;br /&gt;
 function process_node($node) {&lt;br /&gt;
     if ($node-&amp;gt;has_child_nodes( )) {&lt;br /&gt;
         foreach($node-&amp;gt;child_nodes( ) as $n) {&lt;br /&gt;
             process_node($n);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     // process leaves&lt;br /&gt;
     if ($node-&amp;gt;node_type( ) =  = XML_TEXT_NODE) {&lt;br /&gt;
         $content = rtrim($node-&amp;gt;node_value( ));&lt;br /&gt;
         if (!empty($content)) {&lt;br /&gt;
             print &amp;quot;$content\n&amp;quot;;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
 process_node($root);&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
The W3C's DOM provides a platform- and language-neutral method that specifies the structure and content of a document. Using the DOM, you can read an XML document into a tree of nodes and then maneuver through the tree to locate information about a particular element or elements that match your criteria. This is called ''tree-based parsing'' . In contrast, the non-DOM XML functions allow you to do event-based parsing.&lt;br /&gt;
&lt;br /&gt;
Additionally, you can modify the structure by creating, editing, and deleting nodes. In fact, you can use the DOM XML functions to author a new XML document from scratch; see [[PHP Cookbook/XML#Generating XML with the DOM|Recipe 12.3]]&lt;br /&gt;
&lt;br /&gt;
One of the major advantages of the DOM is that by following the W3C's specification, many languages implement DOM functions in a similar manner. Therefore, the work of translating logic and instructions from one application to another is considerably simplified. PHP 4.3 comes with an updated series of DOM functions that are in stricter compliance with the DOM standard than previous versions of PHP. However, the functions are not yet 100% compliant. Future PHP versions should bring a closer alignment, but this may break some applications that need minor updates. Check the DOM XML material in the online PHP Manual at ''http://www.php.net/domxml'' for changes. Functions available in earlier versions of PHP are available, but deprecated.&lt;br /&gt;
&lt;br /&gt;
The DOM is large and complex. For more information, read the specification at ''http://www.w3.org/DOM/'' or pick up a copy of ''XML in a Nutshell''; [[PHP Cookbook/Files|Chapter 18]] discusses the DOM.&lt;br /&gt;
&lt;br /&gt;
For DOM parsing, PHP uses ''libxml'' , developed for the Gnome project. You can download it from ''http://www.xmlsoft.org''. To activate it, configure PHP with &amp;lt;tt&amp;gt;--with-dom&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
DOM functions in PHP are object-oriented. To move from one node to another, call methods such as &amp;lt;tt&amp;gt;$node-&amp;gt;child_nodes( )&amp;lt;/tt&amp;gt; , which returns an array of node objects, and &amp;lt;tt&amp;gt;$node-&amp;gt;parent_node( )&amp;lt;/tt&amp;gt; , which returns the parent node object. Therefore, to process a node, check its type and call a corresponding method:&lt;br /&gt;
&lt;br /&gt;
 // $node is the DOM parsed node &amp;lt;book cover=&amp;quot;soft&amp;quot;&amp;gt;PHP Cookbook&amp;lt;/book&amp;gt;&lt;br /&gt;
 $type = $node-&amp;gt;node_type();&lt;br /&gt;
 &lt;br /&gt;
 switch($type) { &lt;br /&gt;
 case XML_ELEMENT_NODE:&lt;br /&gt;
     // I'm a tag. I have a tagname property.&lt;br /&gt;
     print $node-&amp;gt;node_name();  // prints the tagname property: &amp;quot;book&amp;quot; &lt;br /&gt;
     print $node-&amp;gt;node_value(); // null&lt;br /&gt;
     break;&lt;br /&gt;
 case XML_ATTRIBUTE_NODE:&lt;br /&gt;
     // I'm an attribute. I have a name and a value property.&lt;br /&gt;
     print $node-&amp;gt;node_name();  // prints the name property: &amp;quot;cover&amp;quot;&lt;br /&gt;
     print $node-&amp;gt;node_value(); // prints the value property: &amp;quot;soft&amp;quot;&lt;br /&gt;
     break;&lt;br /&gt;
 case XML_TEXT_NODE:&lt;br /&gt;
     // I'm a piece of text inside an element.&lt;br /&gt;
     // I have a name and a content property.&lt;br /&gt;
     print $node-&amp;gt;node_name();  // prints the name property: &amp;quot;#text&amp;quot;&lt;br /&gt;
     print $node-&amp;gt;node_value(); // prints the content property: &amp;quot;PHP Cookbook&amp;quot;&lt;br /&gt;
     break;&lt;br /&gt;
 default:&lt;br /&gt;
     // another type&lt;br /&gt;
     break;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
To automatically search through a DOM tree for specific elements, use &amp;lt;tt&amp;gt;get_elements_by_tagname( )&amp;lt;/tt&amp;gt; . Here's how to do so with multiple book records:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;books&amp;gt;&lt;br /&gt;
     &amp;lt;book&amp;gt;&lt;br /&gt;
         &amp;lt;title&amp;gt;PHP Cookbook&amp;lt;/title&amp;gt;&lt;br /&gt;
         &amp;lt;author&amp;gt;Sklar&amp;lt;/author&amp;gt;&lt;br /&gt;
         &amp;lt;author&amp;gt;Trachtenberg&amp;lt;/author&amp;gt;&lt;br /&gt;
         &amp;lt;subject&amp;gt;PHP&amp;lt;/subject&amp;gt;&lt;br /&gt;
     &amp;lt;/book&amp;gt;&lt;br /&gt;
     &amp;lt;book&amp;gt;&lt;br /&gt;
         &amp;lt;title&amp;gt;Perl Cookbook&amp;lt;/title&amp;gt;&lt;br /&gt;
         &amp;lt;author&amp;gt;Christiansen&amp;lt;/author&amp;gt;&lt;br /&gt;
         &amp;lt;author&amp;gt;Torkington&amp;lt;/author&amp;gt;&lt;br /&gt;
         &amp;lt;subject&amp;gt;Perl&amp;lt;/subject&amp;gt;&lt;br /&gt;
     &amp;lt;/book&amp;gt;&lt;br /&gt;
 &amp;lt;/books&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's how to find all authors:&lt;br /&gt;
&lt;br /&gt;
 // find and print all authors&lt;br /&gt;
 $authors = $dom-&amp;gt;get_elements_by_tagname('author');&lt;br /&gt;
 &lt;br /&gt;
 // loop through author elements&lt;br /&gt;
 foreach ($authors as $author) { &lt;br /&gt;
     // child_nodes( ) hold the author values&lt;br /&gt;
     $text_nodes = $author-&amp;gt;child_nodes( );&lt;br /&gt;
 &lt;br /&gt;
     foreach ($text_nodes as $text) {    &lt;br /&gt;
          print $text-&amp;gt;node_value( );&lt;br /&gt;
     }&lt;br /&gt;
     print &amp;quot;\n&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;get_elements_by_tagname( )&amp;lt;/tt&amp;gt; function returns an array of element node objects. By looping through each element's children, you can get to the text node associated with that element. From there, you can pull out the node values, which in this case are the names of the book authors, such as &amp;lt;tt&amp;gt;Sklar&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Trachtenberg&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/XML#Generating XML Manually|Recipe 12.2]] for writing XML without DOM; [[PHP Cookbook/XML#Generating XML with the DOM|Recipe 12.3]] for writing XML with DOM; [[PHP Cookbook/XML#Parsing XML with SAX|Recipe 12.5]] for event-based XML parsing; documentation on &amp;lt;tt&amp;gt;domxml_open_file( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/domxml-open-file'', &amp;lt;tt&amp;gt;domxml_open_mem( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/domxml-open-mem'', and the DOM functions in general at ''http://www.php.net/domxml''; more information about the underlying DOM C library at ''http://xmlsoft.org/''.&lt;br /&gt;
&lt;br /&gt;
== Parsing XML with SAX ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to parse an XML document and format it on an event basis, such as when the parser encounters a new opening or closing element tag. For instance, you want to turn an RSS feed into HTML.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use the parsing functions in PHP's XML extension:&lt;br /&gt;
&lt;br /&gt;
 $xml = xml_parser_create();&lt;br /&gt;
 $obj = new Parser_Object;  // a class to assist with parsing&lt;br /&gt;
 &lt;br /&gt;
 xml_set_object($xml,$obj);&lt;br /&gt;
 xml_set_element_handler($xml, 'start_element', 'end_element');&lt;br /&gt;
 xml_set_character_data_handler($xml, 'character_data');&lt;br /&gt;
 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, false);&lt;br /&gt;
 &lt;br /&gt;
 $fp = fopen('data.xml', 'r') or die(&amp;quot;Can't read XML data.&amp;quot;);&lt;br /&gt;
 while ($data = fread($fp, 4096)) {&lt;br /&gt;
   xml_parse($xml, $data, feof($fp)) or die(&amp;quot;Can't parse XML data&amp;quot;);&lt;br /&gt;
 }       &lt;br /&gt;
 fclose($fp);&lt;br /&gt;
 &lt;br /&gt;
 xml_parser_free($xml);&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
These XML parsing functions require the ''expat'' library. However, because Apache 1.3.7 and later is bundled with ''expat'', this library is already installed on most machines. Therefore, PHP enables these functions by default, and you don't need to explicitly configure PHP to support XML.&lt;br /&gt;
&lt;br /&gt;
''expat'' parses XML documents and allows you to configure the parser to call functions when it encounters different parts of the file, such as an opening or closing element tag or character data (the text between tags). Based on the tag name, you can then choose whether to format or ignore the data. This is known as ''event-based parsing'' and contrasts with DOM XML, which use a tree-based parser.&lt;br /&gt;
&lt;br /&gt;
A popular API for event-based XML parsing is SAX: Simple API for XML. Originally developed only for Java, SAX has spread to other languages. PHP's XML functions follow SAX conventions. For more on the latest version of SAX — SAX2 — see ''SAX2'' by David Brownell (O'Reilly).&lt;br /&gt;
&lt;br /&gt;
PHP supports two interfaces to ''expat'': a procedural one and an object-oriented one. Since the procedural interface practically forces you to use global variables to accomplish any meaningful task, we prefer the object-oriented version. With the object-oriented interface, you can bind an object to the parser and interact with the object while processing XML. This allows you to use object properties instead of global variables.&lt;br /&gt;
&lt;br /&gt;
Here's an example application of ''expat'' that shows how to process an RSS feed and transform it into HTML. For more on RSS, see [[PHP Cookbook/XML#Reading RSS Feeds|Recipe 12.12]]. The script starts with the standard XML processing code, followed by the objects created to parse RSS specifically:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$xml = xml_parser_create( );&lt;br /&gt;
$rss = new pc_RSS_parser;&lt;br /&gt;
&lt;br /&gt;
xml_set_object($xml, $rss);&lt;br /&gt;
xml_set_element_handler($xml, 'start_element', 'end_element');&lt;br /&gt;
xml_set_character_data_handler($xml, 'character_data');&lt;br /&gt;
xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, false);&lt;br /&gt;
&lt;br /&gt;
$feed = 'http://pear.php.net/rss.php';&lt;br /&gt;
$fp = fopen($feed, 'r') or die(&amp;quot;Can't read RSS data.&amp;quot;);&lt;br /&gt;
while ($data = fread($fp, 4096)) {&lt;br /&gt;
  xml_parse($xml, $data, feof($fp)) or die(&amp;quot;Can't parse RSS data&amp;quot;);&lt;br /&gt;
}       &lt;br /&gt;
fclose($fp);&lt;br /&gt;
&lt;br /&gt;
xml_parser_free($xml);&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After creating a new XML parser and an instance of the &amp;lt;tt&amp;gt;pc_RSS_parser&amp;lt;/tt&amp;gt; class, configure the parser. First, bind the object to the parser; this tells the parser to call the object's methods instead of global functions. Then call &amp;lt;tt&amp;gt;xml_set_element_handler( )&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;xml_set_character_data_handler( )&amp;lt;/tt&amp;gt; to specify the method names the parser should call when it encounters elements and character data. The first argument to both functions is the parser instance; the other arguments are the function names. With &amp;lt;tt&amp;gt;xml_set_element_handler( )&amp;lt;/tt&amp;gt;, the middle and last arguments are the functions to call when a tag opens and closes, respectively. The &amp;lt;tt&amp;gt;xml_set_character_data_handler( )&amp;lt;/tt&amp;gt; function takes only one additional argument — the function to call when it processes character data.&lt;br /&gt;
&lt;br /&gt;
Because an object has been associated with our parser, when that parser finds the string &amp;lt;tt&amp;gt;&amp;lt;tag&amp;gt;data&amp;lt;/tag&amp;gt;&amp;lt;/tt&amp;gt;, it calls &amp;lt;tt&amp;gt;$rss-&amp;gt;start_element( )&amp;lt;/tt&amp;gt; when it reaches &amp;lt;tt&amp;gt;&amp;lt;tag&amp;gt;&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;$rss-&amp;gt;character_data( )&amp;lt;/tt&amp;gt; when it reaches &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;; and &amp;lt;tt&amp;gt;$rss-&amp;gt;end_element( )&amp;lt;/tt&amp;gt; when it reaches &amp;lt;tt&amp;gt;&amp;lt;/tag&amp;gt;&amp;lt;/tt&amp;gt;. The parser can't be configured to automatically call individual methods for each specific tag; instead, you must handle this yourself. However, the PEAR package &amp;lt;tt&amp;gt;XML_Transform&amp;lt;/tt&amp;gt; provides an easy way to assign handlers on a tag-by-by basis.&lt;br /&gt;
&lt;br /&gt;
The last XML parser configuration option tells the parser not to automatically convert all tags to uppercase. By default, the parser folds tags into capital letters, so &amp;lt;tt&amp;gt;&amp;lt;tag&amp;gt;&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;&amp;lt;TAG&amp;gt;&amp;lt;/tt&amp;gt; both become the same element. Since XML is case-sensitive, and most feeds use lowercase element names, this feature should be disabled.&lt;br /&gt;
&lt;br /&gt;
With the parser configured, feed the data to the parser:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$feed = 'http://pear.php.net/rss.php';&lt;br /&gt;
$fp = fopen($feed, 'r') or die(&amp;quot;Can't read RSS data.&amp;quot;);&lt;br /&gt;
while ($data = fread($fp, 4096)) {&lt;br /&gt;
  xml_parse($xml, $data, feof($fp)) or die(&amp;quot;Can't parse RSS data&amp;quot;);&lt;br /&gt;
}       &lt;br /&gt;
fclose($fp);&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In order to curb memory usage, load the file in 4096-byte chunks, and feed each piece to the parser one at a time. This requires you to write the handler functions that will accommodate text arriving in multiple calls and not assume the entire string comes in all at once.&lt;br /&gt;
&lt;br /&gt;
Last, while PHP cleans up any open parsers when the request ends, you can also manually close the parser by calling &amp;lt;tt&amp;gt;xml_parser_free( )&amp;lt;/tt&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Now that the generic parsing is properly set up, add the &amp;lt;tt&amp;gt;pc_RSS_item&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;pc_RSS_parser&amp;lt;/tt&amp;gt; classes, as shown in Examples [[PHP Cookbook/XML#phpckbk-CHP-12-EX-1|Example 12-1]] and [[PHP Cookbook/XML#phpckbk-CHP-12-EX-2|Example 12-2]], to handle a RSS document.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;phpckbk-CHP-12-EX-1&amp;quot;&amp;gt;&lt;br /&gt;
'''Example 12-1. pc_RSS_item'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;class pc_RSS_item {&lt;br /&gt;
&lt;br /&gt;
  var $title = '';&lt;br /&gt;
  var $description = '';&lt;br /&gt;
  var $link = '';&lt;br /&gt;
&lt;br /&gt;
  function display() {&lt;br /&gt;
    printf('&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;%s&amp;lt;/p&amp;gt;',&lt;br /&gt;
            $this-&amp;gt;link,htmlspecialchars($this-&amp;gt;title),&lt;br /&gt;
            htmlspecialchars($this-&amp;gt;description));&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;phpckbk-CHP-12-EX-2&amp;quot;&amp;gt;&lt;br /&gt;
'''Example 12-2. pc_RSS_parser'''&lt;br /&gt;
&lt;br /&gt;
 class pc_RSS_parser {&lt;br /&gt;
   &lt;br /&gt;
   var $tag;&lt;br /&gt;
   var $item;&lt;br /&gt;
   &lt;br /&gt;
   function start_element($parser, $tag, $attributes) {&lt;br /&gt;
     if ('item' == $tag) {&lt;br /&gt;
       $this-&amp;gt;item = new pc_RSS_item;&lt;br /&gt;
     } elseif (!empty($this-&amp;gt;item)) {&lt;br /&gt;
       $this-&amp;gt;tag = $tag;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   function end_element($parser, $tag) {&lt;br /&gt;
     if ('item' == $tag) {&lt;br /&gt;
       $this-&amp;gt;item-&amp;gt;display();&lt;br /&gt;
       unset($this-&amp;gt;item); &lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   function character_data($parser, $data) {&lt;br /&gt;
     if (!empty($this-&amp;gt;item)) {&lt;br /&gt;
       if (isset($this-&amp;gt;item-&amp;gt;{$this-&amp;gt;tag})) {&lt;br /&gt;
         $this-&amp;gt;item-&amp;gt;{$this-&amp;gt;tag} .= trim($data);&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }  &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;pc_RSS_item&amp;lt;/tt&amp;gt; class provides an interface to an individual feed item. This removes the details of displaying each item from the general parsing code and makes it easy to reset the data for a new item by calling &amp;lt;tt&amp;gt;unset( )&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;pc_RSS_item::display( )&amp;lt;/tt&amp;gt; method prints out an HTML-formatted RSS item. It calls &amp;lt;tt&amp;gt;htmlspecialchars( )&amp;lt;/tt&amp;gt; to reencode any necessary entities, because ''expat'' decodes them into regular characters while parsing the document. This reencoding, however, breaks on feeds that place HTML in the title and description instead of plaintext.&lt;br /&gt;
&lt;br /&gt;
Within &amp;lt;tt&amp;gt;pc_RSS_parser( )&amp;lt;/tt&amp;gt;, the &amp;lt;tt&amp;gt;start_element( )&amp;lt;/tt&amp;gt; method takes three parameters: the XML parser, the name of the tag, and an array of attribute/value pairs (if any) from the element. PHP automatically supplies these values to the handler as part of the parsing process.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;start_element( )&amp;lt;/tt&amp;gt; method checks the value of &amp;lt;tt&amp;gt;$tag&amp;lt;/tt&amp;gt;. If it's &amp;lt;tt&amp;gt;item&amp;lt;/tt&amp;gt;, the parser's found a new RSS item, and a new &amp;lt;tt&amp;gt;pc_RSS_item&amp;lt;/tt&amp;gt; object is instantiated. Otherwise, it checks to see if &amp;lt;tt&amp;gt;$this-&amp;gt;item&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;empty( )&amp;lt;/tt&amp;gt;; if it isn't, the parser is inside an &amp;lt;tt&amp;gt;item&amp;lt;/tt&amp;gt; element. It's then necessary to record the tag's name, so that the &amp;lt;tt&amp;gt;character_data( )&amp;lt;/tt&amp;gt; method knows which property to assign its value to. If it is empty, this part of the RSS feed isn't necessary for our application, and it's ignored.&lt;br /&gt;
&lt;br /&gt;
When the parser finds a closing &amp;lt;tt&amp;gt;item&amp;lt;/tt&amp;gt; tag, the corresponding &amp;lt;tt&amp;gt;end_element( )&amp;lt;/tt&amp;gt; method first prints the RSS item, then cleans up by deleting the object.&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;tt&amp;gt;character_data( )&amp;lt;/tt&amp;gt; method is responsible for assigning the values of &amp;lt;tt&amp;gt;title&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;description&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; to the RSS item. After making sure it's inside an &amp;lt;tt&amp;gt;item&amp;lt;/tt&amp;gt; element, it checks that the current tag is one of the properties of &amp;lt;tt&amp;gt;pc_RSS_item&amp;lt;/tt&amp;gt;. Without this check, if the parser encountered an element other than those three, its value would also be assigned to the object. The &amp;lt;tt&amp;gt;{ }&amp;lt;/tt&amp;gt; s are needed to set the object property dereferencing order. Notice how &amp;lt;tt&amp;gt;trim($data)&amp;lt;/tt&amp;gt; is appended to the property instead of a direct assignment. This is done to handle cases in which the character data is split across the 4096-byte chunks retrieved by &amp;lt;tt&amp;gt;fread( )&amp;lt;/tt&amp;gt;; it also removes the surrounding whitespace found in the RSS feed.&lt;br /&gt;
&lt;br /&gt;
If you run the code on this sample RSS feed:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;rss version=&amp;quot;0.93&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;channel&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;PHP Announcements&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;link&amp;gt;http://www.php.net/&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;description&amp;gt;All the latest information on PHP.&amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;PHP 5.0 Released!&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;http://www.php.net/downloads.php&amp;lt;/link&amp;gt;&lt;br /&gt;
    &amp;lt;description&amp;gt;The newest version of PHP is now available.&amp;lt;/description&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/channel&amp;gt;&lt;br /&gt;
&amp;lt;/rss&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It produces this HTML:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;http://www.php.net/downloads.php&amp;quot;&amp;gt;PHP 5.0 Released!&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The newest version of PHP is now available.&amp;lt;/p&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/XML#Parsing XML with the DOM|Recipe 12.4]] for tree-based XML parsing with DOM; [[PHP Cookbook/XML#Reading RSS Feeds|Recipe 12.12]] for more on parsing RSS; documentation on &amp;lt;tt&amp;gt;xml_parser_create( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xml-parser-create'', &amp;lt;tt&amp;gt;xml_element_handler( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xml-element-handler'', &amp;lt;tt&amp;gt;xml_character_handler( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xml-character-handler'', &amp;lt;tt&amp;gt;xml_parse( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xml-parse'', and the XML functions in general at ''http://www.php.net/xml''; the official SAX site at ''http://www.saxproject.org/''.&lt;br /&gt;
&lt;br /&gt;
== Transforming XML with XSLT ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You have a XML document and a XSL stylesheet. You want to transform the document using XSLT and capture the results. This lets you apply stylesheets to your data and create different versions of your content for different media.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use PHP's XSLT extension:&lt;br /&gt;
&lt;br /&gt;
 $xml = 'data.xml';&lt;br /&gt;
 $xsl = 'stylesheet.xsl';&lt;br /&gt;
 &lt;br /&gt;
 $xslt = xslt_create( );&lt;br /&gt;
 $results = xslt_process($xslt, $xml, $xsl);&lt;br /&gt;
 &lt;br /&gt;
 if (!$results) {&lt;br /&gt;
     error_log(&amp;quot;XSLT Error: #&amp;quot;.xslt_errno($xslt).&amp;quot;: &amp;quot;.xslt_error($xslt));&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 xslt_free($xslt);&lt;br /&gt;
&lt;br /&gt;
The transformed text is stored in &amp;lt;tt&amp;gt;$results&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
XML documents describe the content of data, but they don't contain any information about how those data should be displayed. However, when XML content is coupled with a stylesheet described using XSL (eXtensible Stylesheet Language), the content is displayed according to specific visual rules.&lt;br /&gt;
&lt;br /&gt;
The glue between XML and XSL is XSLT, which stands for eXtensible Stylesheet Language Transformations. These transformations apply the series of rules enumerated in the stylesheet to your XML data. So, just as PHP parses your code and combines it with user input to create a dynamic page, an XSLT program uses XSL and XML to output a new page that contains more XML, HTML, or any other format you can describe.&lt;br /&gt;
&lt;br /&gt;
There are a few XSLT programs available, each with different features and limitations. PHP currently supports only the Sablotron XSLT processor, but in the future you'll be able to use other programs, such as Xalan and Libxslt. You can download Sablotron from ''http://www.gingerall.com''. To enable Sablotron for XSLT processing, configure PHP with both &amp;lt;tt&amp;gt;--enable-xslt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--with-xslt-sablot&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Processing documents takes a few steps. First, you need to grab a handle to a new instance of an XSLT processor with &amp;lt;tt&amp;gt;xslt_create( )&amp;lt;/tt&amp;gt; . Then, to transform the files, use &amp;lt;tt&amp;gt;xslt_process( )&amp;lt;/tt&amp;gt; to make the transformation and check the results:&lt;br /&gt;
&lt;br /&gt;
 $xml = 'data.xml';&lt;br /&gt;
 $xsl = 'stylesheet.xsl';&lt;br /&gt;
 &lt;br /&gt;
 $xslt = xslt_create( );&lt;br /&gt;
 $results = xslt_process($xslt, $xml, $xsl);&lt;br /&gt;
&lt;br /&gt;
You start by defining variables to store the filenames for the XML data and the XSL stylesheet. They're the first two parameters to the transforming function, &amp;lt;tt&amp;gt;xslt_process( )&amp;lt;/tt&amp;gt;. If the fourth argument is missing, as it is here, or set to &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, the function returns the results. Otherwise, it writes the resulting data to the filename passed:&lt;br /&gt;
&lt;br /&gt;
 xslt_process($xslt, $xml, $xsl, 'data.html');&lt;br /&gt;
&lt;br /&gt;
If you want to provide your XML and XSL data from variables instead of files, call &amp;lt;tt&amp;gt;xslt_process( )&amp;lt;/tt&amp;gt; with a fifth parameter, which allows you to substitute string placeholders for your files:&lt;br /&gt;
&lt;br /&gt;
 // grab data from database&lt;br /&gt;
 $r = mysql_query(&amp;quot;SELECT pages.page AS xml, templates.template AS xsl&lt;br /&gt;
                   FROM pages, templates&lt;br /&gt;
                   WHERE pages.id=$id AND templates.id=pages.template&amp;quot;) &lt;br /&gt;
      or die(&amp;quot;$php_errormsg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 $obj = mysql_fetch_object($r);&lt;br /&gt;
 $xml = $obj-&amp;gt;xml;&lt;br /&gt;
 $xsl = $obj-&amp;gt;xsl;&lt;br /&gt;
 &lt;br /&gt;
 // map the strings to args&lt;br /&gt;
 $args = array('/_xml' =&amp;gt; $xml,&lt;br /&gt;
               '/_xsl' =&amp;gt; $xsl);&lt;br /&gt;
 &lt;br /&gt;
 $results = xslt_process($xslt, 'arg:/_xml', 'arg:/_xsl', NULL, $args);&lt;br /&gt;
&lt;br /&gt;
When reading and writing files, Sablotron supports two types of URIs. The PHP default is &amp;lt;tt&amp;gt;file&amp;lt;/tt&amp;gt;:, so Sablotron looks for the data on the filesystem. Sablotron also uses a custom URI of &amp;lt;tt&amp;gt;arg&amp;lt;/tt&amp;gt;:, which allows users to alternatively pass in data using arguments. That's the feature used here.&lt;br /&gt;
&lt;br /&gt;
In the previous example, the data for the XML and XSL comes from a database, but, it can arrive from anywhere, such as a remote URL or POSTed data. Once you've obtained the data, create the &amp;lt;tt&amp;gt;$args&amp;lt;/tt&amp;gt; array. This sets up mappings between the argument names and the variable names. The keys of the associative array are the argument names passed to &amp;lt;tt&amp;gt;xslt_process( )&amp;lt;/tt&amp;gt;; the values are the variables holding the data. By convention, &amp;lt;tt&amp;gt;/_xml&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/_xsl&amp;lt;/tt&amp;gt; are the argument names; however, you can use others.&lt;br /&gt;
&lt;br /&gt;
Then call &amp;lt;tt&amp;gt;xslt_process( )&amp;lt;/tt&amp;gt; and in place of &amp;lt;tt&amp;gt;data.xml&amp;lt;/tt&amp;gt;, use &amp;lt;tt&amp;gt;arg:/_xml&amp;lt;/tt&amp;gt;, with &amp;lt;tt&amp;gt;arg&amp;lt;/tt&amp;gt;: being the string that lets the extension know to look in the &amp;lt;tt&amp;gt;$args&amp;lt;/tt&amp;gt; array. Because you're passing in &amp;lt;tt&amp;gt;$args&amp;lt;/tt&amp;gt; as the fifth parameter, you need to pass &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; as the fourth argument; this makes sure the function returns the results.&lt;br /&gt;
&lt;br /&gt;
Error checking is done using &amp;lt;tt&amp;gt;xslt_error( )&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;xslt_errno( )&amp;lt;/tt&amp;gt; functions:&lt;br /&gt;
&lt;br /&gt;
 if (!$results) {&lt;br /&gt;
     error_log('XSLT Error: #' . xslt_errno($xslt) . ': ' . xslt_error($xslt));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;xslt_error( )&amp;lt;/tt&amp;gt; function returns a formatted message describing the error, while &amp;lt;tt&amp;gt;xslt_errno( )&amp;lt;/tt&amp;gt; provides a numeric error code.&lt;br /&gt;
&lt;br /&gt;
To set up your own custom error handling code, register a function using &amp;lt;tt&amp;gt;xslt_set_error_handler( )&amp;lt;/tt&amp;gt;. If there are errors, that function is automatically called instead of any built-in error handler.&lt;br /&gt;
&lt;br /&gt;
 function xslt_error_handler($processor, $level, $number, $messages) {&lt;br /&gt;
     error_log(&amp;quot;XSLT Error: #$level&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 xslt_set_error_handler($xslt, 'xslt_error_handler');&lt;br /&gt;
&lt;br /&gt;
Finally, PHP cleans up any open XSLT processors when the request ends, but here's how to manually close the processor and free its memory:&lt;br /&gt;
&lt;br /&gt;
 xslt_free($xslt);&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
Documentation on &amp;lt;tt&amp;gt;xslt_create( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xslt-create'', &amp;lt;tt&amp;gt;xslt_process( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xslt-process'', &amp;lt;tt&amp;gt;xslt_errno( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xslt-errno'', &amp;lt;tt&amp;gt;xslt_error( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xslt-error'', &amp;lt;tt&amp;gt;xslt_error_handler( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xslt-error-handler'', and &amp;lt;tt&amp;gt;xslt_free( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xslt-free''; ''XSLT'', by Doug Tidwell (O'Reilly).&lt;br /&gt;
&lt;br /&gt;
== Sending XML-RPC Requests ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to be an XML-RPC client and make requests of a server. XML-RPC lets PHP make function calls to web servers, even if they don't use PHP. The retrieved data is then automatically converted to PHP variables for use in your application.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use PHP's built-in XML-RPC extension with some helper functions. As of PHP 4.1, PHP bundles the ''xmlrpc-epi'' extension. Unfortunately, xmlrpc-epi does not have any native C functions for taking a XML-RPC formatted string and making a request. However, the folks behind xmlrpc-epi have a series of helper functions written in PHP available for download at ''http://xmlrpc-epi.sourceforge.net/xmlrpc_php/index.php''. The only file used here is the one named ''index.php'', which is located in ''xmlrpc_php/''. To install it, just copy that file to a location where PHP can find it in its &amp;lt;tt&amp;gt;include_path&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here's some client code that calls a function on an XML-RPC server that returns state names:&lt;br /&gt;
&lt;br /&gt;
 // this is the default file name from the package&lt;br /&gt;
 // kept here to avoid confusion over the file name&lt;br /&gt;
 require 'utils.php';&lt;br /&gt;
 &lt;br /&gt;
 // server settings&lt;br /&gt;
 $host = 'betty.userland.com';&lt;br /&gt;
 $port = 80;&lt;br /&gt;
 $uri = '/RPC2';&lt;br /&gt;
 &lt;br /&gt;
 // request settings&lt;br /&gt;
 // pass in a number from 1-50; get the nth state in alphabetical order&lt;br /&gt;
 // 1 is Alabama, 50 is Wyoming&lt;br /&gt;
 $method = 'examples.getStateName';&lt;br /&gt;
 $args = array(32); // data to be passed&lt;br /&gt;
 &lt;br /&gt;
 // make associative array out of these variables&lt;br /&gt;
 $request = compact('host', 'port', 'uri', 'method', 'args');&lt;br /&gt;
 &lt;br /&gt;
 // this function makes the XML-RPC request&lt;br /&gt;
 $result = xu_rpc_http_concise($request);&lt;br /&gt;
 &lt;br /&gt;
 print &amp;quot;I love $result!\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
XML-RPC, a format created by Userland Software, allows you to make a request to a web server using HTTP. The request itself is a specially formatted XML document. As a client, you build up an XML request to send that fits with the XML-RPC specification. You then send it to the server, and the server replies with an XML document. You then parse the XML to find the results. In the Solution, the XML-RPC server returns a state name, so the code prints:&lt;br /&gt;
&lt;br /&gt;
 I love New York!&lt;br /&gt;
&lt;br /&gt;
Unlike earlier implementations of XML-RPC, which were coded in PHP, the current bundled extension is written in C, so there is a significant speed increase in processing time. To enable this extension while configuring PHP, add &amp;lt;tt&amp;gt;--with-xmlrpc&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The server settings tell PHP which web site to contact to make the request. The &amp;lt;tt&amp;gt;$host&amp;lt;/tt&amp;gt; is the hostname of the machine; &amp;lt;tt&amp;gt;$port&amp;lt;/tt&amp;gt; is the port the web server is running on, which is usually port 80; and &amp;lt;tt&amp;gt;$uri&amp;lt;/tt&amp;gt; is the pathname to the XML-RPC server you wish to contact. This request is equivalent to ''http://betty.userland.com:80/RPC2''. If no port is given, the function defaults to port 80, and the default URI is the web server root, &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The request settings are the function to call and the data to pass to the function. The method &amp;lt;tt&amp;gt;examples.getStateName&amp;lt;/tt&amp;gt; takes an integer from 1 to 50 and returns a string with the name of the U.S. state, in alphabetical order. In XML-RPC, method names can have periods, while in PHP, they cannot. If they could, the PHP equivalent to passing &amp;lt;tt&amp;gt;32&amp;lt;/tt&amp;gt; as the argument to the XML-RPC call to &amp;lt;tt&amp;gt;examples.getStateName&amp;lt;/tt&amp;gt; is calling a function named &amp;lt;tt&amp;gt;examples.getStateName( )&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 examples.getStateName(32);&lt;br /&gt;
&lt;br /&gt;
In XML-RPC, it looks like this:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version='1.0' encoding=&amp;quot;iso-8859-1&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;methodCall&amp;gt;&lt;br /&gt;
 &amp;lt;methodName&amp;gt;examples.getStateName&amp;lt;/methodName&amp;gt;&lt;br /&gt;
 &amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&lt;br /&gt;
    &amp;lt;int&amp;gt;32&amp;lt;/int&amp;gt;&lt;br /&gt;
   &amp;lt;/value&amp;gt;&lt;br /&gt;
  &amp;lt;/param&amp;gt;&lt;br /&gt;
 &amp;lt;/params&amp;gt;&lt;br /&gt;
 &amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server settings and request information go into a single associative array that is passed to &amp;lt;tt&amp;gt;xu_rpc_http_concise( )&amp;lt;/tt&amp;gt; . As a shortcut, call &amp;lt;tt&amp;gt;compact( )&amp;lt;/tt&amp;gt; , which is identical to:&lt;br /&gt;
&lt;br /&gt;
 $request = array('host'   =&amp;gt; $host,&lt;br /&gt;
                  'port'   =&amp;gt; $port,&lt;br /&gt;
                  'uri'    =&amp;gt; $uri,&lt;br /&gt;
                  'method' =&amp;gt; $method,&lt;br /&gt;
                  'args'   =&amp;gt; $args);&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;xu_rpc_http_concise( )&amp;lt;/tt&amp;gt; function makes the XML-RPC call and returns the results. Since the return value is a string, you can print &amp;lt;tt&amp;gt;$results&amp;lt;/tt&amp;gt; directly. If the XML-RPC call returns multiple values, &amp;lt;tt&amp;gt;xu_rpc_http_concise( )&amp;lt;/tt&amp;gt; returns an array.&lt;br /&gt;
&lt;br /&gt;
There are 10 different parameters that can be passed in the array to &amp;lt;tt&amp;gt;xu_rpc_http_concise( )&amp;lt;/tt&amp;gt;, but the only one that's required is &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt;. The parameters are shown in [[PHP Cookbook/XML#phpckbk-CHP-12-TABLE-1|Table 12-1]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;phpckbk-CHP-12-TABLE-1&amp;quot;&amp;gt;&lt;br /&gt;
'''Table 12-1. Parameters for xu_rpc_http_concise( )'''&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; || Server hostname&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;uri&amp;lt;/tt&amp;gt; || Server URI (default /)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;port&amp;lt;/tt&amp;gt; || Server port (default 80)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;method&amp;lt;/tt&amp;gt; || Name of method to call&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;args&amp;lt;/tt&amp;gt; || Arguments to pass to method&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;debug&amp;lt;/tt&amp;gt; || Debug level (0 to 2: 0 is none, 2 is lots)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;timeout&amp;lt;/tt&amp;gt; || Number of seconds before timing out the request; a value of 0 means never timeout&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;user&amp;lt;/tt&amp;gt; || Username for Basic HTTP Authentication, if necessary&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;pass&amp;lt;/tt&amp;gt; || Password for Basic HTTP Authentication, if necessary&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;secure&amp;lt;/tt&amp;gt; || Use SSL for encrypted transmissions; requires PHP to be built with SSL support (pass any true value)&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/XML#Receiving XML-RPC Requests|Recipe 12.8]] for more on XML-RPC servers; PHP helper functions for use with the xmlrpc-epi extension at ''http://xmlrpc-epi.sourceforge.net/''; ''Programming Web Services with XML-RPC'', by Simon St. Laurent, Joe Johnston, and Edd Dumbill (O'Reilly); more on XML-RPC at ''http://www.xml-rpc.com''&lt;br /&gt;
&lt;br /&gt;
== Receiving XML-RPC Requests ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to create an XML-RPC server and respond to XML-RPC requests. This allows any XML-RPC-enabled client to ask your server questions and you to reply with data.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use PHP's XML-RPC extension. Here is a PHP version of the Userland XML-RPC demonstration application that returns an ISO 8601 string with the current date and time:&lt;br /&gt;
&lt;br /&gt;
 // this is the function exposed as &amp;quot;get_time( )&amp;quot;&lt;br /&gt;
 function return_time($method, $args) {&lt;br /&gt;
    return date('Ymd\THis');&lt;br /&gt;
 }&lt;br /&gt;
   &lt;br /&gt;
 $server = xmlrpc_server_create( ) or die(&amp;quot;Can't create server&amp;quot;);&lt;br /&gt;
 xmlrpc_server_register_method($server, 'return_time', 'get_time') &lt;br /&gt;
     or die(&amp;quot;Can't register method.&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
 $request = $GLOBALS['HTTP_RAW_POST_DATA'];&lt;br /&gt;
 $options = array('output_type' =&amp;gt; 'xml', 'version' =&amp;gt; 'xmlrpc');&lt;br /&gt;
 &lt;br /&gt;
 print xmlrpc_server_call_method($server, $request, NULL, $options)&lt;br /&gt;
     or die(&amp;quot;Can't call method&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
 xmlrpc_server_destroy($server);&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
Since the bundled XML-RPC extension, xmlrpc-epi, is written in C, it processes XML-RPC requests in a speedy and efficient fashion. Add &amp;lt;tt&amp;gt;--with-xmlrpc&amp;lt;/tt&amp;gt; to your configure string to enable this extension during compile time. For more on XML-RPC, see [[PHP Cookbook/XML#Sending XML-RPC Requests|Recipe 12.7]].&lt;br /&gt;
&lt;br /&gt;
The Solution begins with a definition of the PHP function to associate with the XML-RPC method. The name of the function is &amp;lt;tt&amp;gt;return_time( )&amp;lt;/tt&amp;gt; . This is later linked with the &amp;lt;tt&amp;gt;get_time( )&amp;lt;/tt&amp;gt; XML-RPC method:&lt;br /&gt;
&lt;br /&gt;
 function return_time($method, $args) {&lt;br /&gt;
    return date('Ymd\THis');&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The function returns an ISO 8601-formatted string with the current date and time. We escape the &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; inside the call to &amp;lt;tt&amp;gt;date( )&amp;lt;/tt&amp;gt; because the specification requires a literal &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; to divide the date part and the time part. For August 21, 2002 at 3:03:51 P.M., the return value is &amp;lt;tt&amp;gt;20020821T150351&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The function is automatically called with two parameters: the name of the XML-RPC method the server is responding to and an array of method arguments passed by the XML-RPC client to the server. In this example, the server ignores both variables.&lt;br /&gt;
&lt;br /&gt;
Next, create the XML-RPC server and register the &amp;lt;tt&amp;gt;get_time( )&amp;lt;/tt&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
 $server = xmlrpc_server_create( ) or die(&amp;quot;Can't create server&amp;quot;);&lt;br /&gt;
 xmlrpc_server_register_method($server, 'return_time', 'get_time');&lt;br /&gt;
&lt;br /&gt;
We create a new server and assign it to &amp;lt;tt&amp;gt;$server&amp;lt;/tt&amp;gt;, then call &amp;lt;tt&amp;gt;xmlrpc_server_register_method( )&amp;lt;/tt&amp;gt; with three parameters. The first is the newly created server, the second is the name of the method to register, and the third is the name of the PHP function to handle the request.&lt;br /&gt;
&lt;br /&gt;
Now that everything is configured, tell the XML-RPC server to dispatch the method for processing and print the results to the client:&lt;br /&gt;
&lt;br /&gt;
 $request = $GLOBALS['HTTP_RAW_POST_DATA'];&lt;br /&gt;
 $options = array('output_type' =&amp;gt; 'xml', 'version' =&amp;gt; 'xmlrpc');&lt;br /&gt;
 &lt;br /&gt;
 print xmlrpc_server_call_method($server, $request, NULL, $options);&lt;br /&gt;
&lt;br /&gt;
The client request comes in as POST data. PHP converts HTTP POST data to variables, but this is XML-RPC data, so the server needs to access the unparsed data, which is stored in &amp;lt;tt&amp;gt;$GLOBALS['HTTP_RAW_POST_DATA']&amp;lt;/tt&amp;gt;. In this example, the request XML looks like this:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;iso-8859-1&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;methodCall&amp;gt;&lt;br /&gt;
 &amp;lt;methodName&amp;gt;get_time&amp;lt;/methodName&amp;gt;&lt;br /&gt;
 &amp;lt;params/&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Thus, the server is responding to the &amp;lt;tt&amp;gt;get_time( )&amp;lt;/tt&amp;gt; method, and it expects no parameters.&lt;br /&gt;
&lt;br /&gt;
We also configure the response options to output the results in XML and interpret the request as XML-RPC. These two variables are then passed to &amp;lt;tt&amp;gt;xmlrpc_server_call_method( )&amp;lt;/tt&amp;gt; along with the XML-RPC server, &amp;lt;tt&amp;gt;$server&amp;lt;/tt&amp;gt;. The third parameter to this function is for any user data you wish to provide; in this case, there is none, so we pass &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;xmlrpc_server_call_method( )&amp;lt;/tt&amp;gt; function decodes the variables, calls the correct function to handle the method, and encodes the response into XML-RPC. To reply to the client, all you need to do is print out what &amp;lt;tt&amp;gt;xmlrpc_server_call_method( )&amp;lt;/tt&amp;gt; returns.&lt;br /&gt;
&lt;br /&gt;
Finally, clean up with a call to &amp;lt;tt&amp;gt;xmlrpc_server_destroy( )&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 xmlrpc_server_destroy($server);&lt;br /&gt;
&lt;br /&gt;
Using the XML-RPC client code from [[PHP Cookbook/XML#Sending XML-RPC Requests|Recipe 12.7]], you can make a request and find the time, as follows:&lt;br /&gt;
&lt;br /&gt;
 require 'utils.php';&lt;br /&gt;
 &lt;br /&gt;
 $output = array('output_type' =&amp;gt; 'xml', 'version' =&amp;gt; 'xmlrpc');&lt;br /&gt;
 $result = xu_rpc_http_concise(array(&lt;br /&gt;
                              'method'  =&amp;gt; 'get_time',&lt;br /&gt;
                              'host'    =&amp;gt; 'clock.example.com',&lt;br /&gt;
                              'port'    =&amp;gt; 80,&lt;br /&gt;
                              'uri'     =&amp;gt; '/time-xmlrpc.php',&lt;br /&gt;
                              'output' =&amp;gt; $output));&lt;br /&gt;
   &lt;br /&gt;
 print &amp;quot;The local time is $result.\n&amp;quot;;&lt;br /&gt;
 '''The local time is 20020821T162615'''.&lt;br /&gt;
&lt;br /&gt;
It is legal to associate multiple methods with a single XML-RPC server. You can also associate multiple methods with the same PHP function. For example, we can create a server that replies to two methods: &amp;lt;tt&amp;gt;get_gmtime( )&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;get_time( )&amp;lt;/tt&amp;gt;. The first method, &amp;lt;tt&amp;gt;get_gmtime( )&amp;lt;/tt&amp;gt;, is similar to &amp;lt;tt&amp;gt;get_time( )&amp;lt;/tt&amp;gt;, but it replies with the current time in GMT. To handle this, you can extend &amp;lt;tt&amp;gt;get_time( )&amp;lt;/tt&amp;gt; to take an optional parameter, which is the name of a time zone to use when computing the current time.&lt;br /&gt;
&lt;br /&gt;
Here's how to change the &amp;lt;tt&amp;gt;return_time( )&amp;lt;/tt&amp;gt; function to handle both methods:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;function return_time($method, $args) {&lt;br /&gt;
    if ('get_gmtime' == $method) {&lt;br /&gt;
        $tz = 'GMT';&lt;br /&gt;
    } elseif (!empty($args[0])) {&lt;br /&gt;
        $tz = $args[0];&lt;br /&gt;
    } else {&lt;br /&gt;
        // use local time zone&lt;br /&gt;
        $tz = '';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($tz) { putenv(&amp;quot;TZ=$tz&amp;quot;); }&lt;br /&gt;
    $date = date('Ymd\THis');&lt;br /&gt;
    if ($tz) { putenv('TZ=EST5EDT'); } // change EST5EDT to your server's zone&lt;br /&gt;
&lt;br /&gt;
    return $date;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function uses both the &amp;lt;tt&amp;gt;$method&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$args&amp;lt;/tt&amp;gt; parameters. At the top of the function, we check if the request is for &amp;lt;tt&amp;gt;get_gmtime&amp;lt;/tt&amp;gt;. If so, the time zone is set to GMT. If it isn't, see if an alternate time zone is specified as an argument by checking &amp;lt;tt&amp;gt;$args[0]&amp;lt;/tt&amp;gt;. If neither check is &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;, we keep the current time zone.&lt;br /&gt;
&lt;br /&gt;
To configure the server to handle the new method, add only one new line:&lt;br /&gt;
&lt;br /&gt;
 xmlrpc_server_register_method($server, 'return_time', 'get_gmtime');&lt;br /&gt;
&lt;br /&gt;
This maps &amp;lt;tt&amp;gt;get_gmtime( )&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;return_time( )&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here's an example of a client in action. The first request is for &amp;lt;tt&amp;gt;get_time( )&amp;lt;/tt&amp;gt; with no parameters; the second calls &amp;lt;tt&amp;gt;get_time( )&amp;lt;/tt&amp;gt; with a time zone of &amp;lt;tt&amp;gt;PST8PDT&amp;lt;/tt&amp;gt;, which is three hours behind the server; the last request is for the new &amp;lt;tt&amp;gt;get_gmtime( )&amp;lt;/tt&amp;gt; method, which is four hours ahead of the server's time zone.&lt;br /&gt;
&lt;br /&gt;
 require 'utils.php';&lt;br /&gt;
 &lt;br /&gt;
 $output = array('output_type' =&amp;gt; 'xml', 'version' =&amp;gt; 'xmlrpc');&lt;br /&gt;
 &lt;br /&gt;
 // get_time( )&lt;br /&gt;
 $result = xu_rpc_http_concise(array(&lt;br /&gt;
                              'method'  =&amp;gt; 'get_time',&lt;br /&gt;
                              'host'    =&amp;gt; 'clock.example.com',&lt;br /&gt;
                              'port'    =&amp;gt; 80,&lt;br /&gt;
                              'uri'     =&amp;gt; '/time.php',&lt;br /&gt;
                              'output' =&amp;gt; $output));&lt;br /&gt;
   &lt;br /&gt;
 print &amp;quot;The local time is $result.\n&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 // get_time('PST8PDT')&lt;br /&gt;
 $result = xu_rpc_http_concise(array(&lt;br /&gt;
                              'method'  =&amp;gt; 'get_time',&lt;br /&gt;
                              'args'    =&amp;gt; array('PST8PDT'),&lt;br /&gt;
                              'host'    =&amp;gt; 'clock.example.com',&lt;br /&gt;
                              'port'    =&amp;gt; 80,&lt;br /&gt;
                              'uri'     =&amp;gt; '/time.php',&lt;br /&gt;
                              'output' =&amp;gt; $output));&lt;br /&gt;
   &lt;br /&gt;
 print &amp;quot;The time in PST8PDT is $result.\n&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 // get_gmtime( )&lt;br /&gt;
 $result = xu_rpc_http_concise(array(&lt;br /&gt;
                              'method'  =&amp;gt; 'get_gmtime',&lt;br /&gt;
                              'host'    =&amp;gt; 'clock.example.com',&lt;br /&gt;
                              'port'    =&amp;gt; 80,&lt;br /&gt;
                              'uri'     =&amp;gt; '/time.php',&lt;br /&gt;
                              'output' =&amp;gt; $output));&lt;br /&gt;
   &lt;br /&gt;
 print &amp;quot;The time in GMT is $result.\n&amp;quot;;&lt;br /&gt;
 '''The local time is 20020821T162615.'''&lt;br /&gt;
                '''The time in PST8PDT is 20020821T132615.'''&lt;br /&gt;
                '''The time in GMT is 20020821T202615'''.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/XML#Sending XML-RPC Requests|Recipe 12.7]] for more information about XML-RPC clients; documentation on &amp;lt;tt&amp;gt;xmlrpc_server_create( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xmlrpc-server-create'', &amp;lt;tt&amp;gt;xmlrpc_server_register_method( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xmlrpc-server-register-method'', &amp;lt;tt&amp;gt;xmlrpc_server_call_method( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xmlrpc-server-call-method'', and &amp;lt;tt&amp;gt;xmlrpc_server_destroy( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/xmlrpc-server-destroy''; ''Programming Web Services with XML-RPC'' by Simon St. Laurent, Joe Johnston, and Edd Dumbill (O'Reilly); more on XML-RPC at ''http://www.xml-rpc.com''; the original current time XML-RPC server at ''http://www.xmlrpc.com/currentTime''.&lt;br /&gt;
&lt;br /&gt;
== Sending SOAP Requests ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to send a SOAP request. Creating a SOAP client allows you to gather information from SOAP servers, regardless of their operating system and middleware software.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use PEAR's SOAP classes. Here's some client code that uses the GoogleSearch SOAP service:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;require 'SOAP/Client.php';&lt;br /&gt;
&lt;br /&gt;
$query = 'php'; // your Google search terms&lt;br /&gt;
&lt;br /&gt;
$soap = new SOAP_Client('http://api.google.com/search/beta2');&lt;br /&gt;
&lt;br /&gt;
$params = array(&lt;br /&gt;
            new SOAP_Value('key',        'string',  'your google key'),&lt;br /&gt;
            new SOAP_Value('q',          'string',  $query),&lt;br /&gt;
            new SOAP_Value('start',      'int',     0),&lt;br /&gt;
            new SOAP_Value('maxResults', 'int',     10),&lt;br /&gt;
            new SOAP_Value('filter',     'boolean', false),&lt;br /&gt;
            new SOAP_Value('restrict',   'string',  ''),&lt;br /&gt;
            new SOAP_Value('safeSearch', 'boolean', false),&lt;br /&gt;
            new SOAP_Value('lr',         'string',  'lang_en'),&lt;br /&gt;
            new SOAP_Value('ie',         'string',  ''),&lt;br /&gt;
            new SOAP_Value('oe',         'string',  ''));&lt;br /&gt;
&lt;br /&gt;
$hits = $soap-&amp;gt;call('doGoogleSearch', $params, 'urn:GoogleSearch');&lt;br /&gt;
&lt;br /&gt;
foreach ($hits-&amp;gt;resultElements as $hit) {&lt;br /&gt;
    printf('&amp;lt;a href=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;', $hit-&amp;gt;URL, $hit-&amp;gt;title);&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
The Simple Object Access Protocol (SOAP), is, like XML-RPC, a method for exchanging information over HTTP. It uses XML as its message format, which makes it easy to create and parse. As a result, because it's platform- and language-independent, SOAP is available on many platforms and in many languages, including PHP. To make a SOAP request, you instantiate a new &amp;lt;tt&amp;gt;SOAP_Client&amp;lt;/tt&amp;gt; object and pass the constructor the location of the page to make the request:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$soap = new SOAP_Client('http://api.google.com/search/beta2');&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Currently, two different types of communications methods are supported: HTTP and SMTP. Secure HTTP is also allowed, if SSL is built into your version of PHP. To choose one of these methods, begin your URL with &amp;lt;tt&amp;gt;http&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;https&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;mailto&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
After creating a &amp;lt;tt&amp;gt;SOAP_Client&amp;lt;/tt&amp;gt; object, you use its &amp;lt;tt&amp;gt;call( )&amp;lt;/tt&amp;gt; method to call a remote function:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$query = 'php';&lt;br /&gt;
&lt;br /&gt;
$params = array(&lt;br /&gt;
            new SOAP_Value('key',        'string',  'your google key'),&lt;br /&gt;
            new SOAP_Value('q',          'string',  $query),&lt;br /&gt;
            new SOAP_Value('start',      'int',     0),&lt;br /&gt;
            new SOAP_Value('maxResults', 'int',     10),&lt;br /&gt;
            new SOAP_Value('filter',     'boolean', false),&lt;br /&gt;
            new SOAP_Value('restrict',   'string',  ''),&lt;br /&gt;
            new SOAP_Value('safeSearch', 'boolean', false),&lt;br /&gt;
            new SOAP_Value('lr',         'string',  'lang_en'),&lt;br /&gt;
            new SOAP_Value('ie',         'string',  ''),&lt;br /&gt;
            new SOAP_Value('oe',         'string',  ''));&lt;br /&gt;
&lt;br /&gt;
$hits = $soap-&amp;gt;call('doGoogleSearch', $params, 'urn:GoogleSearch');&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;$params&amp;lt;/tt&amp;gt; array holds a collection of &amp;lt;tt&amp;gt;SOAP_Value&amp;lt;/tt&amp;gt; objects. A &amp;lt;tt&amp;gt;SOAP_Value&amp;lt;/tt&amp;gt; object is instantiated with three arguments: the name, type, and value of the parameter you're passing to the SOAP server. These vary from message to message, depending upon the SOAP functions available on the server.&lt;br /&gt;
&lt;br /&gt;
The real action happens with the &amp;lt;tt&amp;gt;SOAP_Client::call( )&amp;lt;/tt&amp;gt; method, which takes a few arguments. The first is the method you want the server to execute; here, it's &amp;lt;tt&amp;gt;doGoogleSearch&amp;lt;/tt&amp;gt;. The second argument is an array of parameters that gets passed to the function on the SOAP server. The third argument, &amp;lt;tt&amp;gt;urn:GoogleSearch&amp;lt;/tt&amp;gt;, is the SOAP namespace; it allows the server to know that &amp;lt;tt&amp;gt;doGoogleSearch&amp;lt;/tt&amp;gt; belongs in the GoogleSearch namespace. With namespaces, a more generally named &amp;lt;tt&amp;gt;search&amp;lt;/tt&amp;gt; method doesn't cause a conflict with another more specific &amp;lt;tt&amp;gt;search&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
There's a fourth parameter that's unused here: &amp;lt;tt&amp;gt;soapAction&amp;lt;/tt&amp;gt;. If you want to provide the SOAP server with a URI indicating the intent of the request, you can add one here. Unfortunately, the definition of the word &amp;quot;intent&amp;quot; varies from implementation to implementation. The current consensus is that &amp;lt;tt&amp;gt;soapAction&amp;lt;/tt&amp;gt; shouldn't be used until its meaning is further clarified. The PEAR SOAP server doesn't use this field, but other vendors may assign their own meanings.&lt;br /&gt;
&lt;br /&gt;
Upon successful execution, the function returns an object containing the server's response. If an error occurs, the function returns a &amp;lt;tt&amp;gt;PEAR_Error&amp;lt;/tt&amp;gt; object. Google returns all sorts of information, but here we just iterate through the &amp;lt;tt&amp;gt;$resultElements&amp;lt;/tt&amp;gt; array and pull out the URL and title of each hit for display:&lt;br /&gt;
&lt;br /&gt;
 foreach ($hits-&amp;gt;resultElements as $hit) {&lt;br /&gt;
     printf('&amp;lt;a href=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/a&amp;gt;&amp;amp;lt;br /&amp;gt;', $hit-&amp;gt;URL, $hit-&amp;gt;title);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This results in:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;a href=&amp;quot;http://www.php.net/&amp;quot;&amp;gt;&amp;lt;b&amp;gt;PHP&amp;lt;/b&amp;gt;: Hypertext Preprocessor&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.php.net/downloads.php&amp;quot;&amp;gt;&amp;lt;b&amp;gt;PHP&amp;lt;/b&amp;gt;: Downloads&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://phpnuke.org/&amp;quot;&amp;gt;&amp;lt;b&amp;gt;PHP&amp;lt;/b&amp;gt;-Nuke&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.phpbuilder.com/&amp;quot;&amp;gt;PHPBuilder.com&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://php.resourceindex.com/&amp;quot;&amp;gt;The &amp;lt;b&amp;gt;PHP&amp;lt;/b&amp;gt; Resource Index&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.php.com/&amp;quot;&amp;gt;&amp;lt;b&amp;gt;PHP&amp;lt;/b&amp;gt;.com: Home&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.php.org/&amp;quot;&amp;gt;&amp;lt;b&amp;gt;PHP&amp;lt;/b&amp;gt;.org&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://php.weblogs.com/&amp;quot;&amp;gt;&amp;lt;b&amp;gt;PHP&amp;lt;/b&amp;gt; Everywhere:&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.php3.org/&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://gtk.php.net/&amp;quot;&amp;gt;&amp;lt;b&amp;gt;PHP&amp;lt;/b&amp;gt;-GTK&amp;lt;/a&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use Web Services Definition Language (WSDL), to implement the request. With WSDL, you don't need to explicitly enumerate the parameter keys or the SOAP namespace:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;require 'SOAP/Client.php';&lt;br /&gt;
&lt;br /&gt;
$wsdl_url = 'http://api.google.com/GoogleSearch.wsdl';&lt;br /&gt;
$WSDL = new SOAP_WSDL($wsdl_url);&lt;br /&gt;
$soap = $WSDL-&amp;gt;getProxy( );&lt;br /&gt;
&lt;br /&gt;
$hits = $soap-&amp;gt;doGoogleSearch('your google key',$query,0,10,&lt;br /&gt;
                               true,'',false,'lang_en','','');&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code is equivalent to the longer previous example. The &amp;lt;tt&amp;gt;SOAP_WSDL&amp;lt;/tt&amp;gt; object takes a URL for the GoogleSearch WSDL file and automatically loads the specification from that URL. Instead of making &amp;lt;tt&amp;gt;$soap&amp;lt;/tt&amp;gt; a &amp;lt;tt&amp;gt;SOAP_Client&amp;lt;/tt&amp;gt;, call &amp;lt;tt&amp;gt;SOAP_WSDL::getProxy( )&amp;lt;/tt&amp;gt; to create a GoogleSearch object.&lt;br /&gt;
&lt;br /&gt;
This new object has methods with the same name as the GoogleSearch SOAP methods. So, instead of passing &amp;lt;tt&amp;gt;doGoogleSearch&amp;lt;/tt&amp;gt; as the first parameter to &amp;lt;tt&amp;gt;SOAP_Client::call( )&amp;lt;/tt&amp;gt;, you call &amp;lt;tt&amp;gt;$soap-&amp;gt;doGoogleSearch( )&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;$params&amp;lt;/tt&amp;gt; array becomes the arguments for the method, without any array encapsulation or &amp;lt;tt&amp;gt;SOAP_Value&amp;lt;/tt&amp;gt; instantiations necessary. Also, because it's set in the WSDL file, the namespace doesn't need to be specified.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/XML#Receiving SOAP Requests|Recipe 12.10]] for more on SOAP servers; [[PHP Cookbook/Client-Side PHP#Program: Displaying Weather Conditions|Recipe 20.11]] for an example of a SOAP client in a PHP-GTK application; PEAR's SOAP classes at ''http://pear.php.net/package-info.php?package=SOAP''; ''Programming Web Services with SOAP'', by Doug Tidwell, James Snell, and Pavel Kulchenko (O'Reilly); information on the Google SOAP service at ''http://www.google.com/apis/''.&lt;br /&gt;
&lt;br /&gt;
== Receiving SOAP Requests ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to create an SOAP server and respond to SOAP requests. If your server responds to SOAP requests, anyone on the Internet that has a SOAP client can make requests of your server.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use PEAR's &amp;lt;tt&amp;gt;SOAP_Server&amp;lt;/tt&amp;gt; class. Here's a server that returns the current date and time:&lt;br /&gt;
&lt;br /&gt;
 require 'SOAP/Server.php';&lt;br /&gt;
 &lt;br /&gt;
 class pc_SOAP_return_time {&lt;br /&gt;
     var $method_namespace = 'urn:pc_SOAP_return_time';&lt;br /&gt;
 &lt;br /&gt;
     function return_time( ) {&lt;br /&gt;
         return date('Ymd\THis');&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $rt = new pc_SOAP_return_time( );&lt;br /&gt;
 &lt;br /&gt;
 $server = new SOAP_Server;&lt;br /&gt;
 $server-&amp;gt;addObjectMap($rt);&lt;br /&gt;
 $server-&amp;gt;service($HTTP_RAW_POST_DATA);&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
There are three steps to creating a SOAP server with PEAR's &amp;lt;tt&amp;gt;SOAP_Server&amp;lt;/tt&amp;gt; class:&lt;br /&gt;
&lt;br /&gt;
# Create a class to process SOAP methods and instantiate it&lt;br /&gt;
# Create an instance of a SOAP server and associate the processing object with the server&lt;br /&gt;
# Instruct the SOAP server to process the request and reply to the SOAP client&lt;br /&gt;
&lt;br /&gt;
The PEAR &amp;lt;tt&amp;gt;SOAP_Server&amp;lt;/tt&amp;gt; class uses objects to handle SOAP requests. A request-handling class needs a &amp;lt;tt&amp;gt;$method_namespace&amp;lt;/tt&amp;gt; property that specifies the SOAP namespace for the class. In this case, it's &amp;lt;tt&amp;gt;urn:pc_SOAP_return_time&amp;lt;/tt&amp;gt;. Object methods then map to SOAP procedure names within the namespace. The actual PHP class name isn't exposed via SOAP, so the fact that both the name of the class and its &amp;lt;tt&amp;gt;$method_namespace&amp;lt;/tt&amp;gt; are identical is a matter of convenience, not of necessity:&lt;br /&gt;
&lt;br /&gt;
 class pc_SOAP_return_time {&lt;br /&gt;
     var $method_namespace = 'urn:pc_SOAP_return_time';&lt;br /&gt;
 &lt;br /&gt;
     function return_time( ) {&lt;br /&gt;
         return date('Ymd\THis');&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $rt = new pc_SOAP_return_time( );&lt;br /&gt;
&lt;br /&gt;
Once the class is defined, you create an instance of the class to link methods with the SOAP server object. Before mapping the procedures to the class methods, however, you first must instantiate a &amp;lt;tt&amp;gt;SOAP_Server&amp;lt;/tt&amp;gt; object:&lt;br /&gt;
&lt;br /&gt;
 $server = new SOAP_Server;&lt;br /&gt;
 $server-&amp;gt;addObjectMap($rt);&lt;br /&gt;
 $server-&amp;gt;service($GLOBALS['HTTP_RAW_POST_DATA']);&lt;br /&gt;
&lt;br /&gt;
Once that's done, call &amp;lt;tt&amp;gt;SOAP_Server::addObjectMap( )&amp;lt;/tt&amp;gt; with the object to tell the SOAP server about the methods the object provides. Now the server is ready to reply to all SOAP requests within the namespace for which you've defined methods.&lt;br /&gt;
&lt;br /&gt;
To tell the server to respond to the request, call &amp;lt;tt&amp;gt;SOAP_Server::service( )&amp;lt;/tt&amp;gt; and pass the SOAP envelope. Because the envelope arrives via POST, you pass &amp;lt;tt&amp;gt;$GLOBALS['HTTP_RAW_POST_DATA']&amp;lt;/tt&amp;gt;. This provides the server with the complete request, because the class takes care of the necessary parsing.&lt;br /&gt;
&lt;br /&gt;
To call this procedure using a PEAR SOAP client, use this code:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;require 'SOAP/Client.php';&lt;br /&gt;
$soapclient = new SOAP_Client('http://clock.example.com/time-soap.php');&lt;br /&gt;
$result = $soapclient-&amp;gt;call('return_time', array( ),&lt;br /&gt;
                             array('namespace' =&amp;gt; 'urn:pc_SOAP_return_time'));&lt;br /&gt;
print &amp;quot;The local time is $result.\n&amp;quot;;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This prints:&lt;br /&gt;
&lt;br /&gt;
 The local time is 20020821T132615.&lt;br /&gt;
&lt;br /&gt;
To extend the method to read in parameters, you need to alter the method prototype to include parameter names and then modify the client request to include data for the additional arguments. This example modifies the SOAP procedure to accept an optional time zone argument:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;class pc_SOAP_return_time {&lt;br /&gt;
    var $method_namespace = 'urn:pc_SOAP_return_time';&lt;br /&gt;
&lt;br /&gt;
    function return_time($tz='') {&lt;br /&gt;
        if ($tz) { putenv(&amp;quot;TZ=$tz&amp;quot;); }&lt;br /&gt;
        $date = date('Ymd\THis');&lt;br /&gt;
        if ($tz) { putenv('TZ=EST5EDT'); } // change EST5EDT to your server's zone &lt;br /&gt;
        return $date&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second parameter in the client's call now takes a &amp;lt;tt&amp;gt;tz&amp;lt;/tt&amp;gt; option:&lt;br /&gt;
&lt;br /&gt;
 $result = $soapclient-&amp;gt;call('return_time', array('tz' =&amp;gt; 'PST8PDT'),&lt;br /&gt;
                              array('namespace' =&amp;gt; 'urn:pc_SOAP_return_time'));&lt;br /&gt;
&lt;br /&gt;
With the new settings, the server returns a time three hours behind the previous one:&lt;br /&gt;
&lt;br /&gt;
 20020821T202615&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/XML#Sending SOAP Requests|Recipe 12.9]] for more on SOAP clients; PEAR's SOAP classes at ''http://pear.php.net/package-info.php?package=SOAP''; ''Programming Web Services with SOAP'' (O'Reilly); the original SOAP current time application at ''http://www.soapware.org/currentTime''.&lt;br /&gt;
&lt;br /&gt;
== Exchanging Data with WDDX ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to serialize data in WDDX format for transmission or unserialize WDDX data you've received. This allows you to communicate with anyone who speaks WDDX.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use PHP's WDDX extension. Serialize multiple variables using &amp;lt;tt&amp;gt;wddx_serialize_vars( )&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 $a = 'string data';&lt;br /&gt;
 $b = 123;&lt;br /&gt;
 $c = 'rye';&lt;br /&gt;
 $d = 'pastrami';&lt;br /&gt;
 $array = array('c', 'd');&lt;br /&gt;
 &lt;br /&gt;
 $wddx = wddx_serialize_vars('a', 'b', $array);&lt;br /&gt;
&lt;br /&gt;
You can also start the WDDX packet with &amp;lt;tt&amp;gt;wddx_packet_start( )&amp;lt;/tt&amp;gt; and add data as it arrives with &amp;lt;tt&amp;gt;wddx_add_vars( )&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 $wddx = wddx_packet_start('Some of my favorite things');&lt;br /&gt;
 &lt;br /&gt;
 // loop through data&lt;br /&gt;
 while ($array = mysql_fetch_array($r)) {&lt;br /&gt;
     $thing = $array['thing'];&lt;br /&gt;
     wddx_add_vars($wddx, 'thing');&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $wddx = wddx_packet_end($wddx);&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;wddx_deserialize( )&amp;lt;/tt&amp;gt; to deserialize data:&lt;br /&gt;
&lt;br /&gt;
 // $wddx holds a WDDX packet&lt;br /&gt;
 $vars = wddx_deserialize($wddx);&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
WDDX stands for Web Distributed Data eXchange and was one of the first XML formats to share information in a language-neutral fashion. Invented by the company behind ColdFusion, WDDX gained a lot of popularity in 1999, but doesn't have much momentum at the present.&lt;br /&gt;
&lt;br /&gt;
Instead, many people have begun to use SOAP as a replacement for WDDX. But WDDX does have the advantage of simplicity, so if the information you're exchanging is basic, WDDX may be a good choice. Also, due to its origins, it's very easy to read and write WDDX packets in ColdFusion, so if you need to communicate with a ColdFusion application, WDDX is helpful.&lt;br /&gt;
&lt;br /&gt;
WDDX requires the ''expat'' library, available with Apache 1.3.7 and higher or from ''http://www.jclark.com/xml/expat.html''. Configure PHP with &amp;lt;tt&amp;gt;--with-xml&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--enable-wddx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The example in the Solution produces the following XML (formatted to be easier to read):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;wddxPacket version='1.0'&amp;gt;&lt;br /&gt;
 &amp;lt;header/&amp;gt;&lt;br /&gt;
 &amp;lt;data&amp;gt;&lt;br /&gt;
     &amp;lt;struct&amp;gt;&lt;br /&gt;
         &amp;amp;lt;var name='a'&amp;gt;&amp;lt;string&amp;gt;string data&amp;lt;/string&amp;gt;&amp;amp;lt;/var&amp;gt;&lt;br /&gt;
         &amp;amp;lt;var name='b'&amp;gt;&amp;lt;number&amp;gt;123&amp;lt;/number&amp;gt;&amp;amp;lt;/var&amp;gt;&lt;br /&gt;
         &amp;amp;lt;var name='c'&amp;gt;&amp;lt;string&amp;gt;rye&amp;lt;/string&amp;gt;&amp;amp;lt;/var&amp;gt;&lt;br /&gt;
         &amp;amp;lt;var name='d'&amp;gt;&amp;lt;string&amp;gt;pastrami&amp;lt;/string&amp;gt;&amp;amp;lt;/var&amp;gt;&lt;br /&gt;
     &amp;lt;/struct&amp;gt;&lt;br /&gt;
 &amp;lt;/data&amp;gt;&lt;br /&gt;
 &amp;lt;/wddxPacket&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Variables are wrapped inside &amp;lt;tt&amp;gt;&amp;amp;lt;var&amp;gt;&amp;lt;/tt&amp;gt; tags with the variable name assigned as the value for the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; attribute. Inside there is another set of tags that indicate the variable type: &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;number&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;dateTime&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;boolean&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;array&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;binary&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;recordSet&amp;lt;/tt&amp;gt;. Finally, you have the data itself.&lt;br /&gt;
&lt;br /&gt;
You can also serialize one variable at a time using &amp;lt;tt&amp;gt;wddx_serialize_value&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
 // one variable&lt;br /&gt;
 $s = wddx_serialize_value('Serialized', 'An optional comment');&lt;br /&gt;
&lt;br /&gt;
This results in the following XML:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;wddxPacket version='1.0'&amp;gt;&lt;br /&gt;
 &amp;lt;header&amp;gt;&lt;br /&gt;
     &amp;lt;comment&amp;gt;An optional comment&amp;lt;/comment&amp;gt;&lt;br /&gt;
 &amp;lt;/header&amp;gt;&lt;br /&gt;
 &amp;lt;data&amp;gt;&lt;br /&gt;
     &amp;lt;string&amp;gt;Serialized&amp;lt;/string&amp;gt;&lt;br /&gt;
 &amp;lt;/data&amp;gt;&lt;br /&gt;
 &amp;lt;/wddxPacket&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
Documentation on WDDX at ''http://www.php.net/wddx''; more information at ''http://www.openwddx.org''; [[PHP Cookbook/Client-Side PHP|Chapter 20]], &amp;quot;Sharing Data with WDDX,&amp;quot; from ''Programming ColdFusion'', by Rob Brooks-Bilson (O'Reilly).&lt;br /&gt;
&lt;br /&gt;
== Reading RSS Feeds ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to retrieve an RSS feed and look at the items. This allows you to incorporate newsfeeds from multiple web sites into your application.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use the PEAR XML_RSS class. Here's an example that reads the RSS feed for the ''php.announce'' mailing list:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;require 'XML/RSS.php';&lt;br /&gt;
&lt;br /&gt;
$feed = 'http://news.php.net/group.php?group=php.announce&amp;amp;format=rss';&lt;br /&gt;
&lt;br /&gt;
$rss =&amp;amp; new XML_RSS($feed);&lt;br /&gt;
$rss-&amp;gt;parse();&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;&amp;lt;ul&amp;gt;\n&amp;quot;;&lt;br /&gt;
foreach ($rss-&amp;gt;getItems() as $item) {&lt;br /&gt;
    print '&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;' . $item['link'] . '&amp;quot;&amp;gt;' . $item['title'] . &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
print &amp;quot;&amp;lt;/ul&amp;gt;\n&amp;quot;;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
RSS, which stands for RDF Site Summary, is an easy-to-use headline or article syndication format written in XML.&amp;lt;ref&amp;gt;RDF stands for Resource Definition Framework. RSS also stands for Rich Site Summary.&amp;lt;/ref&amp;gt; Many news web sites, such as Slashdot and O'Reilly's Meerkat, provide RSS feeds that update whenever new stories are published. Weblogs have also embraced RSS and having an RSS feed for your blog is a standard feature. The PHP web site also publishes RSS feeds for most PHP mailing lists.&lt;br /&gt;
&lt;br /&gt;
Retrieving and parsing a RSS feed is simple:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$feed = 'http://news.php.net/group.php?group=php.announce&amp;amp;format=rss';&lt;br /&gt;
&lt;br /&gt;
$rss =&amp;amp; new XML_RSS($feed);&lt;br /&gt;
$rss-&amp;gt;parse();&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example makes &amp;lt;tt&amp;gt;$rss&amp;lt;/tt&amp;gt; a new &amp;lt;tt&amp;gt;XML_RSS&amp;lt;/tt&amp;gt; object and sets the feed to the RSS feed for the ''php.announce'' mailing list. The feed is then parsed by &amp;lt;tt&amp;gt;XML_RSS::parse( )&amp;lt;/tt&amp;gt; and stored internally within &amp;lt;tt&amp;gt;$rss&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
RSS items are then retrieved as an associative array using &amp;lt;tt&amp;gt;XML_RSS:getItems( )&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
 print &amp;quot;&amp;amp;lt;ul&amp;gt;\n&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 foreach ($rss-&amp;gt;getItems() as $item) {&lt;br /&gt;
     print '&amp;amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;' . $item['link'] . '&amp;quot;&amp;gt;' . $item['title'] . &amp;quot;&amp;lt;/a&amp;gt;&amp;amp;lt;/li&amp;gt;\n&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 print &amp;quot;&amp;amp;lt;/ul&amp;gt;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt; loop creates an unordered list of items with the item title linking back to the URL associated with the complete article, as shown in [[PHP Cookbook/XML#phpckbk-CHP-12-FIG-1|Figure 12-1]]. Besides the required &amp;lt;tt&amp;gt;title&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; fields, an item can have an optional &amp;lt;tt&amp;gt;description&amp;lt;/tt&amp;gt; field that contains a brief write-up about the item.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;phpckbk-CHP-12-FIG-1&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 12-1. php.announce RSS feed'''&lt;br /&gt;
&lt;br /&gt;
[[Image:PHP Cookbook_I_12_tt752.png|php.announce RSS feed]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each channel also has an entry with information about the feed, as shown in [[PHP Cookbook/XML#phpckbk-CHP-12-FIG-2|Figure 12-2]]. To retrieve that data, call &amp;lt;tt&amp;gt;XML_RSS::getChannelInfo( )&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$feed = 'http://news.php.net/group.php?group=php.announce&amp;amp;format=rss';&lt;br /&gt;
$rss =&amp;amp; new XML_RSS($feed);&lt;br /&gt;
&lt;br /&gt;
$rss-&amp;gt;parse();&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;&amp;lt;ul&amp;gt;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
foreach ($rss-&amp;gt;getChannelInfo() as $key =&amp;gt; $value) {&lt;br /&gt;
    print &amp;quot;&amp;lt;li&amp;gt;$key: $value&amp;lt;/li&amp;gt;\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;&amp;lt;/ul&amp;gt;\n&amp;quot;;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;phpckbk-CHP-12-FIG-2&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 12-2. php.announce RSS channel information'''&lt;br /&gt;
&lt;br /&gt;
[[Image:PHP Cookbook_I_12_tt754.png|php.announce RSS channel information]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/XML#Parsing XML with SAX|Recipe 12.5]] for how to process an RSS feed and transform it to HTML; PEAR's &amp;lt;tt&amp;gt;XML_RSS&amp;lt;/tt&amp;gt; class at ''http://pear.php.net/package-info.php?package=XML_RSS''; more information on RSS at ''http://groups.yahoo.com/group/rss-dev/files/specification.html''; O'Reilly Network's Meerkat at ''http://www.oreillynet.com/meerkat/'' .&lt;br /&gt;
== Notes ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Docbook2Wiki</name></author>	</entry>

	</feed>