[Phpxd-commits] CVS: phpXD/include/parser DOMParser.php,NONE,1.1
Status: Beta
Brought to you by:
growbal
From: Thomas D. <th...@us...> - 2002-01-25 22:18:21
|
Update of /cvsroot/phpxd/phpXD/include/parser In directory usw-pr-cvs1:/tmp/cvs-serv12964/include/parser Added Files: DOMParser.php Log Message: --- NEW FILE: DOMParser.php --- <?php // phpXD - a XML DOM Implementation // // This Software and all associated files are released unter the // GNU Public License (GPL), see LICENSE for details. // // $Id: DOMParser.php,v 1.1 2002/01/25 22:18:18 thomi Exp $ /** * Parse a document. * * @package DOMParser * @author Thomas Dohmke <th...@do...> * @version $Revision: 1.1 $ */ class DOMParser { /** * The Document node. * * @private * @type Document */ var $document; /** * The current Element node which is parsed. Only valid while * parsing a XML file! * * @private * @type Node */ var $currentNode; /** * The last node which is parsed. Only valid while parsing a XML file! * * @private * @type Node */ var $lastNode; /** * A CDataSection is parsed. All strings will be collected to one * CDataSection node. Only valid while parsing a XML file! * * @private * @type boolean */ var $parseCData = false; /** * The parsed DTD string. Only valid while parsing a XML file! * * @private * @type string */ var $parsedDTD = false; /** * The parsed DTD is an internal DTD. Only valid while parsing * a XML file! * * @private * @type boolean */ var $parsedDTDInternal = false; /** * A array with the defined namespaces. * * @private * @type array */ var $namespaces = false; /** * The Constructor of the class. * * @public * @returns void */ function DOMParser() { $this->namespaces["xml"] = "http://www.w3.org/XML/1998/namespace"; $this->namespaces["xmlns"] = "http://www.w3.org/2000/xmlns/"; } /** * Loads the XML file specified by $file and creates the DOM tree. * * @public * @param $file <code>string</code> * @returns phpXD */ function parseFile($file) { if (file_exists($file)) { $content = implode("", file($file)); if (!empty($content)) { $this->document = new Document(); $parser = xml_parser_create(); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); xml_set_object($parser, $this); xml_set_element_handler($parser, "handleStartElement", "handleEndElement"); xml_set_character_data_handler($parser, "handleCharacterData"); xml_set_processing_instruction_handler($parser, "handleProcessingInstruction"); xml_set_default_handler($parser, "handleDefault"); if (!xml_parse($parser, $content, true)) { $this->displayError("XML error in file %s, line %d: %s", $file, xml_get_current_line_number($parser), xml_error_string(xml_get_error_code($parser))); } xml_parser_free($parser); return $this->document; } } else { $this->displayError("File %s could not be found or read.", $file); } } /** * The Element Start Handler for Expat. * * @private * @returns void */ function handleStartElement($parser, $name, $attributes) { if (!(strpos($name, ":") === false)) { $prefix = substr($name, 0, strpos($name, ":")); if (is_array($attributes) && !empty($attributes["xmlns:".$prefix])) { $namespace = $attributes["xmlns:".$prefix]; } else { if (is_array($this->namespaces) && !empty($this->namespaces[$prefix])) { $namespace = $this->namespaces[$prefix]; } else { $this->displayError("XML error: unknown namespace in line %d.", xml_get_current_line_number($parser)); } } $this->namespaces[$prefix] = $namespace; } if (!(strpos($name, ":") === false)) { $newChild =& $this->document->createElementNS($namespace, $name); if ($newChild == NAME_SPACE_ERR) { $this->displayError("XML error: namespace not valid in line %d.", xml_get_current_line_number($parser)); } } else { $newChild =& $this->document->createElement($name); } if (!isset($this->document->documentElement)) { $this->document->documentElement =& $newChild; $this->currentNode =& $this->document->documentElement; } else { $this->currentNode->appendChild($newChild); $this->currentNode =& $newChild; } if (is_array($attributes)) { while (list($name, $value) = each($attributes)) { if (!(strpos($name, ":") === false)) { $prefix = substr($name, 0, strpos($name, ":")); $localName = substr($name, strpos($this->nodeName, ":")+1); if ($prefix == "xmlns") { $this->namespaces[$localName] = $value; $namespace = $this->namespaces["xmlns"]; } else { if (is_array($attributes) && !empty($attributes["xmlns:".$prefix])) { $namespace = $attributes["xmlns:".$prefix]; } else { if (is_array($this->namespaces) && !empty($this->namespaces[$prefix])) { $namespace = $this->namespaces[$prefix]; } else { $this->displayError("XML error: unknown namespace". " in line %d.", xml_get_current_line_number($parser)); } } } $result = $this->currentNode->setAttributeNS($namespace, $name, $value); if ($result == NAME_SPACE_ERR) { $this->displayError("XML error: namespace not valid in line %d.", xml_get_current_line_number($parser)); } $attr =& $this->currentNode->getAttributeNode($name); $attr->specified = true; } else { $this->currentNode->setAttribute($name, $value); $attr =& $this->currentNode->getAttributeNode($name); $attr->specified = true; } } } $this->lastNode =& $this->currentNode; } /** * The Element End Handler for Expat. * * @private * @returns void */ function handleEndElement($parser, $name) { $this->currentNode =& $this->currentNode->parentNode; $this->lastNode =& $this->currentNode; } /** * The CharacterData Handler for Expat. * * @private * @returns void */ function handleCharacterData($parser, $text) { if ($this->parseCData) { if ($this->lastNode->nodeType == CDATA_SECTION_NODE) { $this->lastNode->appendData($text); } else { $this->lastNode =& $this->currentNode->appendChild( $this->document->createCDataSection($text)); } } else { $text = str_replace("\t", " ", $text); $text = str_replace("\n", " ", $text); $text = str_replace("\r", " ", $text); $text = str_replace(" ", " ", $text); $text = preg_replace("/\ +/", " ", $text); $this->lastNode =& $this->currentNode->appendChild( $this->document->createTextNode($text)); } } /** * The ProcessingInstruction Handler for Expat. * * @private * @returns void */ function handleProcessingInstruction($parser, $target, $data) { if (!isset($this->document->documentElement)) { $this->document->appendChild( $this->document->createProcessingInstruction($target, $data)); } else { $this->lastNode =& $this->currentNode->appendChild( $this->document->createProcessingInstruction( $target, $data)); } } /** * The DTD Handler. Expat has no DTD Handler callback, so this * is set by handleDefault. * * @private * @returns void */ function handleDTD($parser, $data) { $data = trim($data); if (!empty($data)) { $this->parsedDTD .= " ".$data; } if ($data == "[") { $this->parseDTDInternal = true; } if ($data == "]") { $this->parseDTDInternal = false; } if ((substr($this->parsedDTD, strlen($this->parsedDTD)-1) == ">") && !$this->parseDTDInternal) { $this->document->doctype = new DocumentType(); // this is just a hack to differ between internal and external DTDs $DTD = explode(" ", $this->parsedDTD); $this->document->doctype->name = $DTD[1]; if ($DTD[2] == "SYSTEM") { $this->document->doctype->systemId = $DTD[3]; } else { if ($DTD[2] == "PUBLIC") { $this->document->doctype->publicId = $DTD[3]; $this->document->doctype->systemId = $DTD[4]; } else { $this->document->doctype->internalSubset = $this->parsedDTD; } } xml_set_default_handler($parser, "handleDefault"); return true; } } /** * The Default Handler for Expat. * * @private * @returns void */ function handleDefault($parser, $data) { $data = trim($data); if (!(strpos($data, "<!--") === false)) { $data = str_replace("<!--", "", $data); $data = str_replace("-->", "", $data); if (!isset($this->document->documentElement)) { $this->document->appendChild( $this->document->createComment($data)); } else { $this->lastNode =& $this->currentNode->appendChild( $this->document->createComment($data)); } return true; } if ($data == "<![CDATA[") { $this->parseCData = true; return true; } if ($data == "]]>" && $this->parseCData) { $this->parseCData = false; return true; } if ($data == "<!DOCTYPE") { $this->parsedDTD .= $data; xml_set_default_handler($parser, "handleDTD"); return true; } return false; } /** * Displays errors, which occur while parsing. * * @private * @returns void */ function displayError($message) { if (func_num_args() > 1) { $arguments = func_get_args(); $command = "\$message = sprintf(\$message, "; for ( $i = 1; $i < sizeof($arguments); $i++ ) { $command .= "\$arguments[".$i."], "; } $command = eregi_replace(", $", ");", $command); eval($command); } echo "<strong>phpXD error:</strong> ".$message; exit; } } ?> |