[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;
}
}
?>
|