advanced xml and web services september 12, 2006 robert richards [email protected]

150
Advanced XML and Advanced XML and Web Services Web Services September 12, 2006 September 12, 2006 Robert Richards Robert Richards [email protected] [email protected] http://www.cdatazone.org/files/ http://www.cdatazone.org/files/ workshop.zip workshop.zip

Upload: donte-talford

Post on 31-Mar-2015

217 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Advanced XML Advanced XML and Web Servicesand Web Services

September 12, 2006September 12, 2006

Robert RichardsRobert [email protected]@php.net

http://www.cdatazone.org/files/http://www.cdatazone.org/files/workshop.zipworkshop.zip

Page 2: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

AgendaAgenda Introduction to Terms and ConceptsIntroduction to Terms and Concepts LibxmlLibxml DOMDOM SimpleXMLSimpleXML SAX (ext/xml)SAX (ext/xml) XMLReaderXMLReader XSLXSL XMLWriterXMLWriter SOAP (ext/soap)SOAP (ext/soap)

Page 3: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XML NamespacesXML Namespaces An XML Namespace is a collection of names An XML Namespace is a collection of names

identified by a URI.identified by a URI. They are applicable to elements and attributes.They are applicable to elements and attributes. Namespaces may or may not be associated Namespaces may or may not be associated

with a prefix.with a prefix. xmlns:rob="urn:rob"xmlns:rob="urn:rob" xmlns=xmlns=http://www.example.com/robhttp://www.example.com/rob

Attributes never reside within a default Attributes never reside within a default namespace.namespace.

It is illegal to have two attributes with the It is illegal to have two attributes with the same localname and same namespace on the same localname and same namespace on the same element.same element.

Page 4: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XML Namespace XML Namespace ExampleExample

<order num="1001"> <shipping> <name type="care_of">John Smith</name> <address>123 Here</address> </shipping> <billing> <name type="legal">Jane Doe</name> <address>456 Somewhere else</address> </billing></order>

Page 5: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XML Namespace XML Namespace ExampleExample

<order num="1001" xmlns="urn:order" xmlns:ship="urn:shipping" xmlns:bill="urn:billing"> <ship:shipping> <ship:name type="care_of">John Smith</ship:name> <ship:address>123 Here</ship:address> </ship:shipping> <bill:billing> <bill:name type="legal">Jane Doe</bill:name> <bill:address>456 Somewhere else</bill:address> </bill:billing></order>

Page 6: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Illegal Namespace UsageIllegal Namespace Usage

<order num="1001" xmlns="urn:order"<order num="1001" xmlns="urn:order"

xmlns:order="urn:order"xmlns:order="urn:order"

xmlns:ship="urn:order"xmlns:ship="urn:order">>

<shipping ship:type="fed_ex" type="fed_ex"><shipping ship:type="fed_ex" type="fed_ex">

<name <name ship:type="care_of"ship:type="care_of"

order:type="legal"order:type="legal">John >John Smith</ship:name>Smith</ship:name>

</ship:shipping></ship:shipping>

</order></order>

Page 7: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Illegal Namespace UsageIllegal Namespace Usage

<order num="1001" xmlns="urn:order"<order num="1001" xmlns="urn:order"

xmlns:order="urn:order"xmlns:order="urn:order"

xmlns:ship="urn:order">xmlns:ship="urn:order">

<shipping <shipping ship:type="fed_ex" type="fed_ex"ship:type="fed_ex" type="fed_ex">>

<name ship:type="care_of" <name ship:type="care_of"

order:type="legal">John order:type="legal">John Smith</ship:name>Smith</ship:name>

</ship:shipping></ship:shipping>

</order></order>

<!-- attributes on shipping element are valid ! --><!-- attributes on shipping element are valid ! -->

Page 8: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Reserved Namespaces Reserved Namespaces and Prefixesand Prefixes

The prefix The prefix xmlxml is bound to is bound to http://www.w3.org/XML/1998/nameshttp://www.w3.org/XML/1998/namespacepace..

The prefix The prefix xmlnsxmlns is bound to is bound to http://www.w3.org/2000/xmlns/http://www.w3.org/2000/xmlns/..

Prefixes should also not begin with Prefixes should also not begin with the characters the characters xmlxml..

Page 9: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Schemas and ValidationSchemas and Validation

Validation insures an XML document Validation insures an XML document conforms to a set of defined rules.conforms to a set of defined rules.

Multiple mechanisms exist to write Multiple mechanisms exist to write document rule sets:document rule sets: Document Type Definition (DTD)Document Type Definition (DTD) XML SchemaXML Schema RelaxNGRelaxNG

Page 10: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Document Type Document Type Definition Definition (DTD)(DTD)validation/courses-dtd.xmlvalidation/courses-dtd.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE courses [ <!ELEMENT courses (course+)> <!ELEMENT course (title, description, credits, lastmodified)> <!ATTLIST course cid ID #REQUIRED> <!ELEMENT title (#PCDATA)> <!ELEMENT description (#PCDATA)> <!ELEMENT credits (#PCDATA)> <!ELEMENT lastmodified (#PCDATA)>]><courses> <course cid="c1"> <title>Basic Languages</title> <description>Introduction to Languages</description> <credits>1.5</credits> <lastmodified>2004-09-01T11:13:01</lastmodified> </course> <course cid="c2"> . . . </course></courses>

Page 11: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DTD and IDsDTD and IDsvalidation/course-id.xmlvalidation/course-id.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE courses [ <!ATTLIST course cid ID #REQUIRED>]><courses> <course cid="c1"> <title xml:id="t1">Basic Languages</title> <description>Introduction to Languages</description> </course> <course cid="c2"> <title xml:id="t3">French I</title> <description>Introduction to French</description> </course> <course cid="c3"> <title xml:id="t3">French II</title> <description>Intermediate French</description> </course></courses>

Page 12: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XML SchemaXML Schemavalidation/course.xsdvalidation/course.xsd

<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="courses"> <xsd:complexType> <xsd:sequence> <xsd:element name="course" minOccurs="1" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="title" type="xsd:string"/> <xsd:element name="description" type="xsd:string"/> <xsd:element name="credits" type="xsd:decimal"/> <xsd:element name="lastmodified" type="xsd:dateTime"/> </xsd:sequence> <xsd:attribute name="cid" type="xsd:ID"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element></xsd:schema>

Page 13: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

RelaxNGRelaxNGvalidation/course.rngvalidation/course.rng

<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">

<start> <element name="courses"> <zeroOrMore> <element name="course"> <attribute name="cid"><data type="ID"/></attribute> <element name="title"><text/></element> <element name="description"><text/></element> <element name="credits"><data type="decimal"/></element> <element name="lastmodified"><data type="dateTime"/></element> </element> </zeroOrMore> </element> </start>

</grammar>

Page 14: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XPathXPath

Language to locate and retrieve Language to locate and retrieve information from an XML documentinformation from an XML document

A foundation for XSLTA foundation for XSLT An XML document is a tree An XML document is a tree

containing nodescontaining nodes The XML document is the root nodeThe XML document is the root node Locations are addressable similar to Locations are addressable similar to

the syntax for a filesystemthe syntax for a filesystem

Page 15: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XPath Reference XPath Reference DocumentDocumentxpath/courses.xmlxpath/courses.xml

<courses xmlns:t="http://www.example.com/title"> <course xml:id="c1"> <t:title>Basic Languages</t:title> <description>Introduction to Languages</description> </course> <course xml:id="c2"> <t:title>French I</t:title> <description>Introduction to French</description> </course> <course xml:id="c3"> <t:title>French II</t:title> <description>Intermediate French</description> <pre-requisite cref="c2" /> <?phpx A PI Node ?> <defns xmlns="urn:default">content</defns> </course></courses>

Page 16: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XPath Location ExampleXPath Location Examplexpath/location.phpxpath/location.php

/courses/course/description//description/courses/*/description//description[ancestor::course]

Expression:

Resulting Nodset:<description>Introduction to Languages</description><description>Introduction to French</description><description>Intermediate French</description>

Page 17: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XPath Function ExampleXPath Function Examplexpath/function.phpxpath/function.php

string(/courses/course/pre-string(/courses/course/pre-requisite[@cref="c2"]/..)requisite[@cref="c2"]/..)

French IIFrench II

Intermediate FrenchIntermediate French

contentcontent

Page 18: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XPath and NamespacesXPath and Namespacesxpath/namespaces.phpxpath/namespaces.php

//titleEmpty NodeSet

//t:title<t:title>Basic Languages</t:title><t:title>French I</t:title><t:title>French II</t:title>

//defnsEmpty NodeSet

//*[local-name()="defns"]<defns xmlns="urn:default">content</defns>

Page 19: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

PHP and XMLPHP and XML

PHP 5 introduced numerous PHP 5 introduced numerous interfaces for working with XMLinterfaces for working with XML

The libxml2 library The libxml2 library (http://www.xmlsoft.org/) was (http://www.xmlsoft.org/) was chosen to provide XML supportchosen to provide XML support

The sister library libxslt provides The sister library libxslt provides XSLT supportXSLT support

I/O is handled via PHP streamsI/O is handled via PHP streams

Page 20: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XML Entensions for PHP XML Entensions for PHP 55

ext/libxmlext/libxml ext/xml (SAX push parser)ext/xml (SAX push parser) ext/domext/dom ext/simplexmlext/simplexml ext/xmlreader (pull parser)ext/xmlreader (pull parser) ext/xmlwriterext/xmlwriter ext/xslext/xsl ext/wddxext/wddx ext/soapext/soap

Page 21: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

LibxmlLibxml

Contains common functionality Contains common functionality shared across extensions.shared across extensions.

Defines constants to modify parse Defines constants to modify parse time behavior.time behavior.

Provides access to streams context.Provides access to streams context. Allows modification of error Allows modification of error

handling behavior for XML based handling behavior for XML based extensions.extensions.

Page 22: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Libxml: Parser OptionsLibxml: Parser OptionsLIBXML_NOENTLIBXML_NOENT Substitute entities with Substitute entities with

replacement contentreplacement contentLIBXML_DTDLOADLIBXML_DTDLOAD Load subsets but do not perform Load subsets but do not perform

validationvalidationLIBXML_DTDATTRLIBXML_DTDATTR Create defaulted attributes defined Create defaulted attributes defined

in DTDin DTDLIBXML_DTDVALIDLIBXML_DTDVALID Loads subsets and perform Loads subsets and perform

validationvalidationLIBXML_NOERRORLIBXML_NOERROR Suppress parsing errors from Suppress parsing errors from

libxml2libxml2LIBXML_NOWARNILIBXML_NOWARNINGNG

Suppress parser warnings from Suppress parser warnings from libxml2libxml2

LIBXML_NOBLANKLIBXML_NOBLANKSS

Remove insignificant whitespace Remove insignificant whitespace on parsingon parsing

LIBXML_XINCLUDELIBXML_XINCLUDE Perform XIncludes during parsingPerform XIncludes during parsingLIBXML_NOCDATALIBXML_NOCDATA Merge CDATA nodes in Text nodesMerge CDATA nodes in Text nodesLIBXML_NONETLIBXML_NONET Disable network access when Disable network access when

loadingloading

Page 23: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Libxml: Error HandlingLibxml: Error Handling

bool libxml_use_internal_errors ([bool bool libxml_use_internal_errors ([bool use_errors])use_errors])

void libxml_clear_errors ( void )void libxml_clear_errors ( void )

LibXMLError libxml_get_last_error ( void )LibXMLError libxml_get_last_error ( void )

array libxml_get_errors ( void )array libxml_get_errors ( void )

Page 24: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Libxml: LibXMLErrorLibxml: LibXMLError

Class: LibXMLErrorProperties (Read-Only):

(int) level(int) code(int) column(string) message(string) file(int) line

LibXMLError::code Values:LIBXML_ERR_NONELIBXML_ERR_WARNINGLIBXML_ERR_ERRORLIBXML_ERR_FATAL

Page 25: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

LibXMLError ExampleLibXMLError Examplelibxml/error.phplibxml/error.php

<?php/* Regular Error Handling */$dom = new DOMDocument();$dom->loadXML('<root>');

/* New Error Handling */libxml_use_internal_errors(TRUE);

if (! $dom->loadXML('root')) { $arrError = libxml_get_errors(); foreach ($arrError AS $xmlError) { var_dump($xmlError); }} else { print "Document Loaded";}?>

Page 26: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

LibXMLError ResultLibXMLError ResultPHP Warning: DOMDocument::loadXML(): Premature end of data in tag PHP Warning: DOMDocument::loadXML(): Premature end of data in tag

root line 1 in Entity, line: 1 in root line 1 in Entity, line: 1 in /home/rrichards/workshop/libxml/error.php on line 4/home/rrichards/workshop/libxml/error.php on line 4

Warning: DOMDocument::loadXML(): Premature end of data in tag root Warning: DOMDocument::loadXML(): Premature end of data in tag root line 1 in Entity, line: 1 in /home/rrichards/workshop/libxml/error.php on line 1 in Entity, line: 1 in /home/rrichards/workshop/libxml/error.php on line 4line 4

New Error Handling:New Error Handling:object(LibXMLError)#2 (6) {object(LibXMLError)#2 (6) { ["level"]=> int(3)["level"]=> int(3) ["code"]=> int(4)["code"]=> int(4) ["column"]=> int(1)["column"]=> int(1) ["message"]=> string(34) "Start tag expected, '<' not found"["message"]=> string(34) "Start tag expected, '<' not found" ["file"]=> string(0) ""["file"]=> string(0) "" ["line"]=> int(1)["line"]=> int(1)}}

Page 27: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOMDOM

Tree based parserTree based parser Allows for creation and editing of XML Allows for creation and editing of XML

documentsdocuments W3C Specification with DOM Level 2/3 W3C Specification with DOM Level 2/3

compliancycompliancy Provides XPath supportProvides XPath support Provides XInclude SupportProvides XInclude Support Ability to work with HTML documentsAbility to work with HTML documents Zero copy interoperability with SimpleXMLZero copy interoperability with SimpleXML Replacement for ext/domxml from PHP 4Replacement for ext/domxml from PHP 4

Page 28: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOMNode ClassesDOMNode Classes

DOMDocumentDOMDocument DOMElementDOMElement DOMAttrDOMAttr DOMCommentDOMComment DOMDocumentTypDOMDocumentTyp

ee DOMNotationDOMNotation DOMEntityDOMEntity

DOMEntityReferenceDOMEntityReference DOMProcessingInstruDOMProcessingInstru

ctionction DOMNameSpaceNodeDOMNameSpaceNode DOMDocumentFragmDOMDocumentFragm

entent DOMCharacterDataDOMCharacterData DOMTextDOMText DOMCdataSectionDOMCdataSection

Page 29: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Additional DOM ClassesAdditional DOM Classes

DOMExceptionDOMException DOMImplementationDOMImplementation DOMNodeListDOMNodeList DOMNamedNodeMapDOMNamedNodeMap DOMXPathDOMXPath

Page 30: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Sample DocumentDOM: Sample Document<courses><courses> <course cid="c1"><course cid="c1"> <title>Basic Languages</title><title>Basic Languages</title> <description>Introduction to <description>Introduction to

Languages</description>Languages</description> <credits>1.5</credits><credits>1.5</credits> <lastmodified>2004-09-01T11:13:01</lastmodified><lastmodified>2004-09-01T11:13:01</lastmodified> </course></course> <course cid="c2"><course cid="c2"> <title>French I</title><title>French I</title> <description>Introduction to French</description><description>Introduction to French</description> <credits>3.0</credits><credits>3.0</credits> <lastmodified>2005-06-01T14:21:37</lastmodified><lastmodified>2005-06-01T14:21:37</lastmodified> </course></course> <course cid="c3"><course cid="c3"> <title>French II</title><title>French II</title> <description>Intermediate French</description><description>Intermediate French</description> <credits>3.0</credits><credits>3.0</credits> <lastmodified>2005-03-12T15:45:44</lastmodified><lastmodified>2005-03-12T15:45:44</lastmodified> </course></course></courses></courses>

Page 31: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Document DOM: Document NavigationNavigationdom/navigate.phpdom/navigate.php/* Find first description element in subtrees *//* Find first description element in subtrees */

function locateDescription($nodeset) {function locateDescription($nodeset) { foreach ($nodeset AS $node) {foreach ($nodeset AS $node) { if ($node->nodeType == if ($node->nodeType == XML_ELEMENT_NODEXML_ELEMENT_NODE && $node->nodeName && $node->nodeName

== 'description') {== 'description') { $GLOBALS['arNodeSet'][] = $node;$GLOBALS['arNodeSet'][] = $node; return;return; }} if ($node->hasChildNodes()) { locateDescription($node-if ($node->hasChildNodes()) { locateDescription($node-

>childNodes); }>childNodes); } }}}}

$dom = new DOMDocument();$dom = new DOMDocument();$dom->load('course.xml');$dom->load('course.xml');$root = $dom->documentElement;$root = $dom->documentElement;

$arNodeSet = array();$arNodeSet = array();

if ($root->hasChildNodes()) { locateDescription($root->childNodes); }if ($root->hasChildNodes()) { locateDescription($root->childNodes); }

foreach ($arNodeSet AS $key=>$node) { print "#$key: ".$node-foreach ($arNodeSet AS $key=>$node) { print "#$key: ".$node->nodeValue."\n"; }>nodeValue."\n"; }

Page 32: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Document DOM: Document Navigation ResultsNavigation Results

#0: Introduction to Languages#0: Introduction to Languages

#1: Introduction to French#1: Introduction to French

#2: Intermediate French#2: Intermediate French

Page 33: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM:Document DOM:Document Navigation #2Navigation #2

dom/navigate-2.phpdom/navigate-2.php<?php$dom = new DOMDocument();$dom->load('course.xml');

$nodelist = $dom->getElementsByTagName('description');

foreach ($nodelist AS $key=>$node) { print "#$key: ".$node->nodeValue."\n";}?>

Results:

#0: Introduction to Languages#1: Introduction to French#2: Intermediate French

Page 34: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Navigation DOM: Navigation OptimizedOptimized

dom/navigate-optimized.phpdom/navigate-optimized.phpfunction locateDescription($node) {function locateDescription($node) { while($node) {while($node) { if ($node->nodeType if ($node->nodeType == XML_ELEMENT_NODE &&== XML_ELEMENT_NODE && $node->nodeName $node->nodeName ====

'description') {'description') { $GLOBALS['arNodeSet'][] = $node;$GLOBALS['arNodeSet'][] = $node; return;return; }} locateDescription($node->firstChild);locateDescription($node->firstChild); $node = $node->nextSibling;$node = $node->nextSibling; }}}}

$dom = new DOMDocument();$dom = new DOMDocument();$dom->load('course.xml');$dom->load('course.xml');$root = $dom->documentElement;$root = $dom->documentElement;$arNodeSet = array();$arNodeSet = array();

locateDescription($root->firstChild);locateDescription($root->firstChild);

foreach ($arNodeSet AS $key=>$node) {foreach ($arNodeSet AS $key=>$node) { print "#$key: ".$node->nodeValue."\n";print "#$key: ".$node->nodeValue."\n";}}

Page 35: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Creating a Simple DOM: Creating a Simple TreeTree

dom/create_simple_tree.phpdom/create_simple_tree.php$doc = new DOMDocument();$doc = new DOMDocument();

$root = $doc->createElement("tree");$root = $doc->createElement("tree");$doc->appendChild($root);$doc->appendChild($root);

$root->setAttribute("att1", "att1 value");$root->setAttribute("att1", "att1 value");

$attr2 = $doc->createAttribute("att2");$attr2 = $doc->createAttribute("att2");$attr2->appendChild($doc->createTextNode("att2 value"));$attr2->appendChild($doc->createTextNode("att2 value"));$root->setAttributeNode($attr2);$root->setAttributeNode($attr2);

$child = $root->appendChild($doc->createElement("child"));$child = $root->appendChild($doc->createElement("child"));

$comment = $doc->createComment("My first Document");$comment = $doc->createComment("My first Document");$doc->insertBefore($comment, $root);$doc->insertBefore($comment, $root);

$pi = $doc->createProcessingInstruction("php", 'echo "Hello $pi = $doc->createProcessingInstruction("php", 'echo "Hello World!"');World!"');

$root->appendChild($pi);$root->appendChild($pi);

$cdata = $doc->createCdataSection("special chars: & < > '");$cdata = $doc->createCdataSection("special chars: & < > '");$child->appendChild($cdata);$child->appendChild($cdata);

Page 36: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Simple Tree DOM: Simple Tree OutputOutput

<?xml version="1.0"?><!--My first Document--><tree att1="att1 value" att2="att2 value"> <child><![CDATA[special chars: & < > ']]></child><?php echo "Hello World!"?></tree>

Page 37: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Creating an Atom DOM: Creating an Atom FeedFeed

dom/atom_feed_creation.phpdom/atom_feed_creation.phpdefine('ATOMNS', 'http://www.w3.org/2005/Atom');define('ATOMNS', 'http://www.w3.org/2005/Atom');$feed_title = "Example Atom Feed";$feed_title = "Example Atom Feed";$alt_url = "http://www.example.org/";$alt_url = "http://www.example.org/";$feed = "http://www.example.org/atom/";$feed = "http://www.example.org/atom/";

$doc = new DOMDocument("1.0", "UTF-8");$doc = new DOMDocument("1.0", "UTF-8");

function create_append_Atom_elements($doc, $name, $value=NULL, function create_append_Atom_elements($doc, $name, $value=NULL, $parent=NULL) {$parent=NULL) {

if ($value)if ($value) $newelem = $doc->createElementNS(ATOMNS, $name, $value);$newelem = $doc->createElementNS(ATOMNS, $name, $value);elseelse $newelem = $doc->createElementNS(ATOMNS, $name);$newelem = $doc->createElementNS(ATOMNS, $name);

if ($parent) { return $parent->appendChild($newelem); }if ($parent) { return $parent->appendChild($newelem); }}}

$feed = create_append_Atom_elements($doc, 'feed', NULL, $doc);$feed = create_append_Atom_elements($doc, 'feed', NULL, $doc);create_append_Atom_elements($doc, 'title', $feed_title, $feed);create_append_Atom_elements($doc, 'title', $feed_title, $feed);create_append_Atom_elements($doc, 'subtitle', $feed_title, $feed);create_append_Atom_elements($doc, 'subtitle', $feed_title, $feed);create_append_Atom_elements($doc, 'id', $alt_url, $feed);create_append_Atom_elements($doc, 'id', $alt_url, $feed);create_append_Atom_elements($doc, 'updated', date('c'), $feed);create_append_Atom_elements($doc, 'updated', date('c'), $feed);

$doc->formatOutput = TRUE;$doc->formatOutput = TRUE;print $doc->saveXML();print $doc->saveXML();

Page 38: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: DOM: Creating an Atom Creating an Atom FeedFeed Result Result (initial structure)(initial structure)

<?xml version="1.0" encoding="UTF-8"?><?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"><feed xmlns="http://www.w3.org/2005/Atom"> <title>Example Atom Feed</title><title>Example Atom Feed</title> <subtitle>Example Atom Feed</subtitle><subtitle>Example Atom Feed</subtitle> <id>http://www.example.org/</id><id>http://www.example.org/</id>

<updated>2006-03-23T01:39:40-05:00</updated<updated>2006-03-23T01:39:40-05:00</updated>>

</feed></feed>

Page 39: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Creating an Atom DOM: Creating an Atom FeedFeed

dom/atom_feed_creation.phpdom/atom_feed_creation.php $entry = create_append_Atom_elements($doc, '$entry = create_append_Atom_elements($doc, 'entryentry', NULL, $feed);', NULL, $feed);

$title = create_append_Atom_elements($doc, 'title', $title = create_append_Atom_elements($doc, 'title', 'My first entry''My first entry', $entry);, $entry); $title->setAttribute('type', 'text');$title->setAttribute('type', 'text');

$link = create_append_Atom_elements($doc, 'link', NULL, $entry);$link = create_append_Atom_elements($doc, 'link', NULL, $entry); $link->setAttribute('type', 'text/html');$link->setAttribute('type', 'text/html'); $link->setAttribute('rel', 'alternate');$link->setAttribute('rel', 'alternate'); $link->setAttribute('href', 'http://www.example.org/entry-url');$link->setAttribute('href', 'http://www.example.org/entry-url'); $link->setAttribute('title', 'My first entry');$link->setAttribute('title', 'My first entry');

$author = create_append_Atom_elements($doc, 'author', NULL, $entry);$author = create_append_Atom_elements($doc, 'author', NULL, $entry); create_append_Atom_elements($doc, 'name', 'Rob', $author);create_append_Atom_elements($doc, 'name', 'Rob', $author);

create_append_Atom_elements($doc, 'id', 'http://www.example.org/entry-guid', create_append_Atom_elements($doc, 'id', 'http://www.example.org/entry-guid', $entry);$entry);

create_append_Atom_elements($doc, 'updated', date('c'), $entry);create_append_Atom_elements($doc, 'updated', date('c'), $entry); create_append_Atom_elements($doc, 'published', date('c'), $entry);create_append_Atom_elements($doc, 'published', date('c'), $entry);

$content = create_append_Atom_elements($doc, 'content', NULL, $entry);$content = create_append_Atom_elements($doc, 'content', NULL, $entry); $cdata = $doc->createCDATASection('This is my first Atom entry!<br />More $cdata = $doc->createCDATASection('This is my first Atom entry!<br />More

to follow');to follow'); $content->appendChild($cdata);$content->appendChild($cdata);

$doc->formatOutput = TRUE;$doc->formatOutput = TRUE; print $doc->saveXML();print $doc->saveXML();

Page 40: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: DOM: Creating an Atom Creating an Atom FeedFeedResultResult

dom/atomoutput.xmldom/atomoutput.xml<?xml version="1.0" encoding="UTF-8"?><?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"><feed xmlns="http://www.w3.org/2005/Atom"> <title>Example Atom Feed</title><title>Example Atom Feed</title> <subtitle>Example Atom Feed</subtitle><subtitle>Example Atom Feed</subtitle> <id>http://www.example.org/</id><id>http://www.example.org/</id> <updated>2006-03-23T01:53:59-05:00</updated><updated>2006-03-23T01:53:59-05:00</updated> <entry><entry> <title type="text">My first entry</title><title type="text">My first entry</title> <link type="text/html" rel="alternate" <link type="text/html" rel="alternate" href="http://www.example.org/entry-url" title="My first href="http://www.example.org/entry-url" title="My first

entry"/>entry"/> <author><author> <name>Rob</name><name>Rob</name> </author></author> <id>http://www.example.org/entry-guid</id><id>http://www.example.org/entry-guid</id> <updated>2006-03-23T01:53:59-05:00</updated><updated>2006-03-23T01:53:59-05:00</updated> <published>2006-03-23T01:53:59-05:00</published><published>2006-03-23T01:53:59-05:00</published> <content><![CDATA[This is my first Atom entry!<br />More to <content><![CDATA[This is my first Atom entry!<br />More to

follow]]></content>follow]]></content> </entry></entry></feed></feed>

Page 41: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Document EditingDOM: Document Editingdom/editing.phpdom/editing.php

$dom->load('atomoutput.xml');$dom->load('atomoutput.xml');

$child = $dom->documentElement->firstChild;$child = $dom->documentElement->firstChild;while($child && $child->nodeName != "entry") { $child = $child-while($child && $child->nodeName != "entry") { $child = $child-

>nextSibling; }>nextSibling; }

if ($child && ($child = $child->firstChild)) {if ($child && ($child = $child->firstChild)) { while($child && $child->nodeName != "title") { $child = $child-while($child && $child->nodeName != "title") { $child = $child-

>nextSibling; }>nextSibling; } if ($child) {if ($child) { $child->setAttribute('type', 'html');$child->setAttribute('type', 'html'); $text = $child->firstChild;$text = $child->firstChild; $text->nodeValue = "<em>My first entry</em>";$text->nodeValue = "<em>My first entry</em>";

while($child) {while($child) { if ($child->nodeName == "updated") {if ($child->nodeName == "updated") { $text = $child->firstChild;$text = $child->firstChild; $text->nodeValue = date('c');$text->nodeValue = date('c'); break;break; }} $child = $child->nextSibling;$child = $child->nextSibling; }} }}}}print $dom->saveXML();print $dom->saveXML();

Page 42: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: EditingDOM: Editingdom/new_atomoutput.xmldom/new_atomoutput.xml

<?xml version="1.0" encoding="UTF-8"?><?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"><feed xmlns="http://www.w3.org/2005/Atom"> <title>Example Atom Feed</title><title>Example Atom Feed</title> <subtitle>Example Atom Feed</subtitle><subtitle>Example Atom Feed</subtitle> <id>http://www.example.org/</id><id>http://www.example.org/</id> <updated>2006-03-23T01:53:59-05:00</updated><updated>2006-03-23T01:53:59-05:00</updated> <entry><entry> <title type="html">&lt;em&gt;My first entry&lt;/em&gt;</title><title type="html">&lt;em&gt;My first entry&lt;/em&gt;</title> <link type="text/html" rel="alternate" <link type="text/html" rel="alternate" href="http://www.example.org/entry-url" title="My first href="http://www.example.org/entry-url" title="My first

entry"/>entry"/> <author><author> <name>Rob</name><name>Rob</name> </author></author> <id>http://www.example.org/entry-guid</id><id>http://www.example.org/entry-guid</id> <updated>2006-03-23T02:29:22-05:00</updated><updated>2006-03-23T02:29:22-05:00</updated> <published>2006-03-23T01:53:59-05:00</published><published>2006-03-23T01:53:59-05:00</published> <content><![CDATA[This is my first Atom entry!<br />More to <content><![CDATA[This is my first Atom entry!<br />More to

follow]]></content>follow]]></content> </entry></entry></feed></feed>

Page 43: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: Document DOM: Document ModificationModification

dom/modify.phpdom/modify.php/* Assume $entry refers to the first /* Assume $entry refers to the first

entry element within the Atom entry element within the Atom document */document */

while ($entry->hasChildNodes()) {while ($entry->hasChildNodes()) { $entry->removeChild($entry-$entry->removeChild($entry-

>firstChild);>firstChild);}}

OROR

$node = $entry->lastChild;$node = $entry->lastChild;while($node) {while($node) { $prev = $node->previousSibling;$prev = $node->previousSibling; $entry->removeChild($node);$entry->removeChild($node); $node = $prev;$node = $prev;}}

/* This Will Not Work! *//* This Will Not Work! */foreach($entry->childNodes AS foreach($entry->childNodes AS

$node) {$node) { $entry->removeChild($node);$entry->removeChild($node);}}

/* These will work */$children = $entry->childNodes;$length = $children->length - 1;

for ($x=$length; $x >=0; $x--) { $entry->removeChild($children->item($x));}

OR

$elem = $entry->cloneNode(FALSE);$entry->parentNode->replaceChild($elem, $entry);

Page 44: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM and NamespacesDOM and Namespaces

<xsd:complexType <xsd:complexType

xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="ArrayOfint">name="ArrayOfint"> <xsd:complexContent><xsd:complexContent> <xsd:restriction base="soapenc:Array"><xsd:restriction base="soapenc:Array"> <xsd:attribute ref="soapenc:arrayType" <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:int[ ]"wsdl:arrayType="xsd:int[ ]"/>/> </xsd:restriction></xsd:restriction> </xsd:complexContent></xsd:complexContent></xsd:complexType></xsd:complexType>

Page 45: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Dom and NamepsacesDom and Namepsacesdom/namespace.phpdom/namespace.php

define("SCHEMA_NS", "http://www.w3.org/2001/XMLSchema");define("SCHEMA_NS", "http://www.w3.org/2001/XMLSchema");define("WSDL_NS", "http://schemas.xmlsoap.org/wsdl/");define("WSDL_NS", "http://schemas.xmlsoap.org/wsdl/");$dom = new DOMDocument();$dom = new DOMDocument();

$root = $dom->createElementNS(SCHEMA_NS, "xsd:complexType");$root = $dom->createElementNS(SCHEMA_NS, "xsd:complexType");$dom->appendChild($root);$dom->appendChild($root);

$root->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:wsdl", $root->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:wsdl", WSDL_NS);WSDL_NS);

$root->setAttribute("name", "ArrayOfint");$root->setAttribute("name", "ArrayOfint");

$content = $root->appendChild($content = $root->appendChild(new DOMElement("xsd:complexContent", NULL, new DOMElement("xsd:complexContent", NULL, SCHEMA_NS)SCHEMA_NS)););

$restriction = $content->appendChild($restriction = $content->appendChild(new DOMElement("xsd:restriction", NULL, new DOMElement("xsd:restriction", NULL, SCHEMA_NS)SCHEMA_NS)););

$restriction->setAttribute("base", "soapenc:Array");$restriction->setAttribute("base", "soapenc:Array");

$attribute = $restriction->appendChild($attribute = $restriction->appendChild(new DOMElement("xsd:attribute", NULL, new DOMElement("xsd:attribute", NULL, SCHEMA_NS)SCHEMA_NS)););

$attribute->setAttribute("ref", "soapenc:arrayType");$attribute->setAttribute("ref", "soapenc:arrayType");

$attribute->setAttributeNS(WSDL_NS, "wsdl:arrayType", "xsd:int[]");$attribute->setAttributeNS(WSDL_NS, "wsdl:arrayType", "xsd:int[]");

Page 46: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM and XpathDOM and Xpathdom/xpath/dom-xpath.xmldom/xpath/dom-xpath.xml

<store><store> <books><books> <rare><rare> <book qty="4"><book qty="4"> <name>Cannery Row</name><name>Cannery Row</name> <price>400.00</price><price>400.00</price> <edition>1</edition><edition>1</edition> </book></book> </rare></rare> <classics><classics> <book qty="25"><book qty="25"> <name>Grapes of Wrath</name><name>Grapes of Wrath</name> <price>12.99</price><price>12.99</price> </book></book> <book qty="25"><book qty="25"> <name>Of Mice and Men</name><name>Of Mice and Men</name> <price>9.99</price><price>9.99</price> </book></book> </classics></classics> </books></books></store></store>

Page 47: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM and XpathDOM and Xpathdom/xpath/dom-xpath.phpdom/xpath/dom-xpath.php

$doc = new DOMDocument();$doc = new DOMDocument();$doc->load('dom-xpath.xml');$doc->load('dom-xpath.xml');$xpath = $xpath = new DOMXPath($doc);new DOMXPath($doc);

$nodelist = $xpath->$nodelist = $xpath->queryquery("//name");("//name");print "Last Book Title: ".$nodelist->item($nodelist->length - 1)-print "Last Book Title: ".$nodelist->item($nodelist->length - 1)-

>textContent."\n";>textContent."\n";

$nodelist = $xpath->query("//name[ancestor::rare]");$nodelist = $xpath->query("//name[ancestor::rare]");print "Last Rare Book Title: ".$nodelist->item($nodelist->length - 1)-print "Last Rare Book Title: ".$nodelist->item($nodelist->length - 1)-

>nodeValue."\n";>nodeValue."\n";

$inventory = $xpath->$inventory = $xpath->evaluateevaluate("sum(//book/@qty)");("sum(//book/@qty)");print "Total Books: ".$inventory."\n";print "Total Books: ".$inventory."\n";

$inventory = $xpath->evaluate("sum(//classics/book/@qty)");$inventory = $xpath->evaluate("sum(//classics/book/@qty)");print "Total Classic Books: ".$inventory."\n";print "Total Classic Books: ".$inventory."\n";

$inventory = $xpath->evaluate("count(//book[parent::classics])");$inventory = $xpath->evaluate("count(//book[parent::classics])");print "Distinct Classic Book Titles: ".$inventory."\n";print "Distinct Classic Book Titles: ".$inventory."\n";

Page 48: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM and Xpath ResultsDOM and Xpath Results/* $nodelist = $xpath->query("//name")/* $nodelist = $xpath->query("//name")$nodelist->item($nodelist->length - 1)->textContent */$nodelist->item($nodelist->length - 1)->textContent */Last Book Title: Of Mice and MenLast Book Title: Of Mice and Men

/* $xpath->query("//name[ancestor::rare]");/* $xpath->query("//name[ancestor::rare]");$nodelist->item($nodelist->length - 1)->nodeValue */$nodelist->item($nodelist->length - 1)->nodeValue */Last Rare Book Title: Cannery RowLast Rare Book Title: Cannery Row

/* $xpath->evaluate("sum(/* $xpath->evaluate("sum(//book/@qty//book/@qty)") */)") */Total Books: 54Total Books: 54

/* $xpath->evaluate("sum(/* $xpath->evaluate("sum(//classics/book/@qty//classics/book/@qty)") */)") */Total Classic Books: 50Total Classic Books: 50

/* $xpath->evaluate("count(//book[parent::classics])") *//* $xpath->evaluate("count(//book[parent::classics])") */Distinct Classic Book Titles: 2Distinct Classic Book Titles: 2

Page 49: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM and Xpath w/Namespaces DOM and Xpath w/Namespaces dom/xpath/dom-xpathns.xmldom/xpath/dom-xpathns.xml

<store <store xmlns="http://www.example.com/store" xmlns="http://www.example.com/store" xmlns:bk="http://www.example.com/book"xmlns:bk="http://www.example.com/book">>

<books><books> <rare><rare> <bk:book qty="4"><bk:book qty="4"> <bk:name>Cannery Row</bk:name><bk:name>Cannery Row</bk:name> <bk:price>400.00</bk:price><bk:price>400.00</bk:price> <bk:edition>1</bk:edition><bk:edition>1</bk:edition> </bk:book></bk:book> </rare></rare> <classics><classics> <bk:book qty="25"><bk:book qty="25"> <bk:name>Grapes of Wrath</bk:name><bk:name>Grapes of Wrath</bk:name> <bk:price>12.99</bk:price><bk:price>12.99</bk:price> </bk:book></bk:book> <bk:book qty="25" <bk:book qty="25" xmlns:bk="http://www.example.com/classicbook"xmlns:bk="http://www.example.com/classicbook">> <bk:name>Of Mice and Men</bk:name><bk:name>Of Mice and Men</bk:name> <bk:price>9.99</bk:price><bk:price>9.99</bk:price> </bk:book></bk:book> </classics></classics> <classics <classics xmlns="http://www.example.com/ExteralClassics"xmlns="http://www.example.com/ExteralClassics">> <book qty="33"><book qty="33"> <name>To Kill a Mockingbird</name><name>To Kill a Mockingbird</name> <price>10.99</price><price>10.99</price> </book></book> </classics></classics> </books></books></store></store>

Page 50: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM and Xpath DOM and Xpath w/Namespacesw/Namespaces

dom/xpath/dom-xpathns.phpdom/xpath/dom-xpathns.php$nodelist = $xpath->query("//name");$nodelist = $xpath->query("//name");print "Last Book Title: ".$nodelist->item($nodelist->length - 1)->textContent."\print "Last Book Title: ".$nodelist->item($nodelist->length - 1)->textContent."\

n";n";// // Last Book Title:Last Book Title: /* Why empty? */ /* Why empty? */

$nodelist = $xpath->query("//bk:name");$nodelist = $xpath->query("//bk:name");print "Last Book Title: ".$nodelist->item($nodelist->length - 1)->textContent."\print "Last Book Title: ".$nodelist->item($nodelist->length - 1)->textContent."\

n";n";// // Last Book Title: Grapes of WrathLast Book Title: Grapes of Wrath /* Why not "Of Mice and Men" */ /* Why not "Of Mice and Men" */

$nodelist = $xpath->query("//bk:name[ancestor::rare]");$nodelist = $xpath->query("//bk:name[ancestor::rare]");print "Last Rare Book Title: ".$nodelist->item($nodelist->length - 1)-print "Last Rare Book Title: ".$nodelist->item($nodelist->length - 1)-

>nodeValue."\n";>nodeValue."\n";// // Last Rare Book Title:Last Rare Book Title: /* Why empty? */ /* Why empty? */

$xpath->registerNamespace("rt", "http://www.example.com/store");$xpath->registerNamespace("rt", "http://www.example.com/store");$nodelist = $xpath->query("//bk:name[ancestor::rt:rare]");$nodelist = $xpath->query("//bk:name[ancestor::rt:rare]");print "Last Rare Book Title: ".$nodelist->item($nodelist->length - 1)-print "Last Rare Book Title: ".$nodelist->item($nodelist->length - 1)-

>nodeValue."\n";>nodeValue."\n";// // Last Rare Book Title: Cannery RowLast Rare Book Title: Cannery Row

$xpath->registerNamespace("ext", "http://www.example.com/ExteralClassics");$xpath->registerNamespace("ext", "http://www.example.com/ExteralClassics");$nodelist = $xpath->query("(//bk:name) | (//ext:name)");$nodelist = $xpath->query("(//bk:name) | (//ext:name)");print "Last Book Title: ".$nodelist->item($nodelist->length - 1)->textContent."\print "Last Book Title: ".$nodelist->item($nodelist->length - 1)->textContent."\

n";n";//// Last Book Title: To Kill a Mockingbird Last Book Title: To Kill a Mockingbird

Page 51: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM and Xpath DOM and Xpath w/Namespacesw/Namespaces

dom/xpath/dom-xpathns.phpdom/xpath/dom-xpathns.php$xpath->registerNamespace("bk2", $xpath->registerNamespace("bk2", "http://www.example.com/classicbook");"http://www.example.com/classicbook");

$nodelist = $xpath->query("//bk2:name");$nodelist = $xpath->query("//bk2:name");print "Last Book Title (bk2): "print "Last Book Title (bk2): "print $nodelist->item($nodelist->length - 1)->textContent."\n";print $nodelist->item($nodelist->length - 1)->textContent."\n";// // Last Book Title (bk2): Of Mice and MenLast Book Title (bk2): Of Mice and Men

Complete Results:Complete Results:Last Book Title: Last Book Title: Last Book Title: Grapes of WrathLast Book Title: Grapes of WrathLast Rare Book Title: Last Rare Book Title: Last Rare Book Title: Cannery RowLast Rare Book Title: Cannery RowLast Book Title: To Kill a MockingbirdLast Book Title: To Kill a MockingbirdLast Book Title (bk2): Of Mice and MenLast Book Title (bk2): Of Mice and Men

Page 52: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Performing ValidationPerforming Validationdom/validation/validate.phpdom/validation/validate.php

$doc = new DOMDocument();$doc = new DOMDocument();print "DTD Validation:\n";print "DTD Validation:\n";$doc->load('courses-dtd.xml', LIBXML_DTDVALID);$doc->load('courses-dtd.xml', LIBXML_DTDVALID);/* No errors means document is valid *//* No errors means document is valid */

if ($doc->validate()) { print " Document Is Valid\n"; }if ($doc->validate()) { print " Document Is Valid\n"; }

print "DTD Validation FAILURE:\n";print "DTD Validation FAILURE:\n";$doc->load('course-id.xml');$doc->load('course-id.xml');if (if ($doc->validate()$doc->validate()) { print " Document Is Valid\n"; }) { print " Document Is Valid\n"; }

$doc->load('course.xml');$doc->load('course.xml');print "\nXML Schema Validation:\n";print "\nXML Schema Validation:\n";if (if ($doc->schemaValidate('course.xsd')$doc->schemaValidate('course.xsd')) { print " Document ) { print " Document

is valid\n"; }is valid\n"; }

$doc->load('course.xml');$doc->load('course.xml');print "\nRelaxNG Validation:\n";print "\nRelaxNG Validation:\n";if (if ($doc->relaxNGValidate('course.rng')$doc->relaxNGValidate('course.rng')) { print " Document ) { print " Document

is valid\n"; }is valid\n"; }

Page 53: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Performing Validation Performing Validation ResultsResults

DTD Validation:DTD Validation: Document Is ValidDocument Is Valid

DTD Validation FAILURE:DTD Validation FAILURE:Warning: DOMDocument::validate(): No declaration for element Warning: DOMDocument::validate(): No declaration for element

courses in courses in /home/rrichards/workshop/dom/validation/validate.php on line /home/rrichards/workshop/dom/validation/validate.php on line 1111

Warning: DOMDocument::validate(): No declaration for element Warning: DOMDocument::validate(): No declaration for element course in /home/rrichards/workshop/dom/validation/validate.php course in /home/rrichards/workshop/dom/validation/validate.php on line 11on line 11

Warning: DOMDocument::validate(): No declaration for element Warning: DOMDocument::validate(): No declaration for element title in /home/rrichards/workshop/dom/validation/validate.php title in /home/rrichards/workshop/dom/validation/validate.php on line 11on line 11

. . .. . .

XML Schema Validation:XML Schema Validation: Document is validDocument is valid

RelaxNG Validation:RelaxNG Validation: Document is validDocument is valid

Page 54: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Extending DOM ClassesExtending DOM Classes

Overriding the constructor requires Overriding the constructor requires the parent constructor to be called.the parent constructor to be called.

Properties built into the DOM Properties built into the DOM classes cannot be overridden.classes cannot be overridden.

Methods built into the DOM classes Methods built into the DOM classes may can be overridden.may can be overridden.

The lifespan of an extended object is The lifespan of an extended object is that of the object itself.that of the object itself.

Page 55: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Extending DOM Classes Extending DOM Classes dom/extending/dom/extending/extending.phpextending.php

class customElement extends DOMElement { }class customElement extends DOMElement { }

class customDoc extends DOMDocument {class customDoc extends DOMDocument { public $nodeName = "customDoc";public $nodeName = "customDoc";

function __construct($rootName) {function __construct($rootName) { parent::__construct();parent::__construct(); if (! empty($rootName)) { if (! empty($rootName)) { $element = $this->appendChild(new DOMElement($rootName)); }$element = $this->appendChild(new DOMElement($rootName)); } }}

function createElement($name, $value, $parent=NULL) {function createElement($name, $value, $parent=NULL) { $custom = new customElement($name, $value);$custom = new customElement($name, $value); if ($parent && ($parent instanceof DOMElement)) { if ($parent && ($parent instanceof DOMElement)) { $parent->appendChild($custom); }$parent->appendChild($custom); } return $custom;return $custom; }}}}

$myc = new customDoc("root");$myc = new customDoc("root");$myelement = $myc->createElement("myname", "myvalue", $myc-$myelement = $myc->createElement("myname", "myvalue", $myc-

>documentElement);>documentElement);if ($myelement instanceof customElement) { print "This is a if ($myelement instanceof customElement) { print "This is a

customElement\n"; }customElement\n"; }

print $myc->nodeName."\n";print $myc->nodeName."\n";print $myc->saveXML();print $myc->saveXML();

Page 56: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM Object ScopeDOM Object Scopedom/extending/object_scope.phpdom/extending/object_scope.php

class customElement extends DOMElement { }class customElement extends DOMElement { }

function changeit($doc) {function changeit($doc) { $myelement$myelement = new customElement("custom", "element2"); = new customElement("custom", "element2");

$doc->replaceChild($myelement, $doc->documentElement);$doc->replaceChild($myelement, $doc->documentElement);print "Within changeit function: ".get_class($doc-print "Within changeit function: ".get_class($doc->documentElement)."\n";>documentElement)."\n";

}}

$doc = new DOMDocument();$doc = new DOMDocument();

$myelement$myelement = $doc->appendChild(new customElement("custom", = $doc->appendChild(new customElement("custom", "element"));"element"));

print "After Append: ".get_class($myelement)."\n";print "After Append: ".get_class($myelement)."\n";

unset($myelement);unset($myelement);print "After unset: ".get_class($doc->documentElement)."\n";print "After unset: ".get_class($doc->documentElement)."\n";

changeit($doc);changeit($doc);print "Outside changeit(): ".get_class($doc->documentElement)."\n";print "Outside changeit(): ".get_class($doc->documentElement)."\n";

After Append: customElementAfter Append: customElementAfter unset: DOMElementAfter unset: DOMElementWithin changeit function: customElementWithin changeit function: customElementOutside changeit(): DOMElementOutside changeit(): DOMElement

Page 57: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM: registerNodeClassDOM: registerNodeClass dom/extending/register_node_class.php dom/extending/register_node_class.php

class customElement extends DOMElement { }class customElement extends DOMElement { }function changeit($doc) {function changeit($doc) { $myelement$myelement = new DOMElement("custom", "element2"); = new DOMElement("custom", "element2");

$doc->replaceChild($myelement, $doc->documentElement);$doc->replaceChild($myelement, $doc->documentElement);print "Within changeit function: ".get_class($doc->documentElement)."\n";print "Within changeit function: ".get_class($doc->documentElement)."\n";

}}

$doc = new DOMDocument();$doc = new DOMDocument();$doc->registerNodeClass('DOMElement', 'customElement');$doc->registerNodeClass('DOMElement', 'customElement');

$myelement$myelement = $doc->appendChild($doc->createElement("custom", = $doc->appendChild($doc->createElement("custom", "element"));"element"));

print "After Append: ".get_class($myelement)."\n";print "After Append: ".get_class($myelement)."\n";

unset($myelement);unset($myelement);print "After unset: ".get_class($doc->documentElement)."\n";print "After unset: ".get_class($doc->documentElement)."\n";

changeit($doc);changeit($doc);print "Outside changeit(): ".get_class($doc->documentElement)."\n";print "Outside changeit(): ".get_class($doc->documentElement)."\n";

After Append: customElementAfter Append: customElementAfter unset: customElementAfter unset: customElementWithin changeit function: DOMElementWithin changeit function: DOMElementOutside changeit(): customElementOutside changeit(): customElement

Page 58: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

DOM:Common IssuesDOM:Common Issues

DOM Objects and SessionsDOM Objects and Sessions Removing Nodes while iterating a Nodeset Removing Nodes while iterating a Nodeset

skips nodesskips nodes XML Tree contains garbled charactersXML Tree contains garbled characters Extended class is not returned from Extended class is not returned from

property or methodproperty or method Elements not being returned by IDElements not being returned by ID Entity errors are issues when loading a Entity errors are issues when loading a

documentdocument New DTD is not recognized by documentNew DTD is not recognized by document

Page 59: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXMLSimpleXML

Provides simple access to XML documentsProvides simple access to XML documents Operates only on elements and attributesOperates only on elements and attributes Contains XPath supportContains XPath support Allows for modifications to the XMLAllows for modifications to the XML Zero copy interoperability with DOMZero copy interoperability with DOM New in PHP 5.1.3New in PHP 5.1.3

Elements and attributes can be added using Elements and attributes can be added using addChild() and addAttribute() methods.addChild() and addAttribute() methods.

Node names can be retrieved by calling Node names can be retrieved by calling getName().getName().

Page 60: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: Consuming Yahoo SimpleXML: Consuming Yahoo WebSearch WebSearch

simplexml/yahoo_rest_results.xmlsimplexml/yahoo_rest_results.xml<ResultSet <ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:srch" xmlns="urn:yahoo:srch" xsi:schemaLocation="urn:yahoo:srchxsi:schemaLocation="urn:yahoo:srch http://api.search.yahoo.com/WebSearchService/V1/WebSearchResponse.xsd" http://api.search.yahoo.com/WebSearchService/V1/WebSearchResponse.xsd" totalResultsAvailable="374000" totalResultsAvailable="374000" totalResultsReturnedtotalResultsReturned="5" ="5"

firstResultPosition="1">firstResultPosition="1"> <Result><Result> <Title><Title>Zend Technologies - PHP 5 In Depth - XML in PHP 5 - Zend Technologies - PHP 5 In Depth - XML in PHP 5 -

What's New?</Title>What's New?</Title> <Summary>XML in PHP 5 - What's New? By Christian Stocker. <Summary>XML in PHP 5 - What's New? By Christian Stocker.

March . . . </Summary>March . . . </Summary> <Url><Url>http://www.zend.com/php5/articles/php5-xmlphp.php</Url>http://www.zend.com/php5/articles/php5-xmlphp.php</Url> <ClickUrl>http://uk.wrs.yahoo.com/_ylt=. . .</ClickUrl><ClickUrl>http://uk.wrs.yahoo.com/_ylt=. . .</ClickUrl> <ModificationDate><ModificationDate>1143014400</ModificationDate>1143014400</ModificationDate> <MimeType>text/html</MimeType><MimeType>text/html</MimeType> <Cache><Cache> <Url>http://uk.wrs.yahoo.com/...</Url><Url>http://uk.wrs.yahoo.com/...</Url> <Size>112625</Size><Size>112625</Size> </Cache></Cache> </Result></Result> . . .. . .</Results></Results>

Page 61: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: Consuming Yahoo SimpleXML: Consuming Yahoo WebSearch WebSearch

simplexml/reading_rest.phpsimplexml/reading_rest.php/* URL to Web Search service *//* URL to Web Search service */$url = 'http://api.search.yahoo.com/WebSearchService/V1/webSearch';$url = 'http://api.search.yahoo.com/WebSearchService/V1/webSearch';

/* The query is separate here as the terms must be encoded. *//* The query is separate here as the terms must be encoded. */$url .= '?query='.rawurlencode('php5 xml');$url .= '?query='.rawurlencode('php5 xml');

/* Complete the URL adding App ID, limit to 5 results and only English results *//* Complete the URL adding App ID, limit to 5 results and only English results */$url .= "&appid=zzz&results=5&language=en";$url .= "&appid=zzz&results=5&language=en";

$sxe = simplexml_load_file($url);$sxe = simplexml_load_file($url);

/* Check for number of results returned *//* Check for number of results returned */if ((int)$sxe['totalResultsReturned'] > 0) {if ((int)$sxe['totalResultsReturned'] > 0) { /* Loop through each result and output title, url and modification date /* Loop through each result and output title, url and modification date

*/*/ foreach ($sxe->Result AS $result) {foreach ($sxe->Result AS $result) { print 'Title: '.$result->Title."\n";print 'Title: '.$result->Title."\n"; print 'Url: '.$result->Url."\n";print 'Url: '.$result->Url."\n"; print 'Mod Date: '.date ('M d Y', (int)$result-print 'Mod Date: '.date ('M d Y', (int)$result-

>ModificationDate)."\n\n";>ModificationDate)."\n\n"; }}}}

Page 62: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: Consuming Yahoo SimpleXML: Consuming Yahoo WebSearch WebSearch

RESULTSRESULTSTitle: Zend Technologies - PHP 5 In Depth - XML in PHP 5 - What's Title: Zend Technologies - PHP 5 In Depth - XML in PHP 5 - What's

New?New?Url: http://www.zend.com/php5/articles/php5-xmlphp.phpUrl: http://www.zend.com/php5/articles/php5-xmlphp.phpMod Date: Sep 06 2006Mod Date: Sep 06 2006

Title: FreshPorts -- textproc/php5-xmlTitle: FreshPorts -- textproc/php5-xmlUrl: http://www.freshports.org/textproc/php5-xmlUrl: http://www.freshports.org/textproc/php5-xmlMod Date: Aug 31 2006Mod Date: Aug 31 2006

Title: PHP5 XML support? - Dev ShedTitle: PHP5 XML support? - Dev ShedUrl: http://forums.devshed.com/php-development-5/php5-xml-Url: http://forums.devshed.com/php-development-5/php5-xml-

support-69898.htmlsupport-69898.htmlMod Date: Aug 21 2006Mod Date: Aug 21 2006

Title: ONLamp.com -- Using PHP 5's SimpleXMLTitle: ONLamp.com -- Using PHP 5's SimpleXMLUrl: http://www.onlamp.com/pub/a/php/2004/01/15/simplexml.htmlUrl: http://www.onlamp.com/pub/a/php/2004/01/15/simplexml.htmlMod Date: Sep 06 2006Mod Date: Sep 06 2006

Title: PHP5 XML/XSL - Rendering strings? - PHPTitle: PHP5 XML/XSL - Rendering strings? - PHPUrl: http://www.thescripts.com/forum/thread5141.htmlUrl: http://www.thescripts.com/forum/thread5141.htmlMod Date: Sep 01 2006Mod Date: Sep 01 2006

Page 63: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

<store xmlns="http://www.example.com/store" <store xmlns="http://www.example.com/store" xmlns:bk="http://www.example.com/book">xmlns:bk="http://www.example.com/book">

<books><books> <rare><rare> <bk:book qty="4"><bk:book qty="4"> <bk:name>Cannery Row</bk:name><bk:name>Cannery Row</bk:name> <bk:price>400.00</bk:price><bk:edition>1</bk:edition><bk:price>400.00</bk:price><bk:edition>1</bk:edition> </bk:book></bk:book> </rare></rare> <classics><classics> <bk:book qty="25"><bk:book qty="25"> <bk:name>Grapes of Wrath</bk:name><bk:name>Grapes of Wrath</bk:name> <bk:price>12.99</bk:price><bk:price>12.99</bk:price> </bk:book></bk:book> <bk:book qty="25" xmlns:bk="http://www.example.com/classicbook"><bk:book qty="25" xmlns:bk="http://www.example.com/classicbook"> <bk:name>Of Mice and Men</bk:name><bk:name>Of Mice and Men</bk:name> <bk:price>9.99</bk:price><bk:price>9.99</bk:price> </bk:book></bk:book> </classics></classics> <classics xmlns="http://www.example.com/ExteralClassics"><classics xmlns="http://www.example.com/ExteralClassics"> <book qty="33"><book qty="33"> <name>To Kill a Mockingbird</name><name>To Kill a Mockingbird</name> <price>10.99</price><price>10.99</price> </book></book> </classics></classics> </books></books></store></store>

Page 64: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: NamespacesSimpleXML: Namespacessimplexml/simplexml-namespace.phpsimplexml/simplexml-namespace.php

$store = simplexml_load_file('simplexml-xpathns.xml');$store = simplexml_load_file('simplexml-xpathns.xml');$books = $store->books;$books = $store->books;

foreach ($books->classics AS $classic) {foreach ($books->classics AS $classic) { if ($classic->book)if ($classic->book) print $classic->book->name."\n\n";print $classic->book->name."\n\n";}}/* Why only one result?: To Kill a Mockingbird *//* Why only one result?: To Kill a Mockingbird */

$x = 0;$x = 0;foreach ($books->classics AS $classics) {foreach ($books->classics AS $classics) { if ($x++ == 0) {if ($x++ == 0) { $children = $children =

$classics->children("http://www.example.com/classicbook");$classics->children("http://www.example.com/classicbook"); /* Print name for the books where book element resides in a prefixed /* Print name for the books where book element resides in a prefixed

namespace */namespace */ print print $classics->children("http://www.example.com/book")->book-$classics->children("http://www.example.com/book")->book-

>name>name."\n";."\n"; print print $children$children->book->name."\n";->book->name."\n"; } else} else print $classic->book->name."\n";print $classic->book->name."\n";}}

Page 65: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: Namespaces SimpleXML: Namespaces ResultsResults

To Kill a MockingbirdTo Kill a Mockingbird

Grapes of WrathGrapes of Wrath

Of Mice and MenOf Mice and Men

To Kill a MockingbirdTo Kill a Mockingbird

Page 66: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: XpathSimpleXML: Xpathsimplexml/simplexml-xpathns.phpsimplexml/simplexml-xpathns.php

$sxe = simplexml_load_file('simplexml-xpathns.xml');$sxe = simplexml_load_file('simplexml-xpathns.xml');

$nodelist = $sxe->xpath("//bk:name");$nodelist = $sxe->xpath("//bk:name");print "Last Book Title: ".$nodelist[count($nodelist) - 1]."\n";print "Last Book Title: ".$nodelist[count($nodelist) - 1]."\n";

$sxe->registerXPathNamespace("rt", $sxe->registerXPathNamespace("rt", "http://www.example.com/store");"http://www.example.com/store");

$nodelist = $sxe->xpath("//bk:name[ancestor::rt:rare]");$nodelist = $sxe->xpath("//bk:name[ancestor::rt:rare]");print "Last Rare Book Title: ".$nodelist[count($nodelist) - 1]."\n";print "Last Rare Book Title: ".$nodelist[count($nodelist) - 1]."\n";

$sxe->registerXPathNamespace("ext", $sxe->registerXPathNamespace("ext", "http://www.example.com/ExteralClassics");"http://www.example.com/ExteralClassics");

$nodelist = $sxe->xpath("(//bk:name) | (//ext:name)");$nodelist = $sxe->xpath("(//bk:name) | (//ext:name)");print "Last Book Title: ".$nodelist[count($nodelist) - 1]."\n";print "Last Book Title: ".$nodelist[count($nodelist) - 1]."\n";

$sxe->registerXPathNamespace("bk2", $sxe->registerXPathNamespace("bk2", "http://www.example.com/classicbook");"http://www.example.com/classicbook");

$nodelist = $sxe->xpath("//bk2:name");$nodelist = $sxe->xpath("//bk2:name");print "Last Book Title (bk2): ".$nodelist[count($nodelist) - 1]."\n";print "Last Book Title (bk2): ".$nodelist[count($nodelist) - 1]."\n";

Page 67: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: XPath SimpleXML: XPath ResultsResults

Last Book Title: Grapes of WrathLast Book Title: Grapes of Wrath

Last Rare Book Title: Cannery RowLast Rare Book Title: Cannery Row

Last Book Title: To Kill a MockingbirdLast Book Title: To Kill a Mockingbird

Last Book Title (bk2): Of Mice and Last Book Title (bk2): Of Mice and MenMen

Page 68: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: Advanced SimpleXML: Advanced EditingEditing

simplexml/editing.phpsimplexml/editing.php$data = array(array('title'=>'Result 1', 'descript'=>'Res1 description'),$data = array(array('title'=>'Result 1', 'descript'=>'Res1 description'), array('title'=>'Result 2', 'descript'=>'description of array('title'=>'Result 2', 'descript'=>'description of

Res2'),Res2'), array('title'=>'Result 3', 'descript'=>'This is result 3'));array('title'=>'Result 3', 'descript'=>'This is result 3'));

class webservice extends simpleXMLElement {class webservice extends simpleXMLElement { public function appendElement($name, $value=NULL) {public function appendElement($name, $value=NULL) { $node = dom_import_simplexml($this);$node = dom_import_simplexml($this); $newnode = $value ? new DOMElement($name, $value) : new $newnode = $value ? new DOMElement($name, $value) : new

DOMElement($name);DOMElement($name); $node->appendChild($newnode);$node->appendChild($newnode); return simplexml_import_dom($newnode, 'webservice');return simplexml_import_dom($newnode, 'webservice');} }} }

$rest = simplexml_load_string('<results num="0" />', 'webservice');$rest = simplexml_load_string('<results num="0" />', 'webservice');$rest['num'] = count($data);$rest['num'] = count($data);

foreach ($data AS $result_item) {foreach ($data AS $result_item) { $result = $rest->appendElement('result');$result = $rest->appendElement('result'); $result->appendElement('title', $result_item['title']);$result->appendElement('title', $result_item['title']); $result->appendElement('description');$result->appendElement('description'); $result->description = $result_item['descript']; }$result->description = $result_item['descript']; }

print $rest->asXML();print $rest->asXML();

Page 69: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: Advanced SimpleXML: Advanced Editing ResultsEditing Results

<?xml version="1.0"?><?xml version="1.0"?><results num="3"><results num="3"> <result><result> <title>Result 1</title><title>Result 1</title> <description>Res1 description</description><description>Res1 description</description> </result></result> <result><result> <title>Result 2</title><title>Result 2</title> <description>description of Res2</description><description>description of Res2</description> </result></result> <result><result> <title>Result 3</title><title>Result 3</title> <description>This is result 3</description><description>This is result 3</description> </result></result></results></results>

Page 70: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: Advanced Editing SimpleXML: Advanced Editing PHP 5.1.3PHP 5.1.3

simplexml/editing_php513.phpsimplexml/editing_php513.php

$data = array(array('title'=>'Result 1', 'descript'=>'Res1 $data = array(array('title'=>'Result 1', 'descript'=>'Res1 description'),description'),

array('title'=>'Result 2', 'descript'=>'description of array('title'=>'Result 2', 'descript'=>'description of Res2'),Res2'),

array('title'=>'Result 3', 'descript'=>'This is result 3'));array('title'=>'Result 3', 'descript'=>'This is result 3'));

$rest = simplexml_load_string('<results num="0" />');$rest = simplexml_load_string('<results num="0" />');$rest['num'] = count($data);$rest['num'] = count($data);

foreach ($data AS $result_item) {foreach ($data AS $result_item) { $result = $rest->$result = $rest->addChildaddChild('result');('result'); $result->$result->addChildaddChild('title', $result_item['title']);('title', $result_item['title']); $result->$result->addChildaddChild('description');('description'); $result->description = $result_item['descript'];$result->description = $result_item['descript'];}}

$rest->asXML('editing_php513.xml');$rest->asXML('editing_php513.xml');

Page 71: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: Removing SimpleXML: Removing data data

remove_data.phpremove_data.php<?php<?php$results = simplexml_load_file('editing_php513.xml');$results = simplexml_load_file('editing_php513.xml');

/* Delete title from first result element *//* Delete title from first result element */unset($results->result->title);unset($results->result->title);

/* Delete the 2nd result element - ONLY WORKS in /* Delete the 2nd result element - ONLY WORKS in PHP 5.1.3 */PHP 5.1.3 */

unset($results->result[1]);unset($results->result[1]);

print $results->asXML();print $results->asXML();?>?>

Page 72: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SimpleXML: Removing SimpleXML: Removing data data RESULTSRESULTS

<?xml version="1.0"?><?xml version="1.0"?>

<results num="3"><results num="3">

<result><result>

<description>Res1 description</description><description>Res1 description</description>

</result></result>

<result><result>

<title>Result 3</title><title>Result 3</title>

<description>This is result 3</description><description>This is result 3</description>

</result></result>

</results></results>

Page 73: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Simple API for XML Simple API for XML (SAX)(SAX)

Event based push parserEvent based push parser Low memory usageLow memory usage Works using function callbacksWorks using function callbacks Almost completely compatible with Almost completely compatible with

ext/xml from PHP 4ext/xml from PHP 4 Default encoding is UTF-8 rather Default encoding is UTF-8 rather

than ISO-8859-1 as it was in than ISO-8859-1 as it was in PHP 4PHP 4

Page 74: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SAX: Source Document SAX: Source Document xml/xml_simple.xmlxml/xml_simple.xml

<?xml version='1.0'?><?xml version='1.0'?><chapter xmlns:a="http://www.example.com/namespace-a"<chapter xmlns:a="http://www.example.com/namespace-a" xmlns="http://www.example.com/default">xmlns="http://www.example.com/default"> <a:title>ext/xml</a:title><a:title>ext/xml</a:title> <para><para> First ParagraphFirst Paragraph </para></para> <a:section a:id="about"><a:section a:id="about"> <title>About this Document</title><title>About this Document</title> <para><para> <!-- this is a comment --><!-- this is a comment --> <?php echo 'Hi! This is PHP version ' . phpversion(); ?><?php echo 'Hi! This is PHP version ' . phpversion(); ?> </para></para> </a:section></a:section></chapter></chapter>

Page 75: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SAX: Simple Example SAX: Simple Example xml/xml_simple.phpxml/xml_simple.php

<?php<?phpfunction startElement($parser, $elementname, $attributes) {function startElement($parser, $elementname, $attributes) { print "* Start Element: $elementname \n";print "* Start Element: $elementname \n"; foreach ($attributes as $attname => $attvalue) {foreach ($attributes as $attname => $attvalue) { print " $attname => $attvalue \n";print " $attname => $attvalue \n"; }}}}

function endElement($parser, $elementname) {function endElement($parser, $elementname) { print "* End Element: $elementname\n";print "* End Element: $elementname\n";}}

function charDataHandler($parser,$data) {function charDataHandler($parser,$data) { if (trim($data) != "") print $data."\n";if (trim($data) != "") print $data."\n";}}

function PIhandler ($parser, $target, $data) {function PIhandler ($parser, $target, $data) { print "PI: $target -> $data\n";print "PI: $target -> $data\n";}}

function DefaultHandler($parser, $data) {function DefaultHandler($parser, $data) { print "Default: $data\n";print "Default: $data\n";}}

Page 76: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SAX: Simple Example SAX: Simple Example xml/xml_simple.phpxml/xml_simple.php

$parser = xml_parser_create();$parser = xml_parser_create();/* Disable as case is significant in XML *//* Disable as case is significant in XML */xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING,

false);false);

xml_set_element_handler($parser,"startElement","endElement");xml_set_element_handler($parser,"startElement","endElement");xml_set_character_data_handler($parser, "charDataHandler");xml_set_character_data_handler($parser, "charDataHandler");xml_set_processing_instruction_handler ($parser, xml_set_processing_instruction_handler ($parser,

"PIhandler");"PIhandler");xml_set_default_handler ($parser, "DefaultHandler");xml_set_default_handler ($parser, "DefaultHandler");

if (($fp = fopen("xml_simple.xml", "r"))) { if (($fp = fopen("xml_simple.xml", "r"))) { while ($data = fread($fp, 4096)) {while ($data = fread($fp, 4096)) { xml_parse($parser, $data, feof($fp));xml_parse($parser, $data, feof($fp)); }}}}?>?>

Page 77: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SAX: Simple Example SAX: Simple Example RESULTSRESULTS

* Start Element: chapter * Start Element: chapter xmlns:a => http://www.example.com/namespace-a xmlns:a => http://www.example.com/namespace-a xmlns => http://www.example.com/default xmlns => http://www.example.com/default * Start Element: a:title * Start Element: a:title ext/xmlext/xml* End Element: a:title* End Element: a:title* Start Element: para * Start Element: para

First ParagraphFirst Paragraph* End Element: para* End Element: para* Start Element: a:section * Start Element: a:section a:id => about a:id => about * Start Element: title * Start Element: title About this DocumentAbout this Document* End Element: title* End Element: title* Start Element: para * Start Element: para Default: <!-- this is a comment -->Default: <!-- this is a comment -->PI: php -> echo 'Hi! This is PHP version ' . phpversion(); PI: php -> echo 'Hi! This is PHP version ' . phpversion(); * End Element: para* End Element: para* End Element: a:section* End Element: a:section* End Element: chapter* End Element: chapter

Page 78: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SAX: Error Handling SAX: Error Handling xml/xml_error.phpxml/xml_error.php

<?php<?php/* Malformed document *//* Malformed document */$data = "<root>";$data = "<root>";

$parser = xml_parser_create();$parser = xml_parser_create();

if(! xml_parse($parser, $data, TRUE)) {if(! xml_parse($parser, $data, TRUE)) { /* Normally die is or some other escape mechanism is also /* Normally die is or some other escape mechanism is also

called*/called*/ printf("XML error: %s in line %d, column %d\n\n",printf("XML error: %s in line %d, column %d\n\n", xml_error_string(xml_get_error_code($parser))xml_error_string(xml_get_error_code($parser)),, xml_get_current_line_number($parser),xml_get_current_line_number($parser), xml_get_current_column_number($parser));xml_get_current_column_number($parser));}}

/* Magically you can also get a structured error *//* Magically you can also get a structured error */$xmlError = libxml_get_last_error();$xmlError = libxml_get_last_error();var_dump($xmlError);var_dump($xmlError);?>?>

Page 79: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SAX: Error Handling SAX: Error Handling RESULTSRESULTS

XML error: Invalid document end in line 1, column 7XML error: Invalid document end in line 1, column 7

object(LibXMLError)#1 (6) {object(LibXMLError)#1 (6) { ["level"]=>["level"]=> int(3)int(3) ["code"]=>["code"]=> int(5)int(5) ["column"]=>["column"]=> int(7)int(7) ["message"]=>["message"]=> string(41) "Extra content at the end of the documentstring(41) "Extra content at the end of the document"" ["file"]=>["file"]=> string(0) ""string(0) "" ["line"]=>["line"]=> int(1)int(1)}}

Page 80: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SAX: Advanced Example SAX: Advanced Example xml/xml_advanced.phpxml/xml_advanced.php

class cSax {class cSax { function startElement($parser, $elementname, $attributes) {function startElement($parser, $elementname, $attributes) { list($namespaceURI,$localName)= split("@",$elementname);list($namespaceURI,$localName)= split("@",$elementname); if (! $localName) {if (! $localName) { $localName = $namespaceURI;$localName = $namespaceURI; $namespaceURI = "";$namespaceURI = ""; }} print "* Start Element: $localName".print "* Start Element: $localName". ($namespaceURI ? " in $namespaceURI" : "")."\n";($namespaceURI ? " in $namespaceURI" : "")."\n"; foreach ($attributes as $attname => $attvalue) {foreach ($attributes as $attname => $attvalue) { print " $attname => $attvalue \n";print " $attname => $attvalue \n"; }} }}

function endElement($parser, $elementname) {function endElement($parser, $elementname) { list($namespaceURI,$localName)= split("@",$elementname);list($namespaceURI,$localName)= split("@",$elementname); if (! $localName) {if (! $localName) { $localName = $namespaceURI;$localName = $namespaceURI; $namespaceURI = "";$namespaceURI = ""; }} print "* End Element: $localName".print "* End Element: $localName". ($namespaceURI ? " in $namespaceURI" : "")."\n";($namespaceURI ? " in $namespaceURI" : "")."\n"; }}}}

Page 81: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SAX: Advanced Example SAX: Advanced Example xml/xml_advanced.phpxml/xml_advanced.php

$objcSax = new cSax();$objcSax = new cSax();

$parser = xml_parser_create_ns("ISO-8859-1","@");$parser = xml_parser_create_ns("ISO-8859-1","@");

/* Disable as case is significant in XML *//* Disable as case is significant in XML */xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING,xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);false);

xml_set_object($parser, $objcSax);xml_set_object($parser, $objcSax);

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

if (($fp = fopen("xml_simple.xml", "r"))) { if (($fp = fopen("xml_simple.xml", "r"))) { while ($data = fread($fp, 4096)) {while ($data = fread($fp, 4096)) { if (! xml_parse($parser, $data, feof($fp))) {if (! xml_parse($parser, $data, feof($fp))) { $xmlError = libxml_get_last_error();$xmlError = libxml_get_last_error(); var_dump($xmlError);var_dump($xmlError);

exit;exit; }} }}}}

Page 82: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SAX: Advanced Example SAX: Advanced Example RESULTSRESULTS

* Start Element: chapter in http://www.example.com/default* Start Element: chapter in http://www.example.com/default* Start Element: title in http://www.example.com/namespace-a* Start Element: title in http://www.example.com/namespace-a* End Element: title in http://www.example.com/namespace-a* End Element: title in http://www.example.com/namespace-a* Start Element: para in http://www.example.com/default* Start Element: para in http://www.example.com/default* End Element: para in http://www.example.com/default* End Element: para in http://www.example.com/default* Start Element: section in * Start Element: section in

http://www.example.com/namespace-ahttp://www.example.com/namespace-a http://www.example.com/namespace-a@id => about http://www.example.com/namespace-a@id => about * Start Element: title in http://www.example.com/default* Start Element: title in http://www.example.com/default* End Element: title in http://www.example.com/default* End Element: title in http://www.example.com/default* Start Element: para in http://www.example.com/default* Start Element: para in http://www.example.com/default* End Element: para in http://www.example.com/default* End Element: para in http://www.example.com/default* End Element: section in http://www.example.com/namespace-a* End Element: section in http://www.example.com/namespace-a* End Element: chapter in http://www.example.com/default* End Element: chapter in http://www.example.com/default

Page 83: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReaderXMLReader Forward moving stream based parserForward moving stream based parser It is a Pull parserIt is a Pull parser Based on the C# XmlTextReader APIBased on the C# XmlTextReader API Advantages:Advantages:

Low memory footprintLow memory footprint Namespace supportNamespace support Simple APISimple API Validation supportValidation support Advanced Feature SetAdvanced Feature Set Faster ProcessingFaster Processing

Page 84: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Simple XMLReader: Simple ExampleExample

xmlreader/reader_simple.xmlxmlreader/reader_simple.xml<?xml version='1.0'?><?xml version='1.0'?><chapter xmlns:a="http://www.example.com/namespace-a"<chapter xmlns:a="http://www.example.com/namespace-a" xmlns="http://www.example.com/default">xmlns="http://www.example.com/default"> <a:title>XMLReader</a:title><a:title>XMLReader</a:title> <para><para> First ParagraphFirst Paragraph </para></para> <a:section a:id="about"><a:section a:id="about"> <title>About this Document</title><title>About this Document</title> <para><para> <!-- this is a comment --><!-- this is a comment --> <?php echo 'Hi! This is PHP version ' . phpversion(); ?><?php echo 'Hi! This is PHP version ' . phpversion(); ?> </para></para> </a:section></a:section></chapter></chapter>

Page 85: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Simple ExampleXMLReader: Simple Examplexmlreader/reader_simple.phpxmlreader/reader_simple.php

$reader = new XMLReader();$reader = new XMLReader();$reader->open('reader_simple.xml');$reader->open('reader_simple.xml');$reader->read();$reader->read();

print "xmlns Attribute value: ".$reader->getAttributeNo(0)."\n\n";print "xmlns Attribute value: ".$reader->getAttributeNo(0)."\n\n";while ($reader->read() && $reader->name != "a:title") { }while ($reader->read() && $reader->name != "a:title") { }print "Local Name for Element: ".$reader->localName."\n";print "Local Name for Element: ".$reader->localName."\n";print "Namespace URI for Element: ".$reader->namespaceURI."\n";print "Namespace URI for Element: ".$reader->namespaceURI."\n";

while($reader->read()) {while($reader->read()) { switch ($reader->nodeType) {switch ($reader->nodeType) { case XMLReader::ELEMENT:case XMLReader::ELEMENT: print "Element: ".$reader->name."\n";print "Element: ".$reader->name."\n"; if ($reader->hasAttributes && $reader-if ($reader->hasAttributes && $reader-

>moveToFirstAttribute()) {>moveToFirstAttribute()) { do {do { print " ".$reader->name."=".$reader->value."\n";print " ".$reader->name."=".$reader->value."\n"; } while($reader->moveToNextAttribute());} while($reader->moveToNextAttribute()); }} break;break; case XMLReader::PI:case XMLReader::PI: print "PI Target: ".$reader->name."\n PI Data: ".$reader->value."\n";print "PI Target: ".$reader->name."\n PI Data: ".$reader->value."\n"; }}}}

Page 86: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Simple XMLReader: Simple ExampleExample

RESULTSRESULTS

Local Name for Element: titleLocal Name for Element: titleNamespace URI for Element: Namespace URI for Element:

http://www.example.com/namespace-ahttp://www.example.com/namespace-a

Element: paraElement: paraElement: a:sectionElement: a:section a:id=abouta:id=aboutElement: titleElement: titleElement: paraElement: paraPI Target: phpPI Target: php PI Data: echo 'Hi! This is PHP version ' . PI Data: echo 'Hi! This is PHP version ' .

phpversion(); phpversion();

Page 87: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Consuming Yahoo XMLReader: Consuming Yahoo ShoppingShopping

<?xml version="1.0" encoding="ISO-8859-1"?><?xml version="1.0" encoding="ISO-8859-1"?><ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="urn:yahoo:prods" xmlns="urn:yahoo:prods" xsi:schemaLocation="urn:yahoo:prods xsi:schemaLocation="urn:yahoo:prods

http://api.shopping.yahoo.com/shoppingservice/v1/productsearch.xsd" http://api.shopping.yahoo.com/shoppingservice/v1/productsearch.xsd" totalResultsAvailable="8850" firstResultPosition="2" totalResultsAvailable="8850" firstResultPosition="2"

totalResultsReturned="2">totalResultsReturned="2"> <Result><Result> <Catalog ID="1991433722"><Catalog ID="1991433722"> <Url><![CDATA[http://shopping.yahoo.com/p:Linksys. . .2]]></Url><Url><![CDATA[http://shopping.yahoo.com/p:Linksys. . .2]]></Url> <ProductName><![CDATA[Linksys WRT5. . .r Broadband <ProductName><![CDATA[Linksys WRT5. . .r Broadband

Router]]></ProductName>Router]]></ProductName> <PriceFrom>59.99</PriceFrom><PriceFrom>59.99</PriceFrom> <PriceTo>100.00</PriceTo><PriceTo>100.00</PriceTo> <Thumbnail /><!-- child elements Url (CDATA), Height, Width --><Thumbnail /><!-- child elements Url (CDATA), Height, Width --> <Description><![CDATA[The Wireless-G . . .ces.]]></Description><Description><![CDATA[The Wireless-G . . .ces.]]></Description> <Summary><![CDATA[IEEE 802.3, ...]]></Summary><Summary><![CDATA[IEEE 802.3, ...]]></Summary> <UserRating /><!-- Rating sub elements --><UserRating /><!-- Rating sub elements --> <SpecificationList /><!-- 0+ Specification child elements --><SpecificationList /><!-- 0+ Specification child elements --> </SpecificationList></SpecificationList> </Catalog></Catalog> </Result></Result></ResultSet></ResultSet>

Page 88: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Consuming Yahoo XMLReader: Consuming Yahoo ShoppingShopping

xmlreader/rest_yahoo_shopping.phpxmlreader/rest_yahoo_shopping.phpfunction getTextValue($reader) { ... }function getTextValue($reader) { ... }function processCatalog($reader) { ... }function processCatalog($reader) { ... }function processResult($reader) { ... }function processResult($reader) { ... }

/* URL to Product Search service *//* URL to Product Search service */$url = 'http://api.shopping.yahoo.com/ShoppingService/V1/productSearch';$url = 'http://api.shopping.yahoo.com/ShoppingService/V1/productSearch';

/* The query is separate here as the terms must be encoded. *//* The query is separate here as the terms must be encoded. */$url .= '?query='.rawurlencode('linksys');$url .= '?query='.rawurlencode('linksys');

/* Complete the URL with App ID, limit to 1 result and start at second record *//* Complete the URL with App ID, limit to 1 result and start at second record */$url .= "&appid=zzz&results=2&start=2";$url .= "&appid=zzz&results=2&start=2";

$reader = new XMLReader();$reader = new XMLReader();

if (! $reader->open($url)) { print "Cannot access Webservice\n"; if (! $reader->open($url)) { print "Cannot access Webservice\n"; exit; }exit; }

while($reader->name != "Result") { $reader->read(); }while($reader->name != "Result") { $reader->read(); }do {do { processResult($reader);processResult($reader);} while($reader->next('Result'));} while($reader->next('Result'));

Page 89: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Consuming Yahoo XMLReader: Consuming Yahoo ShoppingShopping

xmlreader/rest_yahoo_shopping.phpxmlreader/rest_yahoo_shopping.phpfunction getTextValue($reader) {function getTextValue($reader) { if ($reader->nodeType != if ($reader->nodeType != XMLReader::ELEMENTXMLReader::ELEMENT || $reader- || $reader-

>isEmptyElement>isEmptyElement || ($reader->read() && $reader->nodeType == || ($reader->read() && $reader->nodeType ==

XMLReader::END_ELEMENTXMLReader::END_ELEMENT)))) return;return; $retVal = $reader->value;$retVal = $reader->value; $reader->read();$reader->read(); return $retVal;return $retVal;}}

function processResult($reader) {function processResult($reader) { $depth = $reader->depth;$depth = $reader->depth; if ($reader->isEmptyElement || ($reader->read() && if ($reader->isEmptyElement || ($reader->read() && $reader->nodeType == $reader->nodeType == XMLReader::END_ELEMENTXMLReader::END_ELEMENT)))) return;return;

while($depth < $reader->depth && $reader->name != "Catalog") while($depth < $reader->depth && $reader->name != "Catalog") { $reader->read(); };{ $reader->read(); };processCatalog($reader);processCatalog($reader);/* Read until </Result> is encountered *//* Read until </Result> is encountered */while($depth < $reader->depth) { $reader->read(); }while($depth < $reader->depth) { $reader->read(); }

}}

Page 90: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Consuming Yahoo XMLReader: Consuming Yahoo ShoppingShopping

xmlreader/rest_yahoo_shopping.phpxmlreader/rest_yahoo_shopping.phpfunction processCatalog($reader) {function processCatalog($reader) { $depth = $reader->depth;$depth = $reader->depth; print "Catalog ID".$reader->getAttribute('ID')."\n";print "Catalog ID".$reader->getAttribute('ID')."\n";

if ($reader->isEmptyElement || ($reader->read() && if ($reader->isEmptyElement || ($reader->read() && $reader->nodeType == $reader->nodeType == XMLReader::END_ELEMENTXMLReader::END_ELEMENT)))) return;return; while($depth < $reader->depth) {while($depth < $reader->depth) { switch ($reader->name) {switch ($reader->name) { case "ProductName":case "ProductName": case "PriceFrom":case "PriceFrom": case "PriceTo":case "PriceTo": case "Description":case "Description": case "Url":case "Url":

print $reader->name.": ".getTextValue($reader)."\print $reader->name.": ".getTextValue($reader)."\n";n";

}} $reader->next();$reader->next(); }}}}

Page 91: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Consuming Yahoo XMLReader: Consuming Yahoo ShoppingShopping

RESULTS (Abbreviated)RESULTS (Abbreviated)Catalog ID1990338714Catalog ID1990338714Url: http://shopping.yahoo.com/p:Linksys%20InstantUrl: http://shopping.yahoo.com/p:Linksys%20Instant

%20Broadband%20EtherFast%20Cable%2FDSL%20Broadband%20EtherFast%20Cable%2FDSL%20Router:1990338714%20Router:1990338714

ProductName: Linksys Instant Broadband EtherFast Cable/DSL ProductName: Linksys Instant Broadband EtherFast Cable/DSL RouterRouter

PriceFrom: 39.99PriceFrom: 39.99PriceTo: 72.71PriceTo: 72.71Description: <P>Linksys, a provider of networking hardware for Description: <P>Linksys, a provider of networking hardware for

the small/medium business (SMB), small office/home office the small/medium business (SMB), small office/home office (SOHO), and enterprise markets and broadband networking (SOHO), and enterprise markets and broadband networking hardware for the home, has announced the new EtherFast hardware for the home, has announced the new EtherFast Cable/DSL Router. The first in the new Instant Broadband Cable/DSL Router. The first in the new Instant Broadband series, this Linksys broadband router will enable home or office series, this Linksys broadband router will enable home or office users to connect their computers to a cable or DSL modem and users to connect their computers to a cable or DSL modem and securely share Internet access and perform networking tasks securely share Internet access and perform networking tasks such as file and printer sharing. The built-in hardware firewall such as file and printer sharing. The built-in hardware firewall gives users the security of sharing files without fear of gives users the security of sharing files without fear of intruders hacking into the network. </P>intruders hacking into the network. </P>

Page 92: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: DTD XMLReader: DTD ValidationValidation

xmlreader/validation/reader.xmlxmlreader/validation/reader.xml<!DOCTYPE chapter [<!DOCTYPE chapter [<!ELEMENT chapter (title, para, section)><!ELEMENT chapter (title, para, section)><!ELEMENT title (#PCDATA)><!ELEMENT title (#PCDATA)><!ELEMENT para ANY><!ELEMENT para ANY><!ATTLIST para name CDATA "default"><!ATTLIST para name CDATA "default"><!ELEMENT section (#PCDATA)><!ELEMENT section (#PCDATA)><!ATTLIST section id ID #REQUIRED><!ATTLIST section id ID #REQUIRED>]>]><chapter><chapter> <title>XMLReader</title><title>XMLReader</title> <para><para> First ParagraphFirst Paragraph </para></para> <section id="about"><section id="about"> <title>About this Document</title><title>About this Document</title> <para>content</para><para>content</para> </section></section></chapter></chapter>

Page 93: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: DTD XMLReader: DTD ValidationValidation

xmlreader/validation/reader.phpxmlreader/validation/reader.php$objReader = XMLReader::open('reader.xml');$objReader = XMLReader::open('reader.xml');$objReader->setParserProperty(XMLReader::VALIDATE, TRUE);$objReader->setParserProperty(XMLReader::VALIDATE, TRUE);

/* As of PHP 5.2 LIBXML Parser Options may be passed *//* As of PHP 5.2 LIBXML Parser Options may be passed */// $objReader = XMLReader::open('reader.xml', NULL, // $objReader = XMLReader::open('reader.xml', NULL,

LIBXML_DTDVALID);LIBXML_DTDVALID);

libxml_use_internal_errors(TRUE);libxml_use_internal_errors(TRUE);

while ($objReader->read()) {while ($objReader->read()) { if (if (! $objReader->isValid()! $objReader->isValid()) {) { print "NOT VALID\n";print "NOT VALID\n"; break;break; }}}}

$arErrors = libxml_get_errors();$arErrors = libxml_get_errors();foreach ($arErrors AS $xmlError) {foreach ($arErrors AS $xmlError) { print $xmlError->message;print $xmlError->message;}}

Page 94: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: DTD XMLReader: DTD ValidationValidation

RESULTSRESULTS

NOT VALIDNOT VALIDElement section was declared #PCDATA but Element section was declared #PCDATA but

contains non text nodescontains non text nodes

Page 95: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Relax NG XMLReader: Relax NG ValidationValidation

xmlreader/validation/reader.rngxmlreader/validation/reader.rng<?xml version="1.0" encoding="utf-8" ?><?xml version="1.0" encoding="utf-8" ?><element name="chapter" <element name="chapter"

xmlns="http://relaxng.org/ns/structure/1.0">xmlns="http://relaxng.org/ns/structure/1.0"> <element name="title"><element name="title"> <text/><text/> </element></element> <element name="para"><element name="para"> <text/><text/> </element></element> <element name="section"><element name="section"> <attribute name="id" /><attribute name="id" /> <text/><text/> </element></element></element></element>

Page 96: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Relax NG XMLReader: Relax NG ValidationValidation

xmlreader/validation/reader-rng.phpxmlreader/validation/reader-rng.php$objReader = XMLReader::open('reader.xml');$objReader = XMLReader::open('reader.xml');$objReader->setRelaxNGSchema('reader.rng');$objReader->setRelaxNGSchema('reader.rng');

libxml_use_internal_errors(TRUE);libxml_use_internal_errors(TRUE);

while ($objReader->read()) {while ($objReader->read()) { if (if (! $objReader->isValid()! $objReader->isValid()) {) { print "NOT VALID\n";print "NOT VALID\n"; break;break; }}}}

$arErrors = libxml_get_errors();$arErrors = libxml_get_errors();foreach ($arErrors AS $xmlError) {foreach ($arErrors AS $xmlError) { print $xmlError->message;print $xmlError->message;}}

Page 97: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLReader: Relax NG XMLReader: Relax NG ValidationValidation RESULTSRESULTS

NOT VALIDNOT VALIDDid not expect element title thereDid not expect element title there

Page 98: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSLXSL Used to transform XML dataUsed to transform XML data XSLT based on XPathXSLT based on XPath Works with DOM and SimpleXML, although Works with DOM and SimpleXML, although

the DOM extension is required.the DOM extension is required. Provides the capability of calling PHP Provides the capability of calling PHP

functions during a transformationfunctions during a transformation DOM nodes may be returned from PHP DOM nodes may be returned from PHP

functionsfunctions The LIBXML_NOCDATA and LIBXML_NOENT The LIBXML_NOCDATA and LIBXML_NOENT

constants are your friends.constants are your friends. libxslt 1.1.5+ is recommended to avoid libxslt 1.1.5+ is recommended to avoid

problems when using xsl:keyproblems when using xsl:key

Page 99: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSL: XML Input Data XSL: XML Input Data xsl/sites.xmlxsl/sites.xml

<?xml version="1.0"?><?xml version="1.0"?><sites><sites> <site xml:id="php-gen"><site xml:id="php-gen"> <name>PHP General</name><name>PHP General</name> <url>http://news.php.net/group.php?<url>http://news.php.net/group.php?

group=php.general&amp;format=rss</url>group=php.general&amp;format=rss</url> </site></site> <site xml:id="php-pear"><site xml:id="php-pear"> <name>PHP Pear Dev</name><name>PHP Pear Dev</name> <url>http://news.php.net/group.php?<url>http://news.php.net/group.php?

group=php.pear.dev&amp;format=rss</url>group=php.pear.dev&amp;format=rss</url> </site></site> <site xml:id="php-planet"><site xml:id="php-planet"> <name>Planet PHP</name><name>Planet PHP</name> <url>http://www.planet-php.org/rss/</url><url>http://www.planet-php.org/rss/</url> </site></site></sites></sites>

Page 100: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSL: Simple XSL: Simple TransformationTransformation

xsl/simple_stylesheet.xslxsl/simple_stylesheet.xsl<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/> <xsl:template match="/"> <html> <body> <xsl:apply-templates select="/sites/site"/> </body> </html> </xsl:template>

<xsl:template match="/sites/site"> <p><xsl:value-of select="./name"/> : <xsl:value-of select="./url" disable-output-escaping="yes"/></p> </xsl:template></xsl:stylesheet>

Page 101: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSL: Simple XSL: Simple TransformationTransformation

xsl/simple_stylesheet.phpxsl/simple_stylesheet.php

/* Load Stylesheet */$stylesheet = new DOMDocument();$stylesheet->load('simple_stylesheet.xsl');

/* Create XSL Processor */$proc = new xsltprocessor();$proc->importStylesheet($stylesheet);

/* Load XML Data */$dom = new DOMDocument();$dom->load('sites.xml');

print $proc->transformToXML($dom);

Page 102: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSL: Simple XSL: Simple TransformationTransformation

RESULTSRESULTS

<html> <body> <p>PHP General : http://news.php.net/group.php?group=php.general&format=rss</p> <p>PHP Pear Dev : http://news.php.net/group.php?group=php.pear.dev&format=rss</p> <p>Planet PHP : http://www.planet-php.org/rss/</p> </body></html>

Page 103: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSL: Advanced XSL: Advanced TransformationTransformationxsl/advanced_stylesheet.phpxsl/advanced_stylesheet.phpfunction initReader($url) {

$GLOBALS['reader'] = new XMLReader(); if ($GLOBALS['reader']->open($url)) { while ($GLOBALS['reader']->read() && $GLOBALS['reader']->name != 'item') { }

if ($GLOBALS['reader']->name == 'item') return 1; } $GLOBALS['reader'] = NULL; return 0;}

function readNextItem() { if ($GLOBALS['reader'] == NULL) return NULL; if ($GLOBALS['beingProc']) $GLOBALS['reader']->next('item'); else $GLOBALS['beingProc'] = TRUE; if ($GLOBALS['reader']->name == 'item') return $GLOBALS['reader']->expand(); return NULL;}

Page 104: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSL: Advanced XSL: Advanced TransformationTransformationxsl/advanced_stylesheet.phpxsl/advanced_stylesheet.php$beingProc = FALSE;

$reader = NULL;

/* Load Stylesheet */$stylesheet = new DOMDocument();$stylesheet->load('advanced_stylesheet.xsl');

/* Create XSL Processor */$proc = new xsltprocessor();$proc->importStylesheet($stylesheet);

/* Load XML Data */$dom = new DOMDocument();$dom->load('sites.xml');

$proc->setParameter(NULL, 'siteid', 'php-gen');$proc->registerPHPFunctions('initReader');$proc->registerPHPFunctions('readNextItem');print $proc->transformToXML($dom);/* END */

Page 105: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSL: Advanced XSL: Advanced TransformationTransformationxsl/advanced_stylesheet.xslxsl/advanced_stylesheet.xsl<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" version="1.0"> <xsl:output method="html"/> <xsl:param name="siteid" select="0" />

<xsl:template match="/"> <html><body> <xsl:apply-templates select="id($siteid)"/> </body></html> </xsl:template>

<xsl:template match="/sites/site"> <xsl:variable name="itemnum" select="php:functionString('initReader', ./url)" /> <xsl:if test="number($itemnum) > 0"> <xsl:call-template name="itemproc" /> </xsl:if> </xsl:template>

Page 106: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSL: Advanced XSL: Advanced TransformationTransformationxsl/advanced_stylesheet.xslxsl/advanced_stylesheet.xsl

<xsl:template match="item"> <p> Title: <b><xsl:value-of select="./title" /></b><br/><br/> URL: <xsl:value-of select="./link" /><br/> Published: <xsl:value-of select="./pubDate" /><br/> </p> </xsl:template>

<xsl:template name="itemproc"> <xsl:variable name="nodeset" select="php:functionString('readNextItem')" /> <xsl:if test="boolean($nodeset)"> <xsl:apply-templates select="$nodeset"/> <xsl:call-template name="itemproc" /> </xsl:if> </xsl:template>

</xsl:stylesheet>

Page 107: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XSL: Advanced XSL: Advanced TransformationTransformation

Results viewed through a browserResults viewed through a browserxsl/advanced_stylesheet.htmlxsl/advanced_stylesheet.html

Title: Re: Spreadsheet Writer

URL: http://news.php.net/php.general/241446Published: Thu, 07 Sep 2006 13:52:09 –0400

Title: Re: Spreadsheet Writer

URL: http://news.php.net/php.general/241447Published: Thu, 07 Sep 2006 13:52:09 -0400

Title: Re: Spreadsheet Writer

URL: http://news.php.net/php.general/241448Published: Thu, 07 Sep 2006 13:52:09 -0400

Page 108: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLWriterXMLWriter

Lightweight and forward-only API for Lightweight and forward-only API for generating well formed XMLgenerating well formed XML

Automatically escapes dataAutomatically escapes data Works with PHP 4.3+ available at Works with PHP 4.3+ available at

http://pecl.php.net/package/xmlwriterhttp://pecl.php.net/package/xmlwriter Object Oriented API available for PHP Object Oriented API available for PHP

5+5+ Part of core PHP distribution since PHP Part of core PHP distribution since PHP

5.1.25.1.2

Page 109: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLWriter: Simple XMLWriter: Simple ExampleExample

xmlwriter/simple.phpxmlwriter/simple.php<?php<?php$xw = new XMLWriter();$xw = new XMLWriter();$xw->openMemory();$xw->openMemory();

/* Turn on indenting to make output look pretty and set string /* Turn on indenting to make output look pretty and set string used for indenting as teh default space is too short*/used for indenting as teh default space is too short*/$xw->setIndent(TRUE);$xw->setIndent(TRUE);$xw->setIndentString(' ');$xw->setIndentString(' ');

/* Write out the optional XML declaration only specifying version *//* Write out the optional XML declaration only specifying version */$xw->startDocument('1.0');$xw->startDocument('1.0');

/* Create the opening document element, which is namespaced *//* Create the opening document element, which is namespaced */$xw->startElementNs(NULL, "chapter", $xw->startElementNs(NULL, "chapter",

"http://www.example.com/default");"http://www.example.com/default");

/* Write out an xml namespace declaration that is used later in the /* Write out an xml namespace declaration that is used later in the document */document */

$res = $xw->writeAttribute('xmlns:a', $res = $xw->writeAttribute('xmlns:a', 'http://www.example.com/namespace-a');'http://www.example.com/namespace-a');

/* Write complete elements with text content *//* Write complete elements with text content */$xw->writeElement('a:title', 'XMLReader');$xw->writeElement('a:title', 'XMLReader');$xw->writeElement('para', 'spec chars < > & " inside para element');$xw->writeElement('para', 'spec chars < > & " inside para element');

Page 110: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLWriter: Simple XMLWriter: Simple ExampleExample

xmlwriter/simple.phpxmlwriter/simple.php/* start an element and add an attribute to it *//* start an element and add an attribute to it */$xw->startElement('a:section');$xw->startElement('a:section');$xw->writeAttribute('a:id', 'about');$xw->writeAttribute('a:id', 'about');

/* Write out an element with special characters *//* Write out an element with special characters */$xw->writeElement('title', 'Pro PHP XML & Webservices');$xw->writeElement('title', 'Pro PHP XML & Webservices');

$xw->startElement('para'); /* This opens the para element */$xw->startElement('para'); /* This opens the para element */

$xw->writeComment("this is a comment");$xw->writeComment("this is a comment");$xw->text(" ");$xw->text(" ");$xw->writePi("php", "echo 'Hi! This is PHP version ' . phpversion(); ");$xw->writePi("php", "echo 'Hi! This is PHP version ' . phpversion(); ");$xw->text("\n ");$xw->text("\n ");

$xw->endElement(); /* This will close the open para element */$xw->endElement(); /* This will close the open para element */

$xw->endDocument();$xw->endDocument();

/* Flush and clear the buffer *//* Flush and clear the buffer */echo $xw->flush(true);echo $xw->flush(true);?>?>

Page 111: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLWriter: Simple XMLWriter: Simple ExampleExample

xmlwriter/simple.phpxmlwriter/simple.php/* start an element and add an attribute to it *//* start an element and add an attribute to it */$xw->startElement('a:section');$xw->startElement('a:section');$xw->writeAttribute('a:id', 'about');$xw->writeAttribute('a:id', 'about');

/* Write out an element with special characters *//* Write out an element with special characters */$xw->writeElement('title', 'Pro PHP XML & Webservices');$xw->writeElement('title', 'Pro PHP XML & Webservices');

$xw->startElement('para'); /* This opens the para element */$xw->startElement('para'); /* This opens the para element */

$xw->writeComment("this is a comment");$xw->writeComment("this is a comment");$xw->text(" ");$xw->text(" ");$xw->writePi("php", "echo 'Hi! This is PHP version ' . phpversion(); $xw->writePi("php", "echo 'Hi! This is PHP version ' . phpversion();

");");$xw->text("\n ");$xw->text("\n ");

$xw->endElement(); /* This will close the open para element */$xw->endElement(); /* This will close the open para element */

$xw->endDocument();$xw->endDocument();

/* Flush and clear the buffer *//* Flush and clear the buffer */echo $xw->flush(true);echo $xw->flush(true);?>?>

Page 112: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLWriter: Creating a Rest XMLWriter: Creating a Rest ServiceService

xmlwriter/rest.php (startid and maxid)xmlwriter/rest.php (startid and maxid)<?php<?php/* If the database does not exist, then create it and populate it with some data *//* If the database does not exist, then create it and populate it with some data */if (! file_exists('xmlwriterdb')) {if (! file_exists('xmlwriterdb')) { if ($dbhandle = sqlite_open('xmlwriterdb', 0666)) {if ($dbhandle = sqlite_open('xmlwriterdb', 0666)) { sqlite_query($dbhandle, 'CREATE TABLE xmlwriter (id int, name sqlite_query($dbhandle, 'CREATE TABLE xmlwriter (id int, name

varchar(15))');varchar(15))'); for ($x=1; $x< 11; $x++) {for ($x=1; $x< 11; $x++) { sqlite_query($dbhandle, sqlite_query($dbhandle, "INSERT INTO xmlwriter VALUES (".$x.", 'Data Num: "."INSERT INTO xmlwriter VALUES (".$x.", 'Data Num: ".

$x."')");$x."')"); }} sqlite_close($dbhandle);sqlite_close($dbhandle); } } /* closes function and saves display space */} } /* closes function and saves display space */

/* Retrieve record based on id(s) *//* Retrieve record based on id(s) */function getDBData($min, $max) {function getDBData($min, $max) { $results = NULL;$results = NULL; if ($dbhandle = sqlite_open('xmlwriterdb')) {if ($dbhandle = sqlite_open('xmlwriterdb')) { $strSQL = 'SELECT id, name FROM xmlwriter where id>='.$min.' $strSQL = 'SELECT id, name FROM xmlwriter where id>='.$min.'

and id <='.$max;and id <='.$max; $query = sqlite_query($dbhandle,$strSQL);$query = sqlite_query($dbhandle,$strSQL);

return sqlite_fetch_all($query, SQLITE_ASSOC);return sqlite_fetch_all($query, SQLITE_ASSOC); } } /* closes function and saves display space */} } /* closes function and saves display space */

Page 113: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLWriter: Creating a Rest XMLWriter: Creating a Rest ServiceService

xmlwriter/rest.phpxmlwriter/rest.php/* Setup defaults *//* Setup defaults */$recid = 0;$recid = 0;$minid = 0;$minid = 0;$maxid = 0;$maxid = 0;

/* Retrieve requested record id(s) and insure $maxid is never less /* Retrieve requested record id(s) and insure $maxid is never less than $minid */than $minid */

if (! empty($_GET['startid'])) {if (! empty($_GET['startid'])) { $minid = (int) $_GET['startid'];$minid = (int) $_GET['startid']; $maxid = $minid;$maxid = $minid; if (! empty($_GET['maxid'])) {if (! empty($_GET['maxid'])) { $maxid = (int) $_GET['maxid'];$maxid = (int) $_GET['maxid']; if ($minid > $maxid) $maxid = $minid;if ($minid > $maxid) $maxid = $minid; }}}}

/* Retrieve the requested records from the database *//* Retrieve the requested records from the database */$arResults = getDBData($minid, $maxid);$arResults = getDBData($minid, $maxid);

Page 114: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLWriter: Creating a Rest XMLWriter: Creating a Rest ServiceService

xmlwriter/rest.phpxmlwriter/rest.php/* Process the resulting records if any *//* Process the resulting records if any */header('Content-Type: text/xml');header('Content-Type: text/xml');$xw = new XMLWriter();$xw = new XMLWriter();

/* Send the XML document directly to output as it is written *//* Send the XML document directly to output as it is written */$xw->openUri('php://output');$xw->openUri('php://output');

$xw->startDocument('1.0', 'UTF-8');$xw->startDocument('1.0', 'UTF-8');$xw->startElement('Results');$xw->startElement('Results');

foreach ($arResults AS $result) {foreach ($arResults AS $result) { $xw->startElement('Result');$xw->startElement('Result'); foreach ($result AS $field_name => $field_value) {foreach ($result AS $field_name => $field_value) { $xw->writeElement($field_name, $field_value); $xw->writeElement($field_name, $field_value); }} $xw->endElement();$xw->endElement(); /* Progressively send the output *//* Progressively send the output */ $xw->flush();$xw->flush();}}$xw->endDocument();$xw->endDocument();/* Flush and clear the buffer *//* Flush and clear the buffer */$xw->flush();$xw->flush();

Page 115: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

XMLWriter: Creating a Rest XMLWriter: Creating a Rest ServiceService

xmlwriter/rest.phpxmlwriter/rest.php/* Process the resulting records if any *//* Process the resulting records if any */header('Content-Type: text/xml');header('Content-Type: text/xml');$xw = new XMLWriter();$xw = new XMLWriter();

/* Send the XML document directly to output as it is written *//* Send the XML document directly to output as it is written */$xw->openUri('php://output');$xw->openUri('php://output');

$xw->startDocument('1.0', 'UTF-8');$xw->startDocument('1.0', 'UTF-8');$xw->startElement('Results');$xw->startElement('Results');

foreach ($arResults AS $result) {foreach ($arResults AS $result) { $xw->startElement('Result');$xw->startElement('Result'); foreach ($result AS $field_name => $field_value) {foreach ($result AS $field_name => $field_value) { $xw->writeElement($field_name, $field_value); $xw->writeElement($field_name, $field_value); }} $xw->endElement();$xw->endElement(); /* Progressively send the output *//* Progressively send the output */ $xw->flush();$xw->flush();}}$xw->endDocument();$xw->endDocument();/* Flush and clear the buffer *//* Flush and clear the buffer */$xw->flush();$xw->flush();

Page 116: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Tree ParsersTree Parsers

Pros:Pros: Full navigation and modification of the Full navigation and modification of the

XML documentXML document Navigating and searching are extremely Navigating and searching are extremely

fast once the tree is loaded into memoryfast once the tree is loaded into memory Cons:Cons:

Must wait until entire tree is loaded to Must wait until entire tree is loaded to begin working with the XML.begin working with the XML.

Memory intensiveMemory intensive

Page 117: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Streaming ParsersStreaming Parsers

Pros:Pros: Uses minimal memoryUses minimal memory Processing takes place immediately Processing takes place immediately

while the document is parsedwhile the document is parsed Cons:Cons:

Minimal to no navigation support Minimal to no navigation support (forward only)(forward only)

No document editing capabilitiesNo document editing capabilities

Page 118: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Raw Test DataRaw Test Data<books><books> <book id="1"><title>1</title><pages>1</pages></book><book id="1"><title>1</title><pages>1</pages></book> <book id="2"><title>2</title><pages>2</pages></book><book id="2"><title>2</title><pages>2</pages></book> <!-- Remaining book elements for a total of 200,000 --><!-- Remaining book elements for a total of 200,000 --></books></books>

Memory Usage:Memory Usage:

DOMDOM SimpleXMLSimpleXML ext/xmlext/xml XMLReaderXMLReader

85.6MB85.6MB 85.6MB85.6MB 26KB26KB 177KB177KB

DOMDOM SimpleXMLSimpleXML ext/xmlext/xml XMLReaderXMLReader

6.6236.623 6.5836.583 0.9300.930 0.2380.238

Using every optimization possible the following results show the time in seconds to locate the book element having id="5000".

Average Time in Seconds for Optimized Search for an Element:

Page 119: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAPSOAP An XML-based protocol for exchanging An XML-based protocol for exchanging

information between applicationsinformation between applications It allows for remote invocation of methods It allows for remote invocation of methods

in a distributed environmentin a distributed environment Uses existing transport protocols such as Uses existing transport protocols such as

HTTPHTTP Can operate with or without a Web Service Can operate with or without a Web Service

Definition Language (WSDL) documentDefinition Language (WSDL) document A W3C standard and the core component to A W3C standard and the core component to

the Web Services Interoperability the Web Services Interoperability Organization (WS-I) Basic ProfileOrganization (WS-I) Basic Profile

Page 120: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Basic WSDL SOAP: Basic WSDL StructureStructure

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"><definitions xmlns="http://schemas.xmlsoap.org/wsdl/">

<types><!-- definition of types used in WSDL --></types><types><!-- definition of types used in WSDL --></types>

<message><!-- abstract definition of the data being transmitted --<message><!-- abstract definition of the data being transmitted --></message>></message>

<portType><portType> <!-- a set of abstract operations refrring to input and output <!-- a set of abstract operations refrring to input and output

messages -->messages --> </portType></portType>

<binding><!-- concrete protocol and data format specs <binding><!-- concrete protocol and data format specs --></binding>--></binding>

<service><!-- specifies locations and bindings for a service <service><!-- specifies locations and bindings for a service --></service>--></service>

</definitions></definitions>

Page 121: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Basic Message SOAP: Basic Message StructureStructure

<?xml version="1.0"?><?xml version="1.0"?><soap:Envelope <soap:Envelope

xmlns:soap="xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/http://schemas.xmlsoap.org/soap/envelope/">">

<soap:Header><soap:Header> <!-- Information to extend message --><!-- Information to extend message --> <!-- For example WS-Security or transaction information --><!-- For example WS-Security or transaction information --> </soap:Header></soap:Header>

<soap:Body><soap:Body> <!-- Either the message contents or soap:Fault --><!-- Either the message contents or soap:Fault --> <soap:Fault><soap:Fault> <!-- SOAP Fault structure and data --><!-- SOAP Fault structure and data --> </soap:Fault></soap:Fault> </soap:Body></soap:Body>

</soap:Envelope></soap:Envelope>

Page 122: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: The SoapClient SOAP: The SoapClient SoapClient::__construct ( mixed wsdl [, array options] )SoapClient::__construct ( mixed wsdl [, array options] )

Some SoapClient options:Some SoapClient options:

location*location* (string) Location of Soap service (string) Location of Soap service

uri*uri* (string) Target namespace for the SOAP (string) Target namespace for the SOAP serverserver

stylestyle11 (int) Binding style for message (int) Binding style for message

(SOAP_DOCUMENT or SOAP_RPC)(SOAP_DOCUMENT or SOAP_RPC)

useuse11 (int) Binding type for style(int) Binding type for style

(SOAP_ENCODED or SOAP_LITERAL)(SOAP_ENCODED or SOAP_LITERAL)

tracetrace (bool) Enable / disable request/response (bool) Enable / disable request/response tracing (default disabled)tracing (default disabled)

exceptionsexceptions (bool) Turn Soap exceptions on / off (bool) Turn Soap exceptions on / off (default on)(default on)*Required in NON-WSDL mode

1 Only used in NON-WSDL mode

Page 123: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: The SoapClient SOAP: The SoapClient SoapClient::__construct ( mixed wsdl [, array options] )SoapClient::__construct ( mixed wsdl [, array options] )

Connection and security options for SoapClient:Connection and security options for SoapClient:

loginlogin Login for HTTP authenticationLogin for HTTP authentication

passwordpassword Password for HTTP authenicationPassword for HTTP authenication

proxy_hostproxy_host Host for Proxy serverHost for Proxy server

proxy_portproxy_port Port for Proxy serverPort for Proxy server

proxy_loginproxy_login Login for Proxy serverLogin for Proxy server

proxy_passwordproxy_password Password for Proxy serverPassword for Proxy server

local_certlocal_cert Client certificate for HTTPS client Client certificate for HTTPS client authenticationauthentication

passphrasepassphrase Passphrase for client certificatePassphrase for client certificate

Page 124: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Function Query a SOAP: Function Query a WSDL WSDL

soap/google/google_get_functions.phpsoap/google/google_get_functions.php<?php<?php try{try{ /* Create the SoapClient and load the WSDL *//* Create the SoapClient and load the WSDL */ $GoogleClient = new $GoogleClient = new

SoapClient('GoogleSearch.wsdl');SoapClient('GoogleSearch.wsdl');

/* Retrieve all defined functions into an array *//* Retrieve all defined functions into an array */ $google_funcs = $GoogleClient->__getFunctions();$google_funcs = $GoogleClient->__getFunctions();

foreach($google_funcs AS $function) {foreach($google_funcs AS $function) { echo $function."\n\n";echo $function."\n\n"; }} } catch (SoapFault $e) {} catch (SoapFault $e) { var_dump($e);var_dump($e); }}?>?>

Page 125: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Function Query a SOAP: Function Query a WSDL WSDL

Google Function RESULTSGoogle Function RESULTSbase64Binarybase64Binary doGetCachedPagedoGetCachedPage(string $key, string (string $key, string

$url)$url)

stringstring doSpellingSuggestiondoSpellingSuggestion(string $key, string (string $key, string $phrase)$phrase)

GoogleSearchResultGoogleSearchResult doGoogleSearchdoGoogleSearch(string $key, (string $key, string $q, int $start, int $maxResults, boolean $filter, string $q, int $start, int $maxResults, boolean $filter, string $restrict, boolean $safeSearch, string $lr, string string $restrict, boolean $safeSearch, string $lr, string $ie, string $oe)$ie, string $oe)

$key$key refers to a Google license key, which may be refers to a Google license key, which may be obatined from:obatined from:

http://www.google.com/apis/index.htmlhttp://www.google.com/apis/index.html

Page 126: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Type Query a SOAP: Type Query a WSDL WSDL

soap/google/google_get_types.phpsoap/google/google_get_types.php<?php<?php try{try{ /* Create the SoapClient and load the WSDL *//* Create the SoapClient and load the WSDL */ $GoogleClient = new $GoogleClient = new

SoapClient('GoogleSearch.wsdl');SoapClient('GoogleSearch.wsdl');

/* Retrieve all defined types into an array *//* Retrieve all defined types into an array */ $types = $GoogleClient->__getTypes();$types = $GoogleClient->__getTypes();

foreach($ types AS $type) {foreach($ types AS $type) { echo $type."\n\n";echo $type."\n\n"; }} } catch (SoapFault $e) {} catch (SoapFault $e) { var_dump($e);var_dump($e); }}?>?>

Page 127: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Type Query a SOAP: Type Query a WSDL WSDL

Google Type RESULTSGoogle Type RESULTSstructstruct GoogleSearchResultGoogleSearchResult { { boolean documentFiltering;boolean documentFiltering; string searchComments;string searchComments; int estimatedTotalResultsCount;int estimatedTotalResultsCount; boolean estimateIsExact;boolean estimateIsExact; ResultElementArray resultElements;ResultElementArray resultElements; string searchQuery;string searchQuery; int startIndex;int startIndex; int endIndex;int endIndex; string searchTips;string searchTips; DirectoryCategoryArray DirectoryCategoryArray

directoryCategories;directoryCategories; double searchTime;double searchTime;}}

ResultElementResultElement ResultElementArrayResultElementArray[ [ ]]

DirectoryCategoryDirectoryCategory DirectoryCategoryArrayDirectoryCategoryArray[ ][ ]

struct ResultElement { string summary; string URL; string snippet; string title; string cachedSize; boolean relatedInformationPresent; string hostName; DirectoryCategory directoryCategory; string directoryTitle;}

struct DirectoryCategory { string fullViewableName; string specialEncoding;}

Page 128: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Retrieving from Google SOAP: Retrieving from Google Cache Cache

soap/google/google_cache_client.phpsoap/google/google_cache_client.php<?php<?php /* The following file holds your registered Google key *//* The following file holds your registered Google key */ require('google_key.php');require('google_key.php');

try {try { /* Create the Soap Client *//* Create the Soap Client */ $client = new $client = new

SoapClient('http://api.google.com/GoogleSearch.wsdl');SoapClient('http://api.google.com/GoogleSearch.wsdl');

$cached = $client->doGetCachedPage($key, $cached = $client->doGetCachedPage($key, 'http://www.google.com/');'http://www.google.com/');

/* display first 200 characters of cached page *//* display first 200 characters of cached page */ echo substr($cached, 0, 500);echo substr($cached, 0, 500);

} catch (SoapFault $e) {} catch (SoapFault $e) { var_dump($e);var_dump($e); }}?>?>

Page 129: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Retrieving from Google SOAP: Retrieving from Google Cache Cache RESULTSRESULTS

<meta http-equiv="Content-Type" content="text/html; <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">charset=US-ASCII">

<BASE HREF="http://www.google.com/"><table <BASE HREF="http://www.google.com/"><table border=1 width=100%><tr><td><table border=1 border=1 width=100%><tr><td><table border=1 bgcolor=#ffffff cellpadding=10 cellspacing=0 bgcolor=#ffffff cellpadding=10 cellspacing=0 width=100% color=#ffffff><tr><td><font face="" width=100% color=#ffffff><tr><td><font face="" color=black size=-1>This is <b><font color=black size=-1>This is <b><font color=#0039b6>G</font> <font color=#0039b6>G</font> <font color=#c41200>o</font> <font color=#c41200>o</font> <font color=#f3c518>o</font> <font color=#f3c518>o</font> <font color=#0039b6>g</font> <font color=#0039b6>g</font> <font color=#30a72f>l</font> <font color=#30a72f>l</font> <font color=#c41200>e</font></b>'s <a color=#c41200>e</font></b>'s <a href="http://www.google.com/help/feahref="http://www.google.com/help/fea

Page 130: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Google Search ClientSOAP: Google Search Clientsoap/google/google_search_client.phpsoap/google/google_search_client.php

<?php<?php /* The following file holds your registered Google key *//* The following file holds your registered Google key */ require('google_key.php');require('google_key.php');

/* Define search criteria *//* Define search criteria */ $search_terms = "PHP XML Web Services book";$search_terms = "PHP XML Web Services book"; $start = 0;$start = 0; $maxResults = 10;$maxResults = 10; $filter = FALSE;$filter = FALSE; $safeSearch = TRUE;$safeSearch = TRUE; $restrict = $lr = $ie = $oe = "";$restrict = $lr = $ie = $oe = "";

/* Within Try/Catch block – omitted to save space *//* Within Try/Catch block – omitted to save space */ /* Create the Soap Client *//* Create the Soap Client */ $client = new SoapClient('http://api.google.com/GoogleSearch.wsdl');$client = new SoapClient('http://api.google.com/GoogleSearch.wsdl');

$results = $client->$results = $client->doGoogleSearchdoGoogleSearch($key, $search_terms, $start, ($key, $search_terms, $start, $maxResults, $maxResults,

$filter, $restrict, $safeSearch, $filter, $restrict, $safeSearch, $lr, $ie, $oe));$lr, $ie, $oe));

var_dump($results);var_dump($results);?>?>

Page 131: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Google Search ClientSOAP: Google Search ClientRESULTSRESULTS

object(stdClass)#2 (11) {object(stdClass)#2 (11) { ["documentFiltering"] => bool(false)["documentFiltering"] => bool(false) ["searchComments"] => string(0) ""["searchComments"] => string(0) "" ["estimatedTotalResultsCount"]=> int(144000000)["estimatedTotalResultsCount"]=> int(144000000) ["estimateIsExact"] => bool(false)["estimateIsExact"] => bool(false) ["resultElements"] => array(10) {["resultElements"] => array(10) { . . . .. . . . [1] => object(stdClass)#5 (9) {[1] => object(stdClass)#5 (9) { ["summary"] => string(0) ""["summary"] => string(0) "" ["URL"]=> string(60) ["URL"]=> string(60)

"http://www.amazon.com/Pro-PHP-XML-Web-Services/dp/1590596331""http://www.amazon.com/Pro-PHP-XML-Web-Services/dp/1590596331" ["snippet"] => string(116) "Amazon.com: Pro <b>PHP XML</b> and <b>Web ["snippet"] => string(116) "Amazon.com: Pro <b>PHP XML</b> and <b>Web

Services</b> (Pro):Services</b> (Pro): <b>Books</b>: Robert Richards by Robert<br> Richards."<b>Books</b>: Robert Richards by Robert<br> Richards." ["title"] => string(91) "Amazon.com: Pro <b>PHP XML</b> and <b>Web Services</b> ["title"] => string(91) "Amazon.com: Pro <b>PHP XML</b> and <b>Web Services</b>

(Pro):(Pro): <b>Books</b>: Robert Richards"<b>Books</b>: Robert Richards" ["cachedSize"] => string(3) "111k"["cachedSize"] => string(3) "111k" ["relatedInformationPresent"] => bool(true)["relatedInformationPresent"] => bool(true) ["hostName"] => string(0) ""["hostName"] => string(0) "" ["directoryCategory"] => object(stdClass)#6 (2) {["directoryCategory"] => object(stdClass)#6 (2) { ["fullViewableName"] => string(0) ""["fullViewableName"] => string(0) "" ["specialEncoding"] => string(0) ""["specialEncoding"] => string(0) "" }} ["directoryTitle"] => string(0) ""["directoryTitle"] => string(0) "" }} . . . .. . . .}}

Page 132: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Client HeadersSOAP: Client Headerssoap/headers.phpsoap/headers.php

soapHeader::__construct ( string namespace, string name [, soapHeader::__construct ( string namespace, string name [, mixed data [, bool mustUnderstand [, mixed mixed data [, bool mustUnderstand [, mixed

actor]]] )actor]]] )

<?php<?php/* Create and authentication object with username/password *//* Create and authentication object with username/password */class authentication {class authentication { public $username;public $username; public $password;public $password;}}

$auth = new authentication();$auth = new authentication();$auth->username = 'MyUsername';$auth->username = 'MyUsername';$auth->password = 'MyPassword';$auth->password = 'MyPassword';

/* You MUST encode the object *//* You MUST encode the object */$authVar = new SoapVar($auth, SOAP_ENC_OBJECT);$authVar = new SoapVar($auth, SOAP_ENC_OBJECT);

$header = new SoapHeader('urn:ExampleAPI', "Authentication",$header = new SoapHeader('urn:ExampleAPI', "Authentication", $authVar, TRUE, SOAP_ACTOR_NEXT);$authVar, TRUE, SOAP_ACTOR_NEXT);

/* Set the new headers to use when creating SOAP messages *//* Set the new headers to use when creating SOAP messages */$sClient->__setSoapHeaders(array($header));$sClient->__setSoapHeaders(array($header));?>?>

Page 133: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Client HeadersSOAP: Client Headers

<SOAP-ENV:Envelope xmlns:ns2="urn:ExampleAPI" ..."><SOAP-ENV:Envelope xmlns:ns2="urn:ExampleAPI" ...">

<SOAP-ENV:Header><SOAP-ENV:Header>

<ns2:Authentication SOAP-ENV:mustUnderstand="1" <ns2:Authentication SOAP-ENV:mustUnderstand="1"

SOAP-ENV:actor="SOAP-ENV:actor="http://schemas.xmlsoap.org/soap/actor/nexthttp://schemas.xmlsoap.org/soap/actor/next">">

<ussername>MyUsername</username><ussername>MyUsername</username>

<password>MyPassword</password><password>MyPassword</password>

</ns2:Authentication></ns2:Authentication>

</SOAP-ENV:Header></SOAP-ENV:Header>

..........

Page 134: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Client Request SOAP: Client Request ModificationModification

soap/google/request_modification.phpsoap/google/request_modification.phprequire('google_key.php');require('google_key.php');

Class mySoapClient extends SoapClient {Class mySoapClient extends SoapClient { function function __doRequest__doRequest($request, $location, $action, $version) {($request, $location, $action, $version) { /* Load the request into a DOMDocument *//* Load the request into a DOMDocument */ $dom = new DOMDocument();$dom = new DOMDocument(); $dom->loadXML($request);$dom->loadXML($request);

/* Find the url element and set url to http://www.php.net/ *//* Find the url element and set url to http://www.php.net/ */ $nodeList = $dom->getElementsByTagName('url');$nodeList = $dom->getElementsByTagName('url'); if ($nodeList->length == 1) {if ($nodeList->length == 1) { $nodeList->item(0)->firstChild->nodeValue = $nodeList->item(0)->firstChild->nodeValue =

"http://www.php.net/";"http://www.php.net/"; }}

/* Serialize the tree and send modified request to parent method *//* Serialize the tree and send modified request to parent method */ $request = $dom->saveXML();$request = $dom->saveXML(); return parent::__doRequest($request, $location, $action, $version);return parent::__doRequest($request, $location, $action, $version); }}}}

$sClient = new $sClient = new mySoapClientmySoapClient('GoogleSearch.wsdl');('GoogleSearch.wsdl');$cached = $sClient->doGetCachedPage($key, '$cached = $sClient->doGetCachedPage($key, 'http://www.google.com/http://www.google.com/');');

echo substr($cached, 1500, 700)."\n";echo substr($cached, 1500, 700)."\n";

Page 135: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Client Request SOAP: Client Request ModificationModification

RESULTS (soap/google/request_modification.php)RESULTS (soap/google/request_modification.php)ont><br><br><center><font size=-2><i>Google is neither ont><br><br><center><font size=-2><i>Google is neither

affiliated with the authors of this page nor responsible for its affiliated with the authors of this page nor responsible for its content.</i></font></center></td></tr></table></td></trcontent.</i></font></center></td></tr></table></td></tr></table>></table>

<hr><hr><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01

Transitional//EN">Transitional//EN"><html><html><head><head> <title>PHP: Hypertext Preprocessor</title><title>PHP: Hypertext Preprocessor</title> <link rel="stylesheet" <link rel="stylesheet"

href="http://static.php.net/www.php.net/style.css" />href="http://static.php.net/www.php.net/style.css" /> <link rel="stylesheet" <link rel="stylesheet"

href="http://static.php.net/www.php.net/styles/phpnet.css" />href="http://static.php.net/www.php.net/styles/phpnet.css" /> <link rel="shortcut icon" <link rel="shortcut icon"

href="http://static.php.net/www.php.net/favicon.ico" />href="http://static.php.net/www.php.net/favicon.ico" /> <link rel="alternate" type="application/rss+xml" title="PHP: <link rel="alternate" type="application/rss+xml" title="PHP:

Hypertext Preprocessor" Hypertext Preprocessor" href="http://www.php.net/news.rss" />href="http://www.php.net/news.rss" />

<script language<script language

Page 136: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Debugging Client SOAP: Debugging Client RequestsRequests

soap/google/debug_client.phpsoap/google/debug_client.php /* Empty key so function will throw SoapFault *//* Empty key so function will throw SoapFault */$key = "";$key = "";

$client_options = array ('trace'=>1);$client_options = array ('trace'=>1);

try {try { /* Create the Soap Client with debug option *//* Create the Soap Client with debug option */ $client = new SoapClient('http://api.google.com/GoogleSearch.wsdl',$client = new SoapClient('http://api.google.com/GoogleSearch.wsdl', $client_options$client_options);); $cached = $client->doGetCachedPage($key, $cached = $client->doGetCachedPage($key,

'http://www.google.com/');'http://www.google.com/');

} catch (SoapFault $e) {} catch (SoapFault $e) { print "Last Request Headers: \n".$client-print "Last Request Headers: \n".$client-

>>__getLastRequestHeaders()__getLastRequestHeaders()."\n\n";."\n\n"; print "Last Request: \n".$client->print "Last Request: \n".$client->__getLastRequest()__getLastRequest()."\n\n";."\n\n"; print "Last Response Headers: \n".$client-print "Last Response Headers: \n".$client-

>>__getLastResponseHeaders()__getLastResponseHeaders()."\n\n";."\n\n"; print "Last Response: \n".$client->print "Last Response: \n".$client->__getLastResponse()__getLastResponse()."\n";."\n";}}

Page 137: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Debugging Client SOAP: Debugging Client RequestRequest

RESULTRESULTLast Request Headers: Last Request Headers: POST /search/beta2 HTTP/1.1POST /search/beta2 HTTP/1.1Host: api.google.comHost: api.google.comConnection: Keep-AliveConnection: Keep-AliveUser-Agent: PHP SOAP 0.1User-Agent: PHP SOAP 0.1Content-Type: text/xml; charset=utf-8Content-Type: text/xml; charset=utf-8SOAPAction: "urn:GoogleSearchAction"SOAPAction: "urn:GoogleSearchAction"Content-Length: 554Content-Length: 554

Last Request: Last Request: <?xml version="1.0" encoding="UTF-8"?><?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope <SOAP-ENV:Envelope

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:GoogleSearch" xmlns:ns1="urn:GoogleSearch" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:doGetCachedPage><key ENV:Body><ns1:doGetCachedPage><key xsi:type="xsd:string"></key><url xsi:type="xsd:string"></key><url xsi:type="xsd:string">http://www.google.com/</url></ns1:doGetCachedPaxsi:type="xsd:string">http://www.google.com/</url></ns1:doGetCachedPage></SOAP-ENV:Body></SOAP-ENV:Envelope>ge></SOAP-ENV:Body></SOAP-ENV:Envelope>

Page 138: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Debugging Client SOAP: Debugging Client RequestsRequests

RESULT ContinuedRESULT ContinuedLast Response Headers: Last Response Headers: POST /search/beta2 HTTP/1.1POST /search/beta2 HTTP/1.1Host: api.google.comHost: api.google.comConnection: Keep-AliveConnection: Keep-AliveUser-Agent: PHP SOAP 0.1User-Agent: PHP SOAP 0.1Content-Type: text/xml; charset=utf-8Content-Type: text/xml; charset=utf-8SOAPAction: "urn:GoogleSearchAction"SOAPAction: "urn:GoogleSearchAction"Content-Length: 554Content-Length: 554

Last Response: Last Response: <?xml version='1.0' encoding='UTF-8'?><?xml version='1.0' encoding='UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/1999/XMLSchema">xmlns:xsd="http://www.w3.org/1999/XMLSchema"><SOAP-ENV:Body><SOAP-ENV:Body><SOAP-ENV:Fault><SOAP-ENV:Fault> <faultcode>SOAP-ENV:Server</faultcode><faultcode>SOAP-ENV:Server</faultcode> <faultstring>Exception from service object: Invalid authorization key: </faultstring><faultstring>Exception from service object: Invalid authorization key: </faultstring> <faultactor>/search/beta2</faultactor><faultactor>/search/beta2</faultactor> <detail><detail> <stackTrace>com.google.soap.search.GoogleSearchFault: Invalid authorization key: <stackTrace>com.google.soap.search.GoogleSearchFault: Invalid authorization key: at at

com.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(QueryLimits.javcom.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(QueryLimits.java:213)a:213)

. . .</stackTrace>. . .</stackTrace> </detail></detail></SOAP-ENV:Fault></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Body></SOAP-ENV:Envelope></SOAP-ENV:Envelope>

Page 139: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Client and SOAP: Client and Document/LiteralDocument/Literal

soap/docliteral/amazonec_funcs.phpsoap/docliteral/amazonec_funcs.php<?php<?php $wsdl = $wsdl =

"http://webservices.amazon.com/AWSECommerceService/AWSECommerceSe"http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl";rvice.wsdl";

try {try { /* Create the Soap Client to an Amazon ECS Search *//* Create the Soap Client to an Amazon ECS Search */ $client = new SoapClient($wsdl);$client = new SoapClient($wsdl);

print "Functions: \n";print "Functions: \n"; $functions = $client->__getFunctions();$functions = $client->__getFunctions(); foreach($functions AS $function) {foreach($functions AS $function) { echo $function."\n";echo $function."\n"; }}

print "\nTypes: \n";print "\nTypes: \n"; $types = $client->__getTypes();$types = $client->__getTypes(); foreach($types AS $type) {foreach($types AS $type) { echo $type."\n\n";echo $type."\n\n"; }} } catch (SoapFault $e) {} catch (SoapFault $e) { var_dump($e);var_dump($e); }}?>?>

Page 140: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Client and SOAP: Client and Document/LiteralDocument/Literal

RESULTS (soap/docliteral/amazonec_ funcs.php)RESULTS (soap/docliteral/amazonec_ funcs.php)Functions: Functions: HelpResponse Help(Help $body)HelpResponse Help(Help $body) ItemSearchResponse ItemSearch(ItemSearch $body)ItemSearchResponse ItemSearch(ItemSearch $body) ItemLookupResponse ItemLookup(ItemLookup $body)ItemLookupResponse ItemLookup(ItemLookup $body) BrowseNodeLookupResponse BrowseNodeLookup(BrowseNodeLookup BrowseNodeLookupResponse BrowseNodeLookup(BrowseNodeLookup

$body)$body) … …

Types: Types: struct ItemLookup {struct ItemLookup { string string MarketplaceDomain;MarketplaceDomain; string AWSAccessKeyId;string AWSAccessKeyId; ItemLookupRequest ItemLookupRequest Shared;Shared; ItemLookupRequest ItemLookupRequest Request;Request;}}

struct struct ItemLookupResponse {ItemLookupResponse { OperationRequestOperationRequest OperationRequest;OperationRequest; Items Items;Items Items;}}

struct ItemLookupRequest {struct ItemLookupRequest { string MerchantId;string MerchantId; positiveInteger OfferPage;positiveInteger OfferPage; string ItemId;string ItemId; string SearchInsideKeywords;string SearchInsideKeywords;}}

struct Items {struct Items { Request Request;Request Request;nonNegativeInteger TotalResults;nonNegativeInteger TotalResults; nonNegativeInteger TotalPages;nonNegativeInteger TotalPages; Item Item;Item Item;}}

Page 141: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Client and SOAP: Client and Document/LiteralDocument/Literalsoap/docliteral/ amazonec.phpsoap/docliteral/ amazonec.php

$AWSAccessKeyId = '<Your AWS Access Key >;$AWSAccessKeyId = '<Your AWS Access Key >;$wsdl = $wsdl =

"http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl"http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl";";

$client = new SoapClient($wsdl);$client = new SoapClient($wsdl);

$params = new ItemLookup();$params = new ItemLookup();$params->AWSAccessKeyId = $AWSAccessKeyId$params->AWSAccessKeyId = $AWSAccessKeyId$params->Request = new ItemLookupRequest();$params->Request = new ItemLookupRequest();$params->Request->ItemId = '1590596331';$params->Request->ItemId = '1590596331';

$results = $client->ItemLookup($params);$results = $client->ItemLookup($params);var_dump($results);var_dump($results);

class ItemLookupRequest class ItemLookupRequest {{ public $ItemId;public $ItemId;}}

class ItemLookup {class ItemLookup { public $MarketplaceDomain;public $MarketplaceDomain; public $AWSAccessKeyId;public $AWSAccessKeyId; public $Request;public $Request;}}

Page 142: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Client and SOAP: Client and Document/LiteralDocument/Literal

RESULTS (soap/docliteral/ amazonec.php)RESULTS (soap/docliteral/ amazonec.php). . .. . . ["Item"]=>["Item"]=> object(stdClass)#13 (3) {object(stdClass)#13 (3) { ["ASIN"]=>string(10) "1590596331"["ASIN"]=>string(10) "1590596331" ["DetailPageURL"]=>string(173) ["DetailPageURL"]=>string(173)

"http://www.amazon.com/gp/redirect.html"http://www.amazon.com/gp/redirect.html%3FASIN=1590596331%26tag=ws%3FASIN=1590596331%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/o/ASIN/1590596331%253FSubscriptionId=0MWT9W26N2NFGGJZ33R2"1590596331%253FSubscriptionId=0MWT9W26N2NFGGJZ33R2"

["ItemAttributes"]=>["ItemAttributes"]=> object(stdClass)#14 (4) {object(stdClass)#14 (4) { ["Author"]=>string(15) "Robert Richards"["Author"]=>string(15) "Robert Richards" ["Manufacturer"]=>string(6) "Apress"["Manufacturer"]=>string(6) "Apress" ["ProductGroup"]=>string(4) "Book"["ProductGroup"]=>string(4) "Book" ["Title"]=>string(34) "Pro PHP XML and Web ["Title"]=>string(34) "Pro PHP XML and Web

Services (Pro)"Services (Pro)" }}

Page 143: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Server WSDL SOAP: Server WSDL (using (using

Document/Literal)Document/Literal) soap/server/exampleapi.wsdlsoap/server/exampleapi.wsdl<xsd:element name="getPeopleByFirstLastName"><xsd:element name="getPeopleByFirstLastName">

<xsd:complexType><xsd:complexType> <xsd:sequence><xsd:sequence> <xsd:element name="first" type="xsd:string"/><xsd:element name="first" type="xsd:string"/> <xsd:element name="last" type="xsd:string"/><xsd:element name="last" type="xsd:string"/> </xsd:sequence></xsd:sequence> </xsd:complexType></xsd:complexType></xsd:element></xsd:element>

<xsd:complexType name="Person"><xsd:complexType name="Person"> <xsd:all><xsd:all> <xsd:element name="id" type="xsd:int"/><xsd:element name="id" type="xsd:int"/> <xsd:element name="lastName" type="xsd:string"/><xsd:element name="lastName" type="xsd:string"/> <xsd:element name="firstName" type="xsd:string"/><xsd:element name="firstName" type="xsd:string"/> </xsd:all></xsd:all></xsd:complexType></xsd:complexType>

<xsd:element name="getPeopleByFirstLastNameResponse" <xsd:element name="getPeopleByFirstLastNameResponse" type="tns:ArrayOfPerson"/>type="tns:ArrayOfPerson"/>

<message name="getPeopleByFirstLastName"><message name="getPeopleByFirstLastName"> <part name="parameters" element="tns:getPeopleByFirstLastName"/><part name="parameters" element="tns:getPeopleByFirstLastName"/></message></message><message name="getPeopleByFirstLastNameResponse"><message name="getPeopleByFirstLastNameResponse"> <part name="result" element="tns:getPeopleByFirstLastNameResponse"/><part name="result" element="tns:getPeopleByFirstLastNameResponse"/></message></message>

Page 144: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: ServerSOAP: Serversoap/server/soap_server.phpsoap/server/soap_server.php

<?php<?php/* System status - TRUE indicates normal operation / /* System status - TRUE indicates normal operation / FALSE indicates down for maintenance */FALSE indicates down for maintenance */$SYS_STATUS = TRUE;$SYS_STATUS = TRUE;

function findPeople($firstName, $lastName) {function findPeople($firstName, $lastName) { /* Initialize the Person Records *//* Initialize the Person Records */ $matching = array();$matching = array(); $people = array(array('id'=>1, 'firstName'=>'John', 'lastName'=>'Smith'), $people = array(array('id'=>1, 'firstName'=>'John', 'lastName'=>'Smith'), array('id'=>2, 'firstName'=>'Jane', 'lastName'=>'Doe'));array('id'=>2, 'firstName'=>'Jane', 'lastName'=>'Doe')); foreach($people AS $person) {foreach($people AS $person) { /* Check if match on first name *//* Check if match on first name */ if (empty($firstSearch) || preg_match('/^'.$firstSearch.'$/i', if (empty($firstSearch) || preg_match('/^'.$firstSearch.'$/i',

$person['firstName'])) {$person['firstName'])) { /* Check if match on last name *//* Check if match on last name */ if (empty($lastSearch) || preg_match('/^'.$lastSearch.'$/i', if (empty($lastSearch) || preg_match('/^'.$lastSearch.'$/i',

$person['lastName'])) {$person['lastName'])) { $matching[ ] = $person;$matching[ ] = $person; }} }} }} return $matching;return $matching;}}

Page 145: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: ServerSOAP: Serversoap/server/soap_server.phpsoap/server/soap_server.php

function getPeopleByFirstLastName($getPeopleByFirstLastName) {function getPeopleByFirstLastName($getPeopleByFirstLastName) { /* If system is down throw SOAP fault *//* If system is down throw SOAP fault */ if (isset($GLOBALS['SYS_STATUS']) && $GLOBALS['SYS_STATUS'] == if (isset($GLOBALS['SYS_STATUS']) && $GLOBALS['SYS_STATUS'] ==

FALSE) {FALSE) { $details = array("SysMessage"=>"Sys Error", "RetryInMinutes"=>60);$details = array("SysMessage"=>"Sys Error", "RetryInMinutes"=>60);

/* SoapFault::__construct ( string faultcode, string faultstring [, string faultactor [, /* SoapFault::__construct ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, SoapHeader mixed detail [, string faultname [, SoapHeader

headerfault]]]] ) */headerfault]]]] ) */ throw throw new SoapFaultnew SoapFault("SYSError", "System Unavailable", ("SYSError", "System Unavailable",

"urn:ExampleAPI","urn:ExampleAPI", $details, "sysmaint");$details, "sysmaint"); }}

$firstSearch = str_replace('*', '([a-z]*)', $getPeopleByFirstLastName->first);$firstSearch = str_replace('*', '([a-z]*)', $getPeopleByFirstLastName->first); $lastSearch = str_replace('*', '([a-z]*)', $getPeopleByFirstLastName->last);$lastSearch = str_replace('*', '([a-z]*)', $getPeopleByFirstLastName->last);

$retval = array();$retval = array(); $results = findPeople($firstSearch, $lastSearch);$results = findPeople($firstSearch, $lastSearch);

foreach($results AS $result) {foreach($results AS $result) { /* Add matching records as an encoded SoapVar *//* Add matching records as an encoded SoapVar */ $retval[] = new SoapVar($result, SOAP_ENC_ARRAY, "Person", $retval[] = new SoapVar($result, SOAP_ENC_ARRAY, "Person",

"urn:ExampleAPI");"urn:ExampleAPI"); }} return $retval; return $retval; }}

Page 146: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: ServerSOAP: Serversoap/server/soap_server.phpsoap/server/soap_server.php

/* Create the server using WSDL and specify the actor URI *//* Create the server using WSDL and specify the actor URI */$sServer = new SoapServer("exampleapi.wsdl", $sServer = new SoapServer("exampleapi.wsdl",

array('actor'=>'urn:ExampleAPI'));array('actor'=>'urn:ExampleAPI'));

/* Register the getPeopleByFirstLastName function *//* Register the getPeopleByFirstLastName function */$sServer->addFunction("getPeopleByFirstLastName");$sServer->addFunction("getPeopleByFirstLastName");

/* Handle the SOAP request *//* Handle the SOAP request */$sServer->handle();$sServer->handle();?>?>

Page 147: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Calling our ServerSOAP: Calling our Serversoap/server/soap_client.phpsoap/server/soap_client.php

<?php<?phptry {try { $sClient = new SoapClient('exampleapi.wsdl');$sClient = new SoapClient('exampleapi.wsdl');

/* Set search parameters *//* Set search parameters */ $params = array('first'=>'jo*', 'last'=>'*');$params = array('first'=>'jo*', 'last'=>'*');

/* Make request and dump response *//* Make request and dump response */ $response = $sClient-$response = $sClient-

>getPeopleByFirstLastName($params);>getPeopleByFirstLastName($params);

var_dump($response);var_dump($response);

} catch (SoapFault $e) {} catch (SoapFault $e) { /* Dump any caught SoapFault exceptions *//* Dump any caught SoapFault exceptions */ var_dump($e);var_dump($e);}}?>?>

Page 148: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Calling our ServerSOAP: Calling our ServerRESULTSRESULTS

array(1) {array(1) { [0]=>[0]=> object(stdClass)#2 (3) {object(stdClass)#2 (3) { ["id"]=>["id"]=> int(1)int(1) ["lastName"]=>["lastName"]=> string(5) "Smith"string(5) "Smith" ["firstName"]=>["firstName"]=> string(4) "John"string(4) "John" }}}}

Page 149: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

SOAP: Modifying A SOAP: Modifying A RequestRequest

$dom = DOMDocument::loadXML(file_get_contents('php://input'));$dom = DOMDocument::loadXML(file_get_contents('php://input'));$soapNS = $dom->documentElement->namespaceURI;$soapNS = $dom->documentElement->namespaceURI;

$soapXPath = new DOMXPath($doc);$soapXPath = new DOMXPath($doc);$soapXPath ->registerNamespace('wssoap', $soapNS);$soapXPath ->registerNamespace('wssoap', $soapNS);$soapXPath ->registerNamespace('wssephp', $soapXPath ->registerNamespace('wssephp', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-

1.0.xsd');1.0.xsd');

$headers = $headers = $soapXPath->query('//wssoap:Envelope/wssoap:Header/wssephp:Security');$soapXPath->query('//wssoap:Envelope/wssoap:Header/wssephp:Security');

if ($security = $headers->item(0)) {if ($security = $headers->item(0)) { $actor = $security->getAttributeNS($soapNS, 'actor');$actor = $security->getAttributeNS($soapNS, 'actor'); /* Code here first checks to make sure actor is correct for this header *//* Code here first checks to make sure actor is correct for this header */ if (/* actor is empty or actor specifies this server */) {if (/* actor is empty or actor specifies this server */) { /* Handle WS-Security and then remove Security element *//* Handle WS-Security and then remove Security element */ $security->parentElement->removeChild($security);$security->parentElement->removeChild($security); }}}}/* If Header is empty it also can be removed *//* If Header is empty it also can be removed */

/* Process request *//* Process request */$soapServer->handle($dom->saveXML());$soapServer->handle($dom->saveXML());

Page 150: Advanced XML and Web Services September 12, 2006 Robert Richards rrichards@php.net

Questions?Questions?