DOMException: '.$errCode.': '.$errText.'

'); } } // ------------------------------------------------------------------------- /** * XML_Node interface * * The XML_Node interface is the primary datatype for the entire Document * Object Model. It represents a single node in the document tree. * * @package phpdomxml */ class XML_Node { /** the name of this node */ var $nodeName; /** the value of this node */ var $nodeValue; /** the type of this node */ var $nodeType; var $parentNode = null; var $childNodes = array(); var $firstChild = null; var $lastChild = null; var $previousSibling = null; var $nextSibling = null; var $attributes = null; var $ownerDocument = null; /** * XML_Node class constructor */ function XML_Node() { $this->_id = rand(); } /** * Appends the specified child node to the XML object's child list. * @param $newChild the new child to add */ function appendChild(&$newChild) { // set parent and owner $newChild->ownerDocument =& $this->ownerDocument; $newChild->parentNode =& $this; // Add child to list of childNodes $this->childNodes[] =& $newChild; // Set child's previousSibling $newChild->previousSibling =& $this->lastChild; // Set current lastChild's nextSibling to this child if (!is_null($this->lastChild)) $this->lastChild->nextSibling =& $newChild; // Now (re)set firstChild and lastChild $this->firstChild =& $this->childNodes[0]; $this->lastChild =& $newChild; return $newChild; } // appendChild function cloneNode($deep) { } // cloneNode function hasAttributes() { return !is_null($this->attributes); } // hasAttributes function hasChildNodes() { return !empty($this->childNodes); } // hasChildNodes // Inserts the node newChild before the existing child node refChild. // If refChild is null, insert newChild at the end of the list of // children. function insertBefore(&$newChild, $refChild = null) { if (is_null($refChild)) { // append to end return $this->appendChild($newChild); } // set parent and owner $newChild->ownerDocument =& $this->ownerDocument; $newChild->parentNode =& $this; // browse childNodes list and create new structure $len = count($this->childNodes); $newList = array(); for ($i = 0; $i < $len; $i++) { $child =& $this->childNodes[$i]; if ($child->_id == $refChild->_id) { if ($i == 0) { // newChild is first in list $this->firstChild =& $newChild; $newChild->previousSibling = null; } else { // get previous in list and set refs $prevChild =& $this->childNodes[$i-1]; $prevChild->nextSibling =& $newChild; $newChild->previousSibling =& $prevChild; } // insert newChild before child $newChild->nextSibling =& $child; $child->previousSibling =& $newChild; // insert in childNodes list $newList[] =& $newChild; } $newList[] =& $child; } // replace old list with new one $this->childNodes = $newList; // return inserted child return $newChild; } // insertBefore function removeChild($oldChild) { // browse childNodes list and create new structure $found = false; $len = count($this->childNodes); $newList = array(); for ($i = 0; $i < $len; $i++) { $child =& $this->childNodes[$i]; if ($child->_id == $oldChild->_id) { $found = true; // get prev & next child $prevChild =& $child->previousSibling; $nextChild =& $child->nextSibling; // reset siblings if (is_null($prevChild) && !is_null($nextChild)) { // first child in list $this->firstChild =& $nextChild; $nextChild->previousSibling = null; } else if (!is_null($prevChild) && !is_null($nextChild)) { // somewhere in middle of list $prevChild->nextSibling =& $nextChild; $nextChild->previousSibling =& $prevChild; } else if (!is_null($prevChild) && is_null($nextChild)) { // last child in list $this->lastChild =& $prevChild; $prevChild->nextSibling = null; } } else { $newList[] =& $child; } } if ($found) { // replace old list with new one $this->childNodes = $newList; // return inserted child return $oldChild; } XML_DOMException::raise(XML_NOT_FOUND_ERR, 'child could not be removed: child not found'); } // removeChild function replaceChild($newChild, $oldChild) { } // replaceChild // dummies function getElementsByTagName($tagName) { } function getElementById($id) { } function toString($pretty = false, $tabs = '') {} } // ------------------------------------------------------------------------- /** * XML_Element intrface * * Element nodes are among the most common objects in the XML document tree. * Element nodes can have attributes associated with them. * * @package phpdomxml */ class XML_Element extends XML_Node { // Constructor function XML_Element($tagName) { $this->XML_Node(); $this->nodeName = $tagName; $this->nodeType = XML_ELEMENT_NODE; } // Retrieves an attribute value by name function getAttribute($name) { return ($this->hasAttribute($name))?$this->attributes[$name]:''; } // getAttribute // return elements with specified attribute 'id' set function getElementById($id) { // is this one of the elements we're looking for? if ($this->getAttribute('id') == $id) return $this; // browse children if ($this->hasChildNodes()) foreach ($this->childNodes as $child) if ($child->getAttribute('id') == $id) return $child; return null; } // getElementById // Return elements with specified tag name function getElementsByTagName($tagName) { $elms = array(); // is this one of the elements we're looking for? if ($this->nodeName == $tagName || $tagName == '*') $elms[] = $this; // browse if ($this->hasChildNodes()) foreach ($this->childNodes as $child) $elms = array_merge($elms, $child->getElementsByTagName($tagName)); return $elms; } // getElementByTagName // Returns true when an attribute with given name exists function hasAttribute($name) { return isset($this->attributes[$name]); } // hasAttribute // Removes an attribute by name function removeAttribute($name) { unset($this->attributes[$name]); } // removeAttribute // Adds a new attribute, or changes an existing one function setAttribute($name, $value) { $this->attributes[$name] = $value; } // setAttribute function toString($pretty = false, $tabs = '') { $s = ''; if ($pretty) $s .= $tabs; $s .= '<'.$this->nodeName; // collect attributes, if any if ($this->hasAttributes()) { foreach ($this->attributes as $key => $val) $s .= ' '.$key.'="'.$val.'"'; } // collect children, if any if ($this->hasChildNodes()) { $s .= '>'; if ($pretty) $s .= "\n"; foreach ($this->childNodes as $child) $s .= $child->toString($pretty, $tabs."\t"); if ($pretty) $s .= $tabs; $s .= 'nodeName.'>'; if ($pretty) $s .= "\n"; } else { $s .= '/>'; if ($pretty) $s .= "\n"; } return $s; } // toString } // ------------------------------------------------------------------------- /** * XML_CharacterData interface * * The XML_CharacterData interface extends XML_Node with a set of attributes * and methods for accessing character data in the DOM. * * @package phpdomxml */ class XML_CharacterData extends XML_Node { var $data; var $length; // XML_CharacterData Constructor function XML_CharacterData($data) { $this->XML_Node(); $this->data = $data; $this->length = strlen($data); } // Appends the supplied string to the existing string data function appendData($data) { $this->data .= $data; $this->nodeValue = $this->data; $this->length = strlen($this->data); } // appendData // Deletes specified data. function deleteData($offset, $count) { if ($offset < 0 || $offset > $this->length) XML_DOMException::raise(INDEX_SIZE_ERR, 'offset '.$offset.' is out of range'); if ($count < 0) XML_DOMException::raise(INDEX_SIZE_ERR, 'count '.$count.' is out of range'); $this->data = substr($this->data, 0, $offset). substr($this->data, $offset+$count); $this->nodeValue = $this->data; $this->length = strlen($this->data); } // deleteData // Inserts a string at the specified offset function insertData($offset, $data) { if ($offset < 0 || $offset > $this->length) XML_DOMException::raise(INDEX_SIZE_ERR, 'offset '.$offset.' is out of range'); $this->data = substr($this->data, 0, $offset).$data. substr($this->data, $offset); $this->nodeValue = $this->data; $this->length = strlen($this->data); } // insertData // Replaces the specified number of characters with the supplied string function replaceData($offset, $count, $data) { $this->deleteData($offset, $count); $this->insertData($offset, $data); } // replaceData // Retrieves a substring of the full string from the specified range function substringData($offset, $count) { if ($offset < 0 || $offset > $this->length) XML_DOMException::raise(INDEX_SIZE_ERR, 'offset '.$offset.' is out of range'); if ($count < 0) XML_DOMException::raise(INDEX_SIZE_ERR, 'count '.$count.' is out of range'); return substr($this->data, $offset, $count); } // substringData } // ------------------------------------------------------------------------- /** * XML_Comment interface * * The content refers to all characters between the start * tags. * * @package phpdomxml */ class XML_Comment extends XML_CharacterData { // Constructor function XML_Comment($comment) { // call parent's constructor parent::XML_CharacterData($comment); $this->nodeName = '#comment'; $this->nodeValue = $comment; $this->nodeType = XML_COMMENT_NODE; } function toString($pretty = false, $tabs = '') { $s = ''; if ($pretty) $s .= $tabs; $s .= ''; if ($pretty) $s .= "\n"; return $s; } // toString } // ------------------------------------------------------------------------- /** * XML_Text interface * * XML refers to this text content as character data and distinguishes it * from markup, the tags that modify that character data. * * @package phpdomxml */ class XML_Text extends XML_CharacterData { // Constructor function XML_Text($text) { // call parent's constructor parent::XML_CharacterData($text); $this->nodeName = '#text'; $this->nodeValue = $text; $this->nodeType = XML_TEXT_NODE; } function splitText($offset) { } function toString($pretty = false, $tabs = '') { $s = ''; if ($pretty) $s .= $tabs; $s .= $this->nodeValue; if ($pretty) $s .= "\n"; return $s; } // toString } // ------------------------------------------------------------------------- /** * XML_CDATASection interface * * Every CDATA-section in an XML document transforms into the Node of the * type CDATASection in DOM. The XML_CDATASection interface inherits the * XML_CharacterData interface through the XML_Text interface. * * @package phpdomxml */ class XML_CDATASection extends XML_Text { // Constructor function XML_CDATASection($data) { $this->nodeName = '#cdata-section'; $this->nodeValue = $data; $this->nodeType = XML_CDATA_SECTION_NODE; } function toString($pretty = false, $tabs = '') { $s = ''; if ($pretty) $s .= $tabs; $s .= 'nodeValue.']]>'; if ($pretty) $s .= "\n"; return $s; } // toString } // ------------------------------------------------------------------------- /** * XML_Document interface * * The XML_Document interface represents the entire HTML or XML document. * Conceptually, it is the root of the document tree, and provides the * primary access to the document's data. * * @package phpdomxml */ class XML_Document extends XML_Node { function XML_Document() { $this->XML_Node(); $this->nodeName = '#document'; $this->nodeType = XML_DOCUMENT_NODE; } function &createCDATASection($data) { $node =& new XML_CDATASection($data); $node->ownerDocument =& $this; return $node; } // createCDATASection function &createComment($comment) { $node =& new XML_Comment($comment); $node->ownerDocument =& $this; return $node; } // createComment // Creates a new XML element with specified name function &createElement($tagName) { $node =& new XML_Element($tagName); $node->ownerDocument =& $this; return $node; } // createElement // Creates a new XML text node with specified text function &createTextNode($text) { $node =& new XML_Text($text); $node->ownerDocument =& $this; return $node; } // createTextNode // Return elements with specified tag name function getElementsByTagName($tagName) { $elms = array(); // browse foreach ($this->childNodes as $child) $elms = array_merge($elms, $child->getElementsByTagName($tagName)); // return possible list of elements return $elms; } // getElementByTagName // Return element with specified id function getElementById($id) { // browse children foreach ($this->childNodes as $child) { $newChild = $child->getElementById($id); if ($newChild->getAttribute('id') == $id) return $newChild; } return null; } // End getElementById // Evalutes the specified XML object, constructs a textual // representation of the XML structure including the node, children // and attributes, and returns the result as a string. function toString($pretty = false, $tabs = '') { $s = ''; foreach ($this->childNodes as $child) $s .= $child->toString($pretty, $tabs); return $s; } // toString } // ------------------------------------------------------------------------- /** * XML class * * The XML object inherits from XML_Document and serves as access point for * your XML needs in projects. * * @package phpdomxml */ class XML extends XML_Document { // Constructor function XML($url = '') { // call parent's constructor $this->XML_Document(); // Load the referenced XML document if (!empty($url)) $this->load($url); } /** * Load an XML document from the specified URL. * * @param string $url location where the XML document recides. */ function load($url = '') { if (empty($url)) XML_DOMException::raise(XML_NO_FILE_ERR, 'No file or url specified'); if (function_exists('file_get_contents')) { $doc = @file_get_contents($url); if (!$doc || empty($doc)) XML_DOMException::raise(XML_FILE_NOT_FOUND_ERR, 'File not found or document is empty'); } else { $doc = @file($url); if (!$doc || empty($doc)) XML_DOMException::raise(XML_NOT_FOUND_ERR, 'File not found or document is empty'); $doc = implode('', $doc); } $this->parseXML($doc); } // load /** * Save an XML document to the specified file or URL. * * @param string $fileName the file name for the file to create. * @param boolean $pretty true for readable layout, false for no layout. */ function save($fileName, $pretty = false) { if (!$fp = fopen($fileName, 'w')) XML_DOMException::raise(XML_UNABLE_TO_OPEN, 'Unable to open file '.$fileName.' for writing'); if (!fwrite($fp, $this->toString($pretty))) XML_DOMException::raise(XML_UNABLE_TO_WRITE, 'Unable to open write to '.$fileName); fclose($fp); return true; } // save /** * Parses the XML text specified in the data argument. * * @param string $data the XML document to parse. */ function parseXML($data) { // Strip white space $data = preg_replace("/>\s+<", $data); $parser = new XML_Parser($this); $parser->parse($data); } // parseXML /** * Encodes the specified XML object into an XML document and sends * it to the specified URL using the POST method. * $url is of the form: (http://)www.domain.com:port/path/to/file * * @param string $url destination where to send the XML document to. */ function send($url) { // Get xml document $strXML = $this->toString(); // Get url parts if (!preg_match("/http/", $url)) $url = "http://".$url; $urlParts = parse_url($url); $host = isset($urlParts['host'])?$urlParts['host']:'localhost'; $port = isset($urlParts['port'])?$urlParts['port']:80; $path = isset($urlParts['path'])?$urlParts['path']:"/"; // Open a connection with the required host $fp = fsockopen($host, $port, $errno, $errstr); if (!$fp) XML_DOMException::raise(XML_UNABLE_TO_CONNECT, 'Unable to connect to '.$host.' at port '.$port.': ('.$errno. ') '.$errstr); // Send the xml document fputs($fp, "POST ".$path." HTTP/1.0\r\n". "Host: ".$host."\r\n". "Content-length: ".strlen($strXML)."\r\n". "Content-type: ".$this->contentType."\r\n". "Connection: close\r\n\r\n". $strXML."\r\n"); return $fp; } // send /** * Encodes the specified XML object into a XML document, sends * it to the specified URL using the POST method, downloads * the server's response and then loads it into the target. * $url is of the form: (http://)www.domain.com:port/path/to/file * * @param string $url destination where to send the XML document to. * @param object $target DOM object where the response will be received. */ function sendAndLoad($url, &$target) { // Check target type, fail on wrong type if (gettype($target) != 'object') XML_DOMException::raise(XML_TYPE_MISMATCH, "Target is of type '".gettype($target). "', but should be 'object'"); // Send the xml document if (!$fp = $this->send($url)) return false; // Recieve response $buf = ''; while (!feof($fp)) $buf .= fread($fp, 128); fclose($fp); // Filter xml out response (dump http headers) if (!preg_match("/(<.*>)/msi", $buf, $matches)) // Greedy match XML_DOMException::raise(XML_UNKNOWN_RESPONSE, 'Unidentified server response: no xml was sent'); $xmlResponse = $matches[1]; $target->parseXML($xmlResponse); return true; } // sendAndLoad } // ------------------------------------------------------------------------- /** * XML_Parser class * * The XML_Parser parses an XML document into a DOM object. * * @package phpdomxml */ class XML_Parser { var $dom = null; var $lastChild = null; var $parser = null; var $encoding = 'ISO-8859-1'; var $inText = false; var $inCData = false; var $CData = ''; var $xmlDecl = ''; var $version = null; var $docTypeDecl = ''; // Constructor function XML_Parser(&$dom) { $this->dom =& $dom; $this->lastChild =& $this->dom; } // parse raw xml document into 'this' function parse($data) { // Get xml declration from document and set in object if (preg_match("//i", $data, $matches)) { $this->xmlDecl = ""; // Get version if (preg_match("/version=\"(.*?)\"/i", $matches[1], $ver)) { $this->version = $ver[1]; } // Get encoding if (preg_match("/encoding=\"(.*?)\"/i", $matches[1], $enc)) { $this->encoding = $enc[1]; } } // Get document type decleration from document and set in object if (preg_match("//i", $data, $matches)) { $this->docTypeDecl = ""; } // try to create parser with found encoding $this->parser = @xml_parser_create($this->encoding); // if creation failed, use php's default encoding if (!is_resource($this->parser)) $this->parser = @xml_parser_create(); // set options xml_set_object($this->parser, &$this); xml_set_element_handler($this->parser, 'openHandler', 'closeHandler'); xml_set_character_data_handler($this->parser, 'cdataHandler'); xml_set_default_handler($this->parser, 'dataHandler'); xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1); // parse the raw data xml_parse($this->parser, $data); // free used memory xml_parser_free($this->parser); } // parse // tag open handler function openHandler(&$parser, $tag, $attr) { // create the element $node =& $this->dom->createElement($tag); // append node to dom structure $this->lastChild->appendChild($node); // attach attributes while (list($name, $value) = each($attr)) { $node->setAttribute($name, $value); } // next child will be added to this node $this->lastChild =& $node; } // openHandler // tag close handler function closeHandler(&$parser, $tag) { // end of multiline text node? if ($this->inText) { $this->inText = false; $node =& $this->dom->createTextNode($this->CData); $this->lastChild->appendChild($node); $this->CData = ''; } // next child will be added to this node's parent $this->lastChild =& $this->lastChild->parentNode; } // closeHandler // cdata handler function cdataHandler(&$parser, $data) { if (!$this->inCData) $this->inText = true; $this->CData .= $data; } // cdataHandler // misc data handler function dataHandler(&$parser, $data) { // determine data type $prefix = strtolower(substr($data, 0, 3)); switch ($prefix) { // xml decleration case 'dom->createComment(substr($data, 4, -3)); $this->lastChild->appendChild($node); break; // cdata section start case 'inCData = true; break; // cdata section end case ']]>': $this->inCData = false; $node =& $this->dom->createCDATASection($this->CData); $this->lastChild->appendChild($node); $this->CData = ''; break; } } // dataHandler } ?>