package2.xml0000644000175000017500000001553600000100644011751 0ustar zigozigo XML_DTD pear.php.net Parsing of DTD files and DTD validation of XML files Parsing of DTD files and DTD validation of XML files. The XML validation is done with the php sax parser, the xml extension, it does not use the domxml extension. Currently supports most of the current XML spec, including entities, elements and attributes. Some uncommon parts of the spec may still be unsupported. Tomas V.V.Cox cox cox@php.net no Stephan Schmidt schst schst@php-tools.net no Chuck Burgess ashnazg ashnazg@php.net no Igor Feghali ifeghali ifeghali@php.net yes 2009-04-27 0.5.2 0.5.0 alpha alpha BSD License - Fixed circular reference which was leaking memory - Due to PHP 4 and 5 differences in object handling, the XML Parser had to be rewritten to be PHP 4 compatible again. - Error when parsing empty XML 4.3.0 1.5.4 XML_Parser pear.php.net 1.3.1 0.5.2 0.5.0 alpha alpha 2009-04-27 BSD License - Fixed circular reference which was leaking memory - Due to PHP 4 and 5 differences in object handling, the XML Parser had to be rewritten to be PHP 4 compatible again. - Error when parsing empty XML 0.5.1 0.5.0 alpha alpha 2009-01-24 BSD License - Dropped dependency of deprecated XML_Tree - Introducing the all new XML_DTD_XmlParser - Added switch to turn folding on/off 0.5.0 0.5.0 alpha alpha 2008-08-22 BSD License - switch to BSD license - add package.xml v2 (while retaining package.xml v1) - PEAR CS cleanup 0.4.2 0.4.2 alpha alpha 2004-05-17 PHP License - fixed bug 168: underscores in element names (tuupola) - fixed bug 1118: missing parameters in calls to _errors() (schst) - fixed bug 1123: incorrect line numbers in error messages (schst) 0.4 0.4 alpha alpha 2003-09-11 PHP 3.0 Initial release as XML_DTD (previously was DTD) package.xml0000644000175000017500000001104411756337150011705 0ustar zigozigo XML_DTD Parsing of DTD files and DTD validation of XML files Parsing of DTD files and DTD validation of XML files. The XML validation is done with the php sax parser, the xml extension, it does not use the domxml extension. Currently supports most of the current XML spec, including entities, elements and attributes. Some uncommon parts of the spec may still be unsupported. cox Tomas V.V.Cox cox@php.net lead schst Stephan Schmidt schst@php-tools.net lead ashnazg Chuck Burgess ashnazg@php.net lead ifeghali Igor Feghali ifeghali@php.net lead 0.5.2 2009-04-27 BSD License alpha - Fixed circular reference which was leaking memory - Due to PHP 4 and 5 differences in object handling, the XML Parser had to be rewritten to be PHP 4 compatible again. - Error when parsing empty XML PEAR XML_Parser 0.4 2003-09-11 PHP 3.0 alpha Initial release as XML_DTD (previously was DTD) 0.4.2 2004-05-17 PHP License alpha - fixed bug 168: underscores in element names (tuupola) - fixed bug 1118: missing parameters in calls to _errors() (schst) - fixed bug 1123: incorrect line numbers in error messages (schst) 0.5.0 2008-08-22 BSD License alpha - switch to BSD license - add package.xml v2 (while retaining package.xml v1) - PEAR CS cleanup 0.5.1 2009-01-24 BSD License alpha - Dropped dependency of deprecated XML_Tree - Introducing the all new XML_DTD_XmlParser - Added switch to turn folding on/off 0.5.2 2009-04-27 BSD License alpha - Fixed circular reference which was leaking memory - Due to PHP 4 and 5 differences in object handling, the XML Parser had to be rewritten to be PHP 4 compatible again. - Error when parsing empty XML XML_DTD-0.5.2/0000755000175000017500000000000011756336752011372 5ustar zigozigoXML_DTD-0.5.2/README.txt0000644000175000017500000000024000000100644013025 0ustar zigozigoFor an example about the format of the DTD parsed tree take a look at the top comments of the DTD.php file. For usage examples take a look at: tests/test.php XML_DTD-0.5.2/DTD/0000755000175000017500000000000011756336752012005 5ustar zigozigoXML_DTD-0.5.2/DTD/XmlParser.php0000644000175000017500000001505300000100644014400 0ustar zigozigo * @copyright 2008-2009 Igor Feghali * @license http://opensource.org/licenses/bsd-license New BSD License * @version CVS: $Id: XmlParser.php,v 1.3 2009/04/28 02:01:29 ifeghali Exp $ * @link http://pear.php.net/package/XML_DTD */ /** * @uses XML_Parser */ require_once 'XML/Parser.php'; /** * XML_DTD_XmlParser * * Usage: * * * $nodes =& XML_DTD_XmlParser::factory('file.xml'); * if (PEAR::isError($nodes)) { * die($nodes->getMessage()); * } * * * @category XML * @package XML_DTD * @author Igor Feghali * @copyright 2008 Igor Feghali * @license http://opensource.org/licenses/bsd-license New BSD License * @link http://pear.php.net/package/XML_DTD */ class XML_DTD_XmlParser extends XML_Parser { var $children = array(); var $ptr = null; var $folding = true; /** * XML_DTD_XmlParser::XmlParser() * * Constructor, not to be used. Use factory() instead. * * @return void * @access public */ function XML_DTD_XmlParser() { parent::XML_Parser(); $this->ptr =& $this; } /** * XML_DTD_XmlParser::factory() * * Parses a XML file and returns its "skeleton". * * @param string $xml Path to XML file * * @return object Instance of XML_DTD_XmlElement containing root * @access public */ function factory($xml) { $p =& new XML_DTD_XmlParser(); $result = $p->setInputFile($xml); if (PEAR::isError($result)) { return $result; } $result = $p->parse(); if (PEAR::isError($result)) { return $result; } /** * Preventing the circular reference memory leak. * See: http://bugs.php.net/bug.php?id=33595 */ unset($p->_handlerObj, $p->ptr); if (count($p->children)) { return $p->children[0]; } else { return PEAR::raiseError('empty XML?'); } } /** * handle start element * * @param resource $xp xml parser resource * @param string $name name of the element * @param array $attr attributes * * @return void * @access private */ function startHandler($xp, $name, $attr) { $e =& new XML_DTD_XmlElement(); $e->name = $name; $e->attr = $attr; $e->lineno = @xml_get_current_line_number($xp); $e->colno = @xml_get_current_column_number($xp); $e->parent =& $this->ptr; $this->ptr->children[] =& $e; $this->ptr =& $e; } /** * handle end element * * @param resource $xp xml parser resource * @param string $name name of the element * * @return void * @access private */ function endHandler($xp, $name) { $tmp =& $this->ptr; $this->ptr =& $this->ptr->parent; /** * We do not need the reference to the parent object anymore. Clean it * up to prevent the circular reference memory leak. * See: http://bugs.php.net/bug.php?id=33595 */ unset($tmp->parent); } /** * handle character data * * @param resource $xp xml parser resource * @param string $cdata character data * * @return void * @access private */ function cdataHandler($xp, $cdata) { if (strlen(trim($cdata))) { $this->ptr->content = '#PCDATA'; } } } /** * XML_DTD_XmlElement * * Simplistic class to hold XML elements and its associated data * * @category XML * @package XML_DTD * @author Igor Feghali * @copyright 2008 Igor Feghali * @license http://opensource.org/licenses/bsd-license New BSD License * @link http://pear.php.net/package/XML_DTD */ class XML_DTD_XmlElement { var $name = ''; var $content = 'EMPTY'; var $attr = array(); var $children = array(); var $parent = null; var $lineno = 0; var $colno = 0; /** * XML_DTD_XmlElement::coord() * * Returns the line/column numbers of the start of a XML element. * * @return string Position of element in xml file (line:column). * @access public */ function coord() { return sprintf('%d:%d', $this->lineno, $this->colno); } /** * XML_DTD_XmlElement::getChildrenNames() * * Returns the names of the children of current XML element. * * @return array Array containing child names * @access public */ function getChildrenNames() { $return = array(); foreach ($this->children as $child) { $return[] = $child->name; } return $return; } } ?> XML_DTD-0.5.2/DTD/XmlValidator.php0000644000175000017500000002317100000100644015071 0ustar zigozigo * @author Igor Feghali * @copyright 2003-2008 Tomas Von Veschler Cox * @license http://opensource.org/licenses/bsd-license New BSD License * @version CVS: $Id: XmlValidator.php,v 1.8 2009/01/18 23:47:55 ifeghali Exp $ * @link http://pear.php.net/package/XML_DTD */ /** * @uses XML_DTD */ require_once 'XML/DTD.php'; /** * @uses XML_DTD_XmlParser */ require_once 'XML/DTD/XmlParser.php'; /** * XML_DTD_XmlValidator * * Usage: * * * $validator = XML_DTD_XmlValidator; * // This will check if the xml is well formed * // and will validate it against its DTD * if (!$validator->isValid($dtd_file, $xml_file)) { * die($validator->getMessage()); * } * * * @category XML * @package XML_DTD * @author Tomas V.V.Cox * @author Igor Feghali * @copyright 2003-2008 Tomas Von Veschler Cox * @license http://opensource.org/licenses/bsd-license New BSD License * @version Release: 0.5.2 * @link http://pear.php.net/package/XML_DTD * @todo Give better error messages :-) * @todo Implement error codes and better error reporting * @todo Add support for //XXX Missing .. (you may find them around the code) */ class XML_DTD_XmlValidator { var $dtd = array(); var $_errors = false; /** * XML_DTD_XmlValidator::isValid() * * Checks an XML file against its DTD * * @param string $dtd_file The DTD file name * @param string $xml_file The XML file * * @return bool True if the XML conforms the definition * @access public */ function isValid($dtd_file, $xml_file) { $nodes =& XML_DTD_XmlParser::factory($xml_file); if (PEAR::isError($nodes)) { $this->_errors($nodes->getMessage()); return false; } $dtd_parser =& new XML_DTD_Parser(); $dtd_parser->folding = true; $this->dtd = @$dtd_parser->parse($dtd_file); $this->_runTree($nodes); return ($this->_errors) ? false : true; } /** * XML_DTD_XmlValidator::_runTree() * * Runs recursively over the XML_Tree tree of objects * validating each of its nodes * * @param object &$node an XML_Tree_Node type object * * @return void * @access private */ function _runTree(&$node) { $this->_validateNode($node); foreach ($node->children as $child) { $this->_runTree($child); } } /** * XML_DTD_XmlValidator::_validateNode() * * Validate a XML_Tree_Node: allowed childs, allowed content * and allowed attributes * * @param object $node an XML_Tree_Node type object * * @return void * @access private */ function _validateNode($node) { $name = $node->name; $lineno = $node->coord(); if (!$this->dtd->elementIsDeclared($name)) { $this->_errors("No declaration for tag <$name> in DTD", $lineno); // We don't run over the childs of undeclared elements // contrary of what xmllint does return; } // // Children validation // $dtd_children = $this->dtd->getChildren($name); do { // There are children when no children allowed if (count($node->children) && !count($dtd_children)) { $this->_errors("No children allowed under <$name>", $lineno); break; } // Search for children names not allowed $was_error = false; $i = 0; foreach ($node->children as $child) { $child_name = $child->name; if (!in_array($child_name, $dtd_children)) { $this->_errors("<$child_name> not allowed under <$name>", $child->coord()); $was_error = true; } $i++; } // Validate the order of the children if (!$was_error && count($dtd_children)) { $children_list = implode(',', $node->getChildrenNames()); $regex = $this->dtd->getPcreRegex($name); if (!preg_match('/^'.$regex.'$/', $children_list)) { $dtd_regex = $this->dtd->getDTDRegex($name); $this->_errors("In element <$name> the children list " . "found:\n'$children_list', " . "does not conform the DTD definition: " . "'$dtd_regex'", $lineno); } } } while (false); // // Content Validation // $node_content = $node->content; $dtd_content = $this->dtd->getContent($name); if ($node_content == '#PCDATA') { if ($dtd_content == null) { $this->_errors("No content allowed for tag <$name>", $lineno); } elseif ($dtd_content == 'EMPTY') { $this->_errors("No content allowed for tag <$name />, " . "declared as 'EMPTY'", $lineno); } } // XXX Missing validate #PCDATA or ANY // // Attributes validation // $atts = $this->dtd->getAttributes($name); $node_atts = $node->attr; foreach ($atts as $attname => $attvalue) { $opts = $attvalue['opts']; $default = $attvalue['defaults']; if ($default == '#REQUIRED' && !isset($node_atts[$attname])) { $this->_errors("Missing required '$attname' attribute in <$name>", $lineno); } // FIXME: make case insensitive comparison if ($default == '#FIXED') { if (isset($node_atts[$attname]) && $node_atts[$attname] != $attvalue['fixed_value'] ) { $this->_errors("The value '{$node_atts[$attname]}' " . "for attribute '$attname' " . "in <$name> can only be " . "'{$attvalue['fixed_value']}'", $lineno); } } if (isset($node_atts[$attname])) { $node_val = $node_atts[$attname]; // Enumerated type validation if (is_array($opts)) { // FIXME: strtoupper() should be applied only when folding=true if (!in_array(strtoupper($node_val), $opts)) { $this->_errors("'$node_val' value " . "for attribute '$attname' under <$name> " . "can only be: '". implode(', ', $opts) . "'", $lineno); } } unset($node_atts[$attname]); } } // XXX Missing NMTOKEN, ID // If there are still attributes those are not declared in DTD if (count($node_atts) > 0) { $this->_errors("The attributes: '" . implode(', ', array_keys($node_atts)) . "' are not declared in DTD for tag <$name>", $lineno); } } /** * XML_DTD_XmlValidator::_errors() * * Stores errors * * @param string $str the error message to append * @param integer $lineno the line number where the tag is declared * * @return void * @access private */ function _errors($str, $lineno = null) { if (is_null($lineno)) { $this->_errors .= "$str\n"; } else { $this->_errors .= "line $lineno: $str\n"; } } /** * XML_DTD_XmlValidator::getMessage() * * Gets all the errors the validator found in the * conformity of the xml document * * @return string the error message */ function getMessage() { return $this->_errors; } } ?> XML_DTD-0.5.2/TODO.txt0000644000175000017500000000076200000100644012646 0ustar zigozigo- Finish tests - Add error codes and better error reporting - Compile a feature list of supported DTD commands - Read and get the DTD in XML_Validator - Create a real php script instead of "tests/test.php" - More TODO's inside the comments of .php files - Improve documentation - Add setOptions() to DTD parser and XML parser WISH: - Build a DTD Validator - Use directly sax instead of XML_Tree for partially validating instead of consuming a lot of memory creating the xml tree XML_DTD-0.5.2/tests/0000755000175000017500000000000011756337110012521 5ustar zigozigoXML_DTD-0.5.2/tests/attributes_good.xml0000644000175000017500000000041600000100644016416 0ustar zigozigo XML_DTD-0.5.2/tests/xhtml1-strict.dtd0000644000175000017500000006160000000100644015720 0ustar zigozigo %HTMLlat1; %HTMLsymbol; %HTMLspecial; XML_DTD-0.5.2/tests/nitf-3-1.dtd0000644000175000017500000022104500000100644014434 0ustar zigozigo XML_DTD-0.5.2/tests/TOTEST0000644000175000017500000000004700000100644013443 0ustar zigozigo- entities - mixed content declaration XML_DTD-0.5.2/tests/attributes.dtd0000644000175000017500000000121200000100644015354 0ustar zigozigo XML_DTD-0.5.2/tests/content_good.xml0000644000175000017500000000020700000100644015700 0ustar zigozigo im the content im the content wwwzzzzasd XML_DTD-0.5.2/tests/attributes_bad.xml0000644000175000017500000000113500000100644016213 0ustar zigozigo XML_DTD-0.5.2/tests/children_bad.xml0000644000175000017500000000217700000100644015624 0ustar zigozigo XML_DTD-0.5.2/tests/children_good.xml0000644000175000017500000000137500000100644016025 0ustar zigozigo XML_DTD-0.5.2/tests/test.php0000755000175000017500000000137400000100755014200 0ustar zigozigo#!/usr/bin/php -Cq parse($dtd)); } else { include 'XML/DTD/XmlValidator.php'; $a = new XML_DTD_XmlValidator; if (!$a->isValid($dtd, $xml)) { echo $a->getMessage(); } } function help() { echo "Usage: test.php []\n"; echo "Passing only will dump the parsed DTD Tree\n"; echo "Passing both, will try to validate with \n"; exit; } ?>XML_DTD-0.5.2/tests/nitf-fishing.xml0000644000175000017500000002201000000100644015577 0ustar zigozigo Norfolk Weather and Tide Updates Weather and Tide Updates for Norfolk A sample, fictitious NITF article

This sample article was created completely from scratch in order to illustrate various features of NITF. Parts of it are somewhat contrived, in order to illustrate as much of the DTD as possible.

By Alan Karben NITF Network News Online ScreamingMedia, Inc. Newport News, VA

Superb weather in Norfolk today. Tides coming in and out as per usual.

The tides, captured on film late yesterday. Karben

The weather was superb today in Norfolk, Virginia. Made me want to take out my boat, manufactured by the Acme Boat Company.

Tides in Norfolk are running normal today. This weeks article highlights many of this week's fishing issues, and also presents a reference table of tide times.

The Tides are High

As can be seen from the table below, the shores of Oceanview again present the brightest spots for fishermen and sandcastle-builders alike.

This is a table filled with weather data, good for fishermen living in Norfolk, Virginia.

today tide tomorrow next day third day
beach high low in out high low high low high low
Sunset 30 14 09:23 18:51 28 11 31 12 33 9
Oceanview 31 15 09:25 18:56 26 11 31 11 31 9
Shellfish 29 15 09:25 18:53 26 9 29 11 30 11

Based on these tide tables, I believe you can see that this weekend stands to be an excellent one for small- or large-scale fishing exhibitions.

Local Nooks

There are many local nooks that fishing fans may want to keep a special eye one.

  • Deer Creek: This area has proven to be a bass-lover's haven. Wilt Monthaven reports that examples of bass over 30 inches long have been reeled-in by both the casual and the professional angler.
  • Fox Run: A bit more difficult, logistically, to navigate. However, the reports of Sturgeon in this area have put it on the fishing map for the first time since 1996.
  • Pheasant Hollow: If you don't mind the crowds, this old favorite has come through this year. More fish than you can shake a stick at. Or a rod at.

Happy fishing everybody!

Stewart Klometers contributed to this article.
XML_DTD-0.5.2/tests/content_bad.xml0000644000175000017500000000064200000100644015501 0ustar zigozigo I should be empty XML_DTD-0.5.2/tests/children.dtd0000644000175000017500000000065200000100644014765 0ustar zigozigo XML_DTD-0.5.2/tests/content.dtd0000644000175000017500000000024300000100644014643 0ustar zigozigo XML_DTD-0.5.2/DTD.php0000644000175000017500000003277700000100644012477 0ustar zigozigo * @author Igor Feghali * @copyright 2003-2008 Tomas Von Veschler Cox * @license http://opensource.org/licenses/bsd-license New BSD License * @version CVS: $Id: DTD.php,v 1.9 2009/01/18 23:47:55 ifeghali Exp $ * @link http://pear.php.net/package/XML_DTD */ /** * XML_DTD_Parser * * Usage: * * * // Create a new XML_DTD parser object * $dtd_parser = new XML_DTD_Parser; * // Do the parse and return a XML_DTD_Tree object * // containing the DTD tree representatio. * $dtd_tree = $dtd_parser->parse($dtd_file); * * * @category XML * @package XML_DTD * @author Tomas V.V.Cox * @author Igor Feghali * @copyright 2003-2008 Tomas V.V.Cox * @license http://opensource.org/licenses/bsd-license New BSD License * @version Release: 0.5.2 * @link http://pear.php.net/package/XML_DTD * @todo Entities: PUBLIC | SYSTEM | NDATA * @todo Tokenized types for ATTLIST */ class XML_DTD_Parser { /** * @var array */ var $dtd = array(); /** * @var boolean */ var $folding = false; /** * XML_DTD_Parser::_parseENTITIES() * * Do entities preprocessing * * @param string $str string to parse * * @return string * @access private */ function _parseENTITIES($str) { // Find all ENTITY tags if (preg_match_all('|]+)\s*>|s', $str, $m)) { $ids = array(); $repls = array(); foreach ($m[1] as $entity) { // Internal entities if ( preg_match('/^%?\s+([a-zA-Z0-9.\-]+)\s+(["\'])(.*)\2\s*$/s', $entity, $n) ) { // entity name $id = '/%' . $n[1] . ';/'; // replacement text $repl = $n[3]; $ids[] = $id; $repls[] = $repl; } else { // XXX PUBLIC | SYSTEM | NDATA trigger_error("Entity not supported"); } } // replace replacements in entities $defined_ids = $defined_repls = array(); for ($i = 0; $i < count($ids); $i++) { if ($i <> 0) { $repls[$i] = preg_replace($defined_ids, $defined_repls, $repls[$i]); // XXX Search for not previously defined entities } $defined_ids[] = $ids[$i]; $defined_repls[] = $repls[$i]; } // replace replacements in the whole DTD array_flip($ids); array_flip($repls); $str = preg_replace($ids, $repls, $str); // Check if there are still unparsed entities if (preg_match_all('/(%[^#][a-zA-Z0-9.]+;)/', $str, $o)) { foreach ($o[1] as $notparsed) { trigger_error("Entity ID: " . "'$notparsed' not recognized, skipping"); $str = preg_replace("/$notparsed/", '', $str); } } } return $str; } /** * XML_DTD_Parser::parse() * * @param string $cont it could be either a filename or a string * @param boolean $is_file if the first param is supposed to be a string * or a filename * * @return XML_DTD_Tree a XML_DTD_Tree object * @access public */ function parse($cont, $is_file = true) { if ($is_file) { $cont = file_get_contents($cont); } if ($this->folding) { $cont = strtoupper($cont); } // Remove DTD comments $cont = preg_replace('||Us', '', $cont); $cont = $this->_parseENTITIES($cont); if (preg_match_all('|]+)>|s', $cont, $m)) { foreach ($m[1] as $tag) { $fields = array(); $in = 0; $buff = ''; $tag = preg_replace('|\s+|s', ' ', $tag); // Manual split the parts of the elements // take care of netsted lists (a|(c|d)|b) for ($i = 0; $i < strlen($tag); $i++) { if ($tag{$i} == ' ' && !$in && $buff) { $fields[] = $buff; $buff = ''; continue; } if ($tag{$i} == '(') { $in++; } elseif ($tag{$i} == ')') { $in--; } $buff .= $tag{$i}; } if ($buff) { $fields[] = $buff; } // Call the element handler $elem = $fields[0]; array_shift($fields); switch ($elem) { case 'ELEMENT': $this->_ELEMENT($fields); break; case 'ATTLIST': $this->_ATTLIST($fields); break; case 'ENTITY': break; default: trigger_error("$elem not implemented yet", E_USER_WARNING); break; } } } return new XML_DTD_Tree($this->dtd); } /** * XML_DTD_Parser::_ELEMENT() * * Handles the ELEMENT parsing * * @param array $data $data[0] the element, * $data[1] the string with allowed childs * * @return void * @access private * @todo PHPCS - rename to _element for CamelCase rule */ function _ELEMENT($data) { // $data[0] the element // $data[1] the string with allowed childs $elem_name = $data[0]; $ch = str_replace(' ', '', $data[1]); // Content if ($ch{0} != '(') { $content = $ch; $children = array(); } else { // Enumerated list of childs $content = null; do { $children = preg_split('/([^#a-zA-Z0-9_.-]+)/', $ch, -1, PREG_SPLIT_NO_EMPTY); if (in_array('#PCDATA', $children)) { $content = '#PCDATA'; if (count($children) == 1) { $children = array(); break; } } $this->dtd['elements'][$elem_name]['child_validation_dtd_regex'] = $ch; // Convert the DTD regex language into PCRE regex format $reg = str_replace(',', ',?', $ch); $reg = preg_replace('/([#a-zA-Z0-9_.-]+)/', '(,?\\0)', $reg); $this->dtd['elements'][$elem_name]['child_validation_pcre_regex'] = $reg; } while (false); } // Tree of rules childs $this->dtd['elements'][$elem_name]['children'] = $children; // Either null, #PCDATA, EMPTY or ANY $this->dtd['elements'][$elem_name]['content'] = $content; } /** * XML_DTD_Parser::_ATTLIST() * * Handles the ATTLIST parsing * * @param array $data $data[0] the element name, * $data[1] string with the attributes * * @return void * @access private * @todo PHPCS - rename to _attList for CamelCase rule */ function _ATTLIST($data) { $elem = $data[0]; array_shift($data); for ($i=0; $i < count($data); $i = $i + 3) { $a = array(); $att = $data[$i]; $opts = $data[$i+1]; if ($opts{0} == '(' && $opts{strlen($opts)-1} == ')' ) { $a['opts'] = preg_split('/\||,/', preg_replace('|\s+|', '', substr($opts, 1, -1))); } else { $a['opts'] = $opts; // XXX ID is missing yet } $def = $data[$i+2]; if ($def{0} == '"' && $def{strlen($def)-1} == '"') { $def = substr($def, 1, -1); } elseif ($def == '#FIXED') { $a['fixed_value'] = substr($data[$i+3], 1, -1); //strip "s $i++; } $a['defaults'] = $def; $this->dtd['elements'][$elem]['attributes'][$att] = $a; } } } /** * XML_DTD_Tree * * DTD tree format: * * * [elements] => array( * => array( * [children] => array( * 0 => //allowed children array * ), * [child_validation_pcre_regex] => string, // The regex for validating * // the list of childs * [child_validation_dtd_regex] => string, // The DTD element declaration * [content] => string // null, #PCDATA, EMPTY or ANY * [attributes] => array( * => array( * [opts] => (array|string), // enumerated or CDATA * [defaults] => (#IMPLIED|#REQUIRED|#FIXED|value), * [fixed_value] => string // only when defaults is #FIXED * ) * ) * ) * ) * * * @category XML * @package XML_DTD * @author Tomas V.V.Cox * @copyright 2003-2008 Tomas V.V.Cox * @license http://opensource.org/licenses/bsd-license New BSD License * @version Release: 0.5.2 * @link http://pear.php.net/package/XML_DTD */ class XML_DTD_Tree { /** * XML_DTD_Tree::XML_DTD_Tree() * * The DTD tree array coming from XML_DTD_Parse->parse() * * @param array $tree DTD tree * * @access public */ function XML_DTD_Tree($tree) { $this->dtd = $tree; } /** * XML_DTD_Tree::getChildren() * * @param string $elem element * * @return array * @access public */ function getChildren($elem) { return $this->dtd['elements'][$elem]['children']; } /** * XML_DTD_Tree::getContent() * * @param string $elem element * * @return string * @access public */ function getContent($elem) { return $this->dtd['elements'][$elem]['content']; } /** * XML_DTD_Tree::getPcreRegex() * * Return the perl regular expresion used for validating * the children of a node * * @param string $elem element * * @return string * @access public */ function getPcreRegex($elem) { return $this->dtd['elements'][$elem]['child_validation_pcre_regex']; } /** * XML_DTD_Tree::getDTDRegex() * * Return the DTD element definition for $elem * * @param string $elem element * * @return string * @access public */ function getDTDRegex($elem) { return $this->dtd['elements'][$elem]['child_validation_dtd_regex']; } /** * XML_DTD_Tree::getAttributes() * * @param string $elem element * * @return array * @access public */ function getAttributes($elem) { if (!isset($this->dtd['elements'][$elem]['attributes'])) { return array(); } return $this->dtd['elements'][$elem]['attributes']; } /** * XML_DTD_Tree::elementIsDeclared() * * @param string $elem element * * @return bool * @access public */ function elementIsDeclared($elem) { return isset($this->dtd['elements'][$elem]); } } ?>