Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Moving DTD to XML_DTD

git-svn-id: http://svn.php.net/repository/pear/packages/XML_DTD/trunk@140078 c90b9560-bf6c-de11-be94-00142212c4b1
  • Loading branch information...
commit 1a1d9c43c5963813bd719bf1f683d162f015b653 1 parent 5c38c8e
@tvvcox tvvcox authored
View
268 DTD.php
@@ -0,0 +1,268 @@
+<?php
+//
+// +----------------------------------------------------------------------+
+// | DTD class |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2003 Tomas Von Veschler Cox |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Authors: Tomas V.V.Cox <cox@idecnet.com> |
+// | |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+/*
+DTD tree format:
+
+[elements] => array(
+ <tag name> => array(
+ [children] => array(
+ 0 => <child name> //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(
+ <att name> => array(
+ [opts] => (array|string), // enumerated or CDATA
+ [defaults] => (#IMPLIED|#REQUIRED|#FIXED|value),
+ [fixed_value] => string // only when defaults is #FIXED
+ )
+ )
+ )
+)
+
+TODO:
+ - Entities: PUBLIC | SYSTEM | NDATA
+ - Tokenized types for ATTLIST
+ - others ...
+*/
+
+/*
+Usage:
+
+// Create a new XML_DTD parser object
+$dtd_parser = new XML_DTD_Parser;
+// Do the parse and return a DTD_Tree object
+// containing the above mentioned tree.
+$dtd_tree = $dtd_parser->parse($dtd_file);
+
+*/
+class XML_DTD_Parser
+{
+ var $dtd = array();
+
+ function parseENTITIES($str)
+ {
+ // Find all ENTITY tags
+ if (preg_match_all('|<!ENTITY\s+([^>]+)\s*>|s', $str, $m)) {
+ $ids = array();
+ $repls = array();
+ foreach ($m[1] as $entity) {
+ // Internal entities
+ if (preg_match('|^%?\s+([a-zA-Z0-9.]+)\s+"([^"]*)"\s*$|s', $entity, $n)) {
+ // entity name
+ $id = '/%' . $n[1] . ';/';
+ // replacement text
+ $repl = $n[2];
+ $ids[] = $id;
+ $repls[] = $repl;
+ // XXX PUBLIC | SYSTEM | NDATA
+ } else {
+ trigger_error("Entity <!ENTITY $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;
+ }
+
+ function parse($file)
+ {
+ $cont = file_get_contents($file);
+ // 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);
+ }
+
+
+ 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();
+ // Enumerated list of childs
+ } else {
+ $content = null;
+ do {
+ $children = preg_split('/([^#a-zA-Z0-9.]+)/', $ch, -1, PREG_SPLIT_NO_EMPTY);
+ if (($i = array_search('#PCDATA', $children)) !== false) {
+ $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;
+ }
+
+ 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;
+ }
+ }
+}
+
+class XML_DTD_Tree
+{
+ function XML_DTD_Tree($tree)
+ {
+ $this->dtd = $tree;
+ }
+
+ function getChildren($elem)
+ {
+ return $this->dtd['elements'][$elem]['children'];
+ }
+
+ function getContent($elem)
+ {
+ return $this->dtd['elements'][$elem]['content'];
+ }
+
+ function getPcreRegex($elem)
+ {
+ return $this->dtd['elements'][$elem]['child_validation_pcre_regex'];
+ }
+
+ function getDTDRegex($elem)
+ {
+ return $this->dtd['elements'][$elem]['child_validation_dtd_regex'];
+ }
+
+ function getAttributes($elem)
+ {
+ if (!isset($this->dtd['elements'][$elem]['attributes'])) {
+ return array();
+ }
+ return $this->dtd['elements'][$elem]['attributes'];
+ }
+
+ function elementIsDeclared($elem)
+ {
+ return isset($this->dtd['elements'][$elem]);
+ }
+}
+?>
View
190 DTD/XmlValidator.php
@@ -0,0 +1,190 @@
+<?php
+//
+// +----------------------------------------------------------------------+
+// | DTD_XML_Validator class |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2003 Tomas Von Veschler Cox |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Authors: Tomas V.V.Cox <cox@idecnet.com> |
+// | |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+//
+// TODO:
+// - Give better error messages :-)
+// - Add the line number in the error message
+// - Implement error codes and better error reporting
+// - Add support for //XXX Missing .. (you may find them arround the code)
+//
+
+
+/*
+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());
+}
+
+*/
+require_once 'XML/DTD.php';
+require_once 'XML/Tree.php';
+
+class XML_DTD_XmlValidator
+{
+
+ var $dtd = array();
+ var $errors = false;
+
+ function isValid($dtd_file, $xml_file)
+ {
+ $xml_tree =& new XML_Tree($xml_file);
+ $nodes = $xml_tree->getTreeFromFile();
+ if (PEAR::isError($nodes)) {
+ $this->errors($nodes->getMessage());
+ return false;
+ }
+ $dtd_parser =& new XML_DTD_Parser;
+ $this->dtd = @$dtd_parser->parse($dtd_file);
+ $this->runTree($nodes);
+ return ($this->errors) ? false : true;
+ }
+
+ function runTree(&$node)
+ {
+ //echo "Parsing node: $node->name\n";
+ $children = array();
+ // Get the list of children under the parent node
+ foreach ($node->children as $child) {
+ // a text node
+ if (!strlen($child->name)) {
+ $children[] = '#PCDATA';
+ } else {
+ $children[] = $child->name;
+ }
+ }
+ $this->validateNode($node, $children);
+ // Recursively run the tree
+ foreach ($node->children as $child) {
+ if (strlen($child->name)) {
+ $this->runTree($child);
+ }
+ }
+ }
+
+ function validateNode($node, $children)
+ {
+ $name = $node->name;
+ if (!$this->dtd->elementIsDeclared($name)) {
+ $this->errors("No declaration for tag <$name> in DTD");
+ // 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($children) && !count($dtd_children)) {
+ $this->errors("No children allowed under <$name>");
+ break;
+ }
+ // Search for children names not allowed
+ $was_error = false;
+ foreach ($children as $child) {
+ if (!in_array($child, $dtd_children)) {
+ $this->errors("<$child> not allowed under <$name>");
+ $was_error = true;
+ }
+ }
+ // Validate the order of the children
+ if (!$was_error && count($dtd_children)) {
+ $children_list = implode(',', $children);
+ $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'\n".
+ "does not conform the DTD definition:\n'$dtd_regex'"); //XXX DEBUG: \nreg applied: $regex");
+ }
+ }
+ } while (false);
+
+ //
+ // Content Validation
+ //
+ $node_content = $node->content;
+ $dtd_content = $this->dtd->getContent($name);
+ if (strlen($node_content)) {
+ if ($dtd_content == null) {
+ $this->errors("No content allowed for tag <$name>");
+ } elseif ($dtd_content == 'EMPTY') {
+ $this->errors("No content allowed for tag <$name />, declared as 'EMPTY'");
+ }
+ }
+ // XXX Missing validate #PCDATA or ANY
+
+ //
+ // Attributes validation
+ //
+ $atts = $this->dtd->getAttributes($name);
+ $node_atts = $node->attributes;
+ 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>");
+ }
+ 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']}'");
+ }
+ }
+ if (isset($node_atts[$attname])) {
+ $node_val = $node_atts[$attname];
+ // Enumerated type validation
+ if (is_array($opts)) {
+ if (!in_array($node_val, $opts)) {
+ $this->errors("'$node_val' value for attribute '$attname' under <$name> ".
+ "can only be: '". implode(', ', $opts) . "'");
+ }
+ }
+ 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>");
+ }
+ }
+
+ function errors($str)
+ {
+ $this->errors .= "$str\n-----\n";
+ }
+
+ function getMessage()
+ {
+ return $this->errors;
+ }
+
+}
+?>
View
6 README.txt
@@ -0,0 +1,6 @@
+For 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
+
View
13 TODO.txt
@@ -0,0 +1,13 @@
+- Finish tests
+- Add error codes and better error reporting
+- Compile a feature list of supported DTD commands
+- Read <!DOCTYPE ..> 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
+- Add API Doc comments
+
+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
View
61 package.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- do not use the "Type" attribute here, that one is only for
+ generated package.xml files -->
+<package version="1.0">
+ <name>XML_DTD</name>
+ <summary>Parsing of DTD files and DTD validation of XML files</summary>
+ <description>
+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.
+</description>
+ <license>PHP 3.0</license>
+ <maintainers>
+ <maintainer>
+ <user>cox</user>
+ <name>Tomas V.V.Cox</name>
+ <email>cox@idecnet.com</email>
+ <role>lead</role>
+ </maintainer>
+ </maintainers>
+
+ <release>
+ <version>0.3</version>
+ <date>2002-02-23</date>
+ <state>alpha</state>
+ <notes>Initial release</notes>
+ <filelist>
+ <dir name="/" baseinstalldir="XML">
+ <file role="php">DTD.php</file>
+ <file role="doc">README.txt</file>
+ <file role="doc">TODO.txt</file>
+ <dir name="DTD">
+ <file role="php">XmlValidator.php</file>
+ </dir>
+ <dir name="tests" role="test">
+ <file>TOTEST</file>
+ <file>attributes.dtd</file>
+ <file>attributes_bad.xml</file>
+ <file>attributes_good.xml</file>
+ <file>children.dtd</file>
+ <file>children_bad.xml</file>
+ <file>children_good.xml</file>
+ <file>content.dtd</file>
+ <file>content_bad.xml</file>
+ <file>content_good.xml</file>
+ <file>package-1.0</file>
+ <file>package-1.1.dtd</file>
+ <file>test.php</file>
+ </dir>
+ </dir>
+ </filelist>
+ <deps>
+ <dep type="pkg" rel="ge" version="1.0">XML_Tree</dep>
+ </deps>
+ </release>
+
+</package>
View
2  tests/TOTEST
@@ -0,0 +1,2 @@
+- entities
+- mixed content declaration
View
20 tests/attributes.dtd
@@ -0,0 +1,20 @@
+<!ELEMENT foo (string|enum)+>
+<!ELEMENT string EMPTY>
+<!ELEMENT enum EMPTY>
+<!ATTLIST string
+ att1 CDATA #IMPLIED
+ att2 CDATA #REQUIRED
+ att3 CDATA #FIXED "POST"
+ att4 CDATA "mydefault">
+<!ATTLIST enum
+ en1 (bullets|ordered|glossary) "ordered"
+ en2 (pkg|ext|php|prog|ldlib) #REQUIRED
+ en3 (has|eq|lt|le|gt|ge) #IMPLIED>
+<!ATTLIST unsupported
+ att1 ID #IMPLIED
+ att2 IDREF #IMPLIED
+ att3 IDREFS #IMPLIED
+ att4 NMTOKEN #IMPLIED
+ att5 NMTOKENS #IMPLIED>
+<!ATTLIST notdeclared
+ not CDATA #IMPLIED>
View
20 tests/attributes_bad.xml
@@ -0,0 +1,20 @@
+<foo>
+<!-- Test required att2 and with no att1 -->
+<string/>
+<!-- Test required att2 and with att1 -->
+<string att1="any" />
+<!-- Test FIXED -->
+<string att2="any" att3="should be POST" />
+<!-- Enum required n2 missing -->
+<enum />
+<!-- Enum en2 present but invalid -->
+<enum en2="im not valid" />
+<!-- Enum en2 correct but n1 invalid -->
+<enum en2="pkg" en1="im not valid" />
+<!-- Enum en2 correct but en3 invalid -->
+<enum en2="ldlib" en3="im not valid" />
+<!-- Not declared tests -->
+<string not="im not valid" />
+<string att2="any" not="im not valid" />
+<string att2="any" notdeclared="any" />
+</foo>
View
11 tests/attributes_good.xml
@@ -0,0 +1,11 @@
+<foo>
+<string att2="any" />
+<string att1="any" att2="any2" />
+<string att1="any" att2="any2" att3="POST" />
+<string att1="any" att2="any2" att3="POST" att4="any" />
+
+<enum en2="ext" />
+<enum en2="ext" en1="ordered" />
+<enum en2="prog" en1="glossary" en3="ge" />
+
+</foo>
View
16 tests/children.dtd
@@ -0,0 +1,16 @@
+<!ELEMENT foo (test1|test2|test3|test4|test5|test6|test7|test8|test9)+>
+
+<!ELEMENT a EMPTY>
+<!ELEMENT bbb EMPTY>
+<!ELEMENT c EMPTY>
+<!ELEMENT dddd EMPTY>
+
+<!ELEMENT test1 (a)>
+<!ELEMENT test2 (a|bbb|c|dddd)>
+<!ELEMENT test3 (a|bbb)*>
+<!ELEMENT test4 (a,bbb,c,dddd)>
+<!ELEMENT test5 (a,bbb,c,dddd)+>
+<!ELEMENT test6 ((a|bbb),(c|dddd))>
+<!ELEMENT test7 (a,(c|dddd))>
+<!ELEMENT test8 (a?,dddd+,c*)>
+<!ELEMENT test9 (a,(c|bbb)*)>
View
56 tests/children_bad.xml
@@ -0,0 +1,56 @@
+<foo>
+<test1 />
+<test1><a/><a/></test1>
+<test1><b/></test1>
+<test1><bbb/></test1>
+<test1><a/><bbb/></test1>
+
+<test2 />
+<test2><b/></test2>
+<test2><bbb/><aaa/><c/></test2>
+<test2><a/><a/><a/></test2>
+<test2><c/><a/><c/><bbb/><dddd/></test2>
+
+<test3><dddd/></test3>
+
+<test4/>
+<test4><a/></test4>
+<test4><a/><c/></test4>
+<test4><a/><bbb/><c/></test4>
+<test4><dddd/><c/><bbb/><a/></test4>
+<test4><a/><bbb/><c/><c/><dddd/></test4>
+
+<test5/>
+<test5><a/></test5>
+<test5><a/><c/></test5>
+<test5><a/><bbb/><c/></test5>
+<test5><dddd/><c/><bbb/><a/></test5>
+<test5><a/><bbb/><c/><c/><dddd/></test5>
+
+<test6><a/><bbb/></test6>
+<test6><a/><bbb/><c/></test6>
+<test6><a/><c/><c/></test6>
+
+<test7 />
+<test7><c/></test7>
+<test7><a/><bbb/></test7>
+<test7><a/><c/><c/></test7>
+<test7><a/><dddd/><dddd/></test7>
+<test7><a/><c/><dddd/></test7>
+<test7><a/><dddd/><c/></test7>
+
+<test8 />
+<test8><bbb/></test8>
+<test8><a/><a/><dddd/></test8>
+<test8><a/><c/></test8>
+<test8><c/></test8>
+<test8><a/><a/><dddd/><c/></test8>
+<test8><a/><a/><dddd/><dddd/><c/></test8>
+
+<test9 />
+<test9><c/></test9>
+<test9><a/><dddd/></test9>
+<test9><bbb/></test9>
+<test9><c/><c/></test9>
+
+</foo>
View
37 tests/children_good.xml
@@ -0,0 +1,37 @@
+<foo>
+
+<test1><a/></test1>
+
+<test2><a/></test2>
+<test2><bbb/></test2>
+
+<test3/>
+<test3><bbb/></test3>
+<test3><a/><a/></test3>
+<test3><a/><bbb/><a/></test3>
+
+<test4><a/><bbb/><c/><dddd/></test4>
+
+<test5><a/><bbb/><c/><dddd/></test5>
+<test5><a/><bbb/><c/><dddd/><a/><bbb/><c/><dddd/><a/><bbb/><c/><dddd/></test5>
+
+<test6><a/><c/></test6>
+<test6><a/><dddd/></test6>
+<test6><bbb/><c/></test6>
+<test6><bbb/><dddd/></test6>
+
+<test7><a/><c/></test7>
+<test7><a/><dddd/></test7>
+
+<test8><dddd/></test8>
+<test8><a/><dddd/></test8>
+<test8><a/><dddd/><dddd/><dddd/></test8>
+<test8><dddd/><dddd/><c/></test8>
+<test8><dddd/><dddd/><c/><c/><c/></test8>
+
+<test9><a/></test9>
+<test9><a/><c/><bbb/></test9>
+<test9><a/><bbb/><bbb/></test9>
+<test9><a/><bbb/><bbb/><c/></test9>
+
+</foo>
View
6 tests/content.dtd
@@ -0,0 +1,6 @@
+<!ELEMENT foo (bar|bar2|bar3|bar4)+>
+<!ELEMENT bar (#PCDATA)>
+<!ELEMENT bar2 ANY>
+<!ELEMENT bar3 EMPTY>
+<!ELEMENT jack EMPTY>
+<!ELEMENT bar4 (#PCDATA|jack|bar3)*>
View
14 tests/content_bad.xml
@@ -0,0 +1,14 @@
+<foo>
+<!-- test undeclared tag under content only nodes -->
+<bar><i_should_be_content/></bar>
+<bar2><i_should_be_content/></bar2>
+<bar3><i_should_be_content/></bar3>
+<!-- test declared tags under content only nodes -->
+<bar><jack/></bar>
+<bar2><jack/></bar2>
+<bar3><jack/></bar3>
+<!-- test not empty tag when declared as EMPTY -->
+<bar3>I should be empty</bar3>
+<!-- mixed content test -->
+<bar4><bar2/></bar4>
+</foo>
View
7 tests/content_good.xml
@@ -0,0 +1,7 @@
+<foo>
+<bar>im the content</bar>
+<bar2>im the content</bar2>
+<bar3></bar3>
+<bar3 />
+<bar4>www<jack/>zzzz<jack/><bar3/>asd</bar4>
+</foo>
View
83 tests/package-1.0
@@ -0,0 +1,83 @@
+<!--
+ $Id$
+
+ This is the PEAR package description, version 1.0b3.
+ It should be used with the informal public identifier:
+
+ "-//PHP Group//DTD PEAR Package 1.0b3//EN//XML"
+
+ Copyright (c) 1997-2003 The PHP Group
+
+ This source file is subject to version 2.02 of the PHP license,
+ that is bundled with this package in the file LICENSE, and is
+ available at through the world-wide-web at
+ http://www.php.net/license/2_02.txt.
+ If you did not receive a copy of the PHP license and are unable to
+ obtain it through the world-wide-web, please send a note to
+ license@php.net so we can mail you a copy immediately.
+
+ Authors:
+ Stig S. Bakken <ssb@fast.no>
+
+ -->
+
+<!ELEMENT package (name|summary|description|license|maintainers|release|changelog)>
+<!ATTLIST package type (source|binary|empty) "empty"
+ version CDATA #REQUIRED>
+
+<!ELEMENT name (#PCDATA)>
+
+<!ELEMENT summary (#PCDATA)>
+
+<!ELEMENT description (#PCDATA)>
+
+<!ELEMENT maintainers (maintainer)+>
+
+<!ELEMENT maintainer (user|role|name|email)*>
+
+<!ELEMENT user (#PCDATA)>
+
+<!ELEMENT role (#PCDATA)>
+
+<!ELEMENT email (#PCDATA)>
+
+<!ELEMENT changelog (release)*>
+
+<!ELEMENT release (version|license|state|date|notes|filelist|deps)*>
+
+<!ELEMENT version (#PCDATA)>
+
+<!ELEMENT state (#PCDATA)>
+
+<!ELEMENT date (#PCDATA)>
+
+<!ELEMENT notes (#PCDATA)>
+
+<!ELEMENT filelist (dir|file|libfile)*>
+
+<!ELEMENT dir (dir|file|libfile)*>
+<!ATTLIST dir name CDATA #REQUIRED
+ baseinstalldir CDATA #IMPLIED>
+
+<!ELEMENT file (#PCDATA)>
+<!ATTLIST file role (php|ext|test|doc|data) 'php'
+ debug (na|on|off) 'na'
+ threaded (na|on|off) 'na'
+ format CDATA #IMPLIED
+ baseinstalldir CDATA #IMPLIED>
+
+<!ELEMENT libfile (libname|sources|includes|libadd)*>
+
+<!ELEMENT libname (#PCDATA)>
+
+<!ELEMENT sources (#PCDATA)>
+
+<!ELEMENT libadd (#PCDATA)>
+
+<!ELEMENT deps (dep)*>
+
+<!ELEMENT dep (#PCDATA)>
+<!ATTLIST dep
+ type (pkg|ext|php|prog|ldlib|ltlib|os|websrv|sapi) #REQUIRED
+ rel (has|eq|lt|le|gt|ge) #IMPLIED
+ version CDATA #IMPLIED>
View
113 tests/package-1.1.dtd
@@ -0,0 +1,113 @@
+<!--
+ $Id: package-1.1.dtd,v 1.1 2003-09-11 13:10:04 cox Exp $
+
+ This is the PEAR package description, version 1.0b3.
+ It should be used with the informal public identifier:
+
+ "-//PHP Group//DTD PEAR Package 1.0b3//EN//XML"
+
+ Copyright (c) 1997-2003 The PHP Group
+
+ This source file is subject to version 2.02 of the PHP license,
+ that is bundled with this package in the file LICENSE, and is
+ available at through the world-wide-web at
+ http://www.php.net/license/2_02.txt.
+ If you did not receive a copy of the PHP license and are unable to
+ obtain it through the world-wide-web, please send a note to
+ license@php.net so we can mail you a copy immediately.
+
+ Authors:
+ Stig S. Bakken <ssb@fast.no>
+ Tomas V.V.Cox <cox@idecnet.com>
+
+ DTD Revision: 1.1
+
+ -->
+
+<!ENTITY % FileRoles "(php|ext|test|doc|data|src|script)">
+<!ENTITY % DepTypes "(pkg|ext|php|prog|ldlib|ltlib|os|websrv|sapi)">
+<!ENTITY % DepRels "(has|not|eq|lt|le|gt|ge)">
+<!ENTITY % ProvideTypes "(ext|prog|class|function|feature|api)">
+
+<!ELEMENT package (name,summary,description,license?,maintainers,release,changelog?)>
+<!ATTLIST package
+ type (source|binary|empty) "empty"
+ version CDATA #REQUIRED>
+
+<!ELEMENT name (#PCDATA)>
+
+<!ELEMENT summary (#PCDATA)>
+
+<!ELEMENT description (#PCDATA)>
+
+<!ELEMENT maintainers (maintainer)+>
+
+<!ELEMENT maintainer (user,role,name,email)>
+
+<!ELEMENT user (#PCDATA)>
+
+<!ELEMENT role (#PCDATA)>
+
+<!ELEMENT email (#PCDATA)>
+
+<!ELEMENT changelog (release)*>
+
+<!ELEMENT release (license?,version,state,date,notes,filelist,provides*,deps?)>
+
+<!ELEMENT license (#PCDATA)>
+
+<!ELEMENT version (#PCDATA)>
+
+<!ELEMENT state (#PCDATA)>
+
+<!ELEMENT date (#PCDATA)>
+
+<!ELEMENT notes (#PCDATA)>
+
+<!ELEMENT filelist (dir|file|libfile)+>
+
+<!ELEMENT dir (dir|file|libfile)*>
+<!ATTLIST dir
+ name CDATA #REQUIRED
+ role %FileRoles; 'php'
+ baseinstalldir CDATA #IMPLIED>
+
+<!ELEMENT file (#PCDATA|replace)*>
+<!ATTLIST file
+ name CDATA #IMPLIED
+ role %FileRoles; 'php'
+ debug (na|on|off) 'na'
+ threaded (na|on|off) 'na'
+ format CDATA #IMPLIED
+ md5sum CDATA #IMPLIED
+ install-as CDATA #IMPLIED
+ platform CDATA #IMPLIED
+ baseinstalldir CDATA #IMPLIED>
+
+<!ELEMENT replace EMPTY>
+<!ATTLIST replace
+ from CDATA #REQUIRED
+ to CDATA #REQUIRED
+ type CDATA #REQUIRED>
+
+<!ELEMENT libfile (libname|sources|includes|libadd)*>
+
+<!ELEMENT libname (#PCDATA)>
+
+<!ELEMENT sources (#PCDATA)>
+
+<!ELEMENT libadd (#PCDATA)>
+
+<!ELEMENT deps (dep)*>
+
+<!ELEMENT dep (#PCDATA)>
+<!ATTLIST dep
+ type %DepTypes; #REQUIRED
+ rel %DepRels; #IMPLIED
+ version CDATA #IMPLIED>
+
+<!ELEMENT provides EMPTY>
+<!ATTLIST provides
+ type %ProvideTypes; #REQUIRED
+ name CDATA #REQUIRED
+ extends CDATA #IMPLIED>
View
32 tests/test.php
@@ -0,0 +1,32 @@
+#!/usr/bin/php -Cq
+<?php
+ob_implicit_flush(true);
+$path = ini_get('include_path');
+ini_set('include_path', realpath('..') . ":$path");
+$argv = $_SERVER['argv'];
+if (!is_file(@$argv[1])) {
+ help();
+}
+$dtd = $argv[1];
+if (isset($argv[2]) && !is_file($argv[2])) {
+ help();
+}
+$xml = isset($argv[2]) ? $argv[2] : false;
+if (!$xml) {
+ include 'XML/DTD.php';
+ $a = new XML_DTD_Parser;
+ print_r($a->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 <dtd file> [<xml file>]\n";
+ echo "Passing only <dtd file> will dump the parsed DTD Tree\n";
+ echo "Passing both, will try to validate <xml file> with <dtd file>\n";
+ exit;
+}
+?>
View
978 tests/xhtml1-strict.dtd
@@ -0,0 +1,978 @@
+<!--
+ Extensible HTML version 1.0 Strict DTD
+
+ This is the same as HTML 4 Strict except for
+ changes due to the differences between XML and SGML.
+
+ Namespace = http://www.w3.org/1999/xhtml
+
+ For further information, see: http://www.w3.org/TR/xhtml1
+
+ Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+ All Rights Reserved.
+
+ This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+
+ $Revision: 1.1 $
+ $Date: 2003-09-11 13:10:04 $
+
+-->
+
+<!--================ Character mnemonic entities =========================-->
+
+<!ENTITY % HTMLlat1 PUBLIC
+ "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+ "xhtml-lat1.ent">
+%HTMLlat1;
+
+<!ENTITY % HTMLsymbol PUBLIC
+ "-//W3C//ENTITIES Symbols for XHTML//EN"
+ "xhtml-symbol.ent">
+%HTMLsymbol;
+
+<!ENTITY % HTMLspecial PUBLIC
+ "-//W3C//ENTITIES Special for XHTML//EN"
+ "xhtml-special.ent">
+%HTMLspecial;
+
+<!--================== Imported Names ====================================-->
+
+<!ENTITY % ContentType "CDATA">
+ <!-- media type, as per [RFC2045] -->
+
+<!ENTITY % ContentTypes "CDATA">
+ <!-- comma-separated list of media types, as per [RFC2045] -->
+
+<!ENTITY % Charset "CDATA">
+ <!-- a character encoding, as per [RFC2045] -->
+
+<!ENTITY % Charsets "CDATA">
+ <!-- a space separated list of character encodings, as per [RFC2045] -->
+
+<!ENTITY % LanguageCode "NMTOKEN">
+ <!-- a language code, as per [RFC3066] -->
+
+<!ENTITY % Character "CDATA">
+ <!-- a single character, as per section 2.2 of [XML] -->
+
+<!ENTITY % Number "CDATA">
+ <!-- one or more digits -->
+
+<!ENTITY % LinkTypes "CDATA">
+ <!-- space-separated list of link types -->
+
+<!ENTITY % MediaDesc "CDATA">
+ <!-- single or comma-separated list of media descriptors -->
+
+<!ENTITY % URI "CDATA">
+ <!-- a Uniform Resource Identifier, see [RFC2396] -->
+
+<!ENTITY % UriList "CDATA">
+ <!-- a space separated list of Uniform Resource Identifiers -->
+
+<!ENTITY % Datetime "CDATA">
+ <!-- date and time information. ISO date format -->
+
+<!ENTITY % Script "CDATA">
+ <!-- script expression -->
+
+<!ENTITY % StyleSheet "CDATA">
+ <!-- style sheet data -->
+
+<!ENTITY % Text "CDATA">
+ <!-- used for titles etc. -->
+
+<!ENTITY % Length "CDATA">
+ <!-- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % MultiLength "CDATA">
+ <!-- pixel, percentage, or relative -->
+
+<!ENTITY % Pixels "CDATA">
+ <!-- integer representing length in pixels -->
+
+<!-- these are used for image maps -->
+
+<!ENTITY % Shape "(rect|circle|poly|default)">
+
+<!ENTITY % Coords "CDATA">
+ <!-- comma separated list of lengths -->
+
+<!--=================== Generic Attributes ===============================-->
+
+<!-- core attributes common to most elements
+ id document-wide unique id
+ class space separated list of classes
+ style associated style info
+ title advisory title/amplification
+-->
+<!ENTITY % coreattrs
+ "id ID #IMPLIED
+ class CDATA #IMPLIED
+ style %StyleSheet; #IMPLIED
+ title %Text; #IMPLIED"
+ >
+
+<!-- internationalization attributes
+ lang language code (backwards compatible)
+ xml:lang language code (as per XML 1.0 spec)
+ dir direction for weak/neutral text
+-->
+<!ENTITY % i18n
+ "lang %LanguageCode; #IMPLIED
+ xml:lang %LanguageCode; #IMPLIED
+ dir (ltr|rtl) #IMPLIED"
+ >
+
+<!-- attributes for common UI events
+ onclick a pointer button was clicked
+ ondblclick a pointer button was double clicked
+ onmousedown a pointer button was pressed down
+ onmouseup a pointer button was released
+ onmousemove a pointer was moved onto the element
+ onmouseout a pointer was moved away from the element
+ onkeypress a key was pressed and released
+ onkeydown a key was pressed down
+ onkeyup a key was released
+-->
+<!ENTITY % events
+ "onclick %Script; #IMPLIED
+ ondblclick %Script; #IMPLIED
+ onmousedown %Script; #IMPLIED
+ onmouseup %Script; #IMPLIED
+ onmouseover %Script; #IMPLIED
+ onmousemove %Script; #IMPLIED
+ onmouseout %Script; #IMPLIED
+ onkeypress %Script; #IMPLIED
+ onkeydown %Script; #IMPLIED
+ onkeyup %Script; #IMPLIED"
+ >
+
+<!-- attributes for elements that can get the focus
+ accesskey accessibility key character
+ tabindex position in tabbing order
+ onfocus the element got the focus
+ onblur the element lost the focus
+-->
+<!ENTITY % focus
+ "accesskey %Character; #IMPLIED
+ tabindex %Number; #IMPLIED
+ onfocus %Script; #IMPLIED
+ onblur %Script; #IMPLIED"
+ >
+
+<!ENTITY % attrs "%coreattrs; %i18n; %events;">
+
+<!--=================== Text Elements ====================================-->
+
+<!ENTITY % special.pre
+ "br | span | bdo | map">
+
+
+<!ENTITY % special
+ "%special.pre; | object | img ">
+
+<!ENTITY % fontstyle "tt | i | b | big | small ">
+
+<!ENTITY % phrase "em | strong | dfn | code | q |
+ samp | kbd | var | cite | abbr | acronym | sub | sup ">
+
+<!ENTITY % inline.forms "input | select | textarea | label | button">
+
+<!-- these can occur at block or inline level -->
+<!ENTITY % misc.inline "ins | del | script">
+
+<!-- these can only occur at block level -->
+<!ENTITY % misc "noscript | %misc.inline;">
+
+<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
+
+<!-- %Inline; covers inline or "text-level" elements -->
+<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
+
+<!--================== Block level elements ==============================-->
+
+<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
+<!ENTITY % lists "ul | ol | dl">
+<!ENTITY % blocktext "pre | hr | blockquote | address">
+
+<!ENTITY % block
+ "p | %heading; | div | %lists; | %blocktext; | fieldset | table">
+
+<!ENTITY % Block "(%block; | form | %misc;)*">
+
+<!-- %Flow; mixes block and inline and is used for list items etc. -->
+<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
+
+<!--================== Content models for exclusions =====================-->
+
+<!-- a elements use %Inline; excluding a -->
+
+<!ENTITY % a.content
+ "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
+
+<!-- pre uses %Inline excluding big, small, sup or sup -->
+
+<!ENTITY % pre.content
+ "(#PCDATA | a | %fontstyle; | %phrase; | %special.pre; | %misc.inline;
+ | %inline.forms;)*">
+
+<!-- form uses %Block; excluding form -->
+
+<!ENTITY % form.content "(%block; | %misc;)*">
+
+<!-- button uses %Flow; but excludes a, form and form controls -->
+
+<!ENTITY % button.content
+ "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
+ table | %special; | %fontstyle; | %phrase; | %misc;)*">
+
+<!--================ Document Structure ==================================-->
+
+<!-- the namespace URI designates the document profile -->
+
+<!ELEMENT html (head, body)>
+<!ATTLIST html
+ %i18n;
+ id ID #IMPLIED
+ xmlns %URI; #FIXED 'http://www.w3.org/1999/xhtml'
+ >
+
+<!--================ Document Head =======================================-->
+
+<!ENTITY % head.misc "(script|style|meta|link|object)*">
+
+<!-- content model is %head.misc; combined with a single
+ title and an optional base element in any order -->
+
+<!ELEMENT head (%head.misc;,
+ ((title, %head.misc;, (base, %head.misc;)?) |
+ (base, %head.misc;, (title, %head.misc;))))>
+
+<!ATTLIST head
+ %i18n;
+ id ID #IMPLIED
+ profile %URI; #IMPLIED
+ >
+
+<!-- The title element is not considered part of the flow of text.
+ It should be displayed, for example as the page header or
+ window title. Exactly one title is required per document.
+ -->
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ %i18n;
+ id ID #IMPLIED
+ >
+
+<!-- document base URI -->
+
+<!ELEMENT base EMPTY>
+<!ATTLIST base
+ href %URI; #REQUIRED
+ id ID #IMPLIED
+ >
+
+<!-- generic metainformation -->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+ %i18n;
+ id ID #IMPLIED
+ http-equiv CDATA #IMPLIED
+ name CDATA #IMPLIED
+ content CDATA #REQUIRED
+ scheme CDATA #IMPLIED
+ >
+
+<!--
+ Relationship values can be used in principle:
+
+ a) for document specific toolbars/menus when used
+ with the link element in document head e.g.
+ start, contents, previous, next, index, end, help
+ b) to link to a separate style sheet (rel="stylesheet")
+ c) to make a link to a script (rel="script")
+ d) by stylesheets to control how collections of
+ html nodes are rendered into printed documents
+ e) to make a link to a printable version of this document
+ e.g. a PostScript or PDF version (rel="alternate" media="print")
+-->
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ %attrs;
+ charset %Charset; #IMPLIED
+ href %URI; #IMPLIED
+ hreflang %LanguageCode; #IMPLIED
+ type %ContentType; #IMPLIED
+ rel %LinkTypes; #IMPLIED
+ rev %LinkTypes; #IMPLIED
+ media %MediaDesc; #IMPLIED
+ >
+
+<!-- style info, which may include CDATA sections -->
+<!ELEMENT style (#PCDATA)>
+<!ATTLIST style
+ %i18n;
+ id ID #IMPLIED
+ type %ContentType; #REQUIRED
+ media %MediaDesc; #IMPLIED
+ title %Text; #IMPLIED
+ xml:space (preserve) #FIXED 'preserve'
+ >
+
+<!-- script statements, which may include CDATA sections -->
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ charset %Charset; #IMPLIED
+ type %ContentType; #REQUIRED
+ src %URI; #IMPLIED
+ defer (defer) #IMPLIED
+ xml:space (preserve) #FIXED 'preserve'
+ >
+
+<!-- alternate content container for non script-based rendering -->
+
+<!ELEMENT noscript %Block;>
+<!ATTLIST noscript
+ %attrs;
+ >
+
+<!--=================== Document Body ====================================-->
+
+<!ELEMENT body %Block;>
+<!ATTLIST body
+ %attrs;
+ onload %Script; #IMPLIED
+ onunload %Script; #IMPLIED
+ >
+
+<!ELEMENT div %Flow;> <!-- generic language/style container -->
+<!ATTLIST div
+ %attrs;
+ >
+
+<!--=================== Paragraphs =======================================-->
+
+<!ELEMENT p %Inline;>
+<!ATTLIST p
+ %attrs;
+ >
+
+<!--=================== Headings =========================================-->
+
+<!--
+ There are six levels of headings from h1 (the most important)
+ to h6 (the least important).
+-->
+
+<!ELEMENT h1 %Inline;>
+<!ATTLIST h1
+ %attrs;
+ >
+
+<!ELEMENT h2 %Inline;>
+<!ATTLIST h2
+ %attrs;
+ >
+
+<!ELEMENT h3 %Inline;>
+<!ATTLIST h3
+ %attrs;
+ >
+
+<!ELEMENT h4 %Inline;>
+<!ATTLIST h4
+ %attrs;
+ >
+
+<!ELEMENT h5 %Inline;>
+<!ATTLIST h5
+ %attrs;
+ >
+
+<!ELEMENT h6 %Inline;>
+<!ATTLIST h6
+ %attrs;
+ >
+
+<!--=================== Lists ============================================-->
+
+<!-- Unordered list -->
+
+<!ELEMENT ul (li)+>
+<!ATTLIST ul
+ %attrs;
+ >
+
+<!-- Ordered (numbered) list -->
+
+<!ELEMENT ol (li)+>
+<!ATTLIST ol
+ %attrs;
+ >
+
+<!-- list item -->
+
+<!ELEMENT li %Flow;>
+<!ATTLIST li
+ %attrs;
+ >
+
+<!-- definition lists - dt for term, dd for its definition -->
+
+<!ELEMENT dl (dt|dd)+>
+<!ATTLIST dl
+ %attrs;
+ >
+
+<!ELEMENT dt %Inline;>
+<!ATTLIST dt
+ %attrs;
+ >
+
+<!ELEMENT dd %Flow;>
+<!ATTLIST dd
+ %attrs;
+ >
+
+<!--=================== Address ==========================================-->
+
+<!-- information on author -->
+
+<!ELEMENT address %Inline;>
+<!ATTLIST address
+ %attrs;
+ >
+
+<!--=================== Horizontal Rule ==================================-->
+
+<!ELEMENT hr EMPTY>
+<!ATTLIST hr
+ %attrs;
+ >
+
+<!--=================== Preformatted Text ================================-->
+
+<!-- content is %Inline; excluding "img|object|big|small|sub|sup" -->
+
+<!ELEMENT pre %pre.content;>
+<!ATTLIST pre
+ %attrs;
+ xml:space (preserve) #FIXED 'preserve'
+ >
+
+<!--=================== Block-like Quotes ================================-->
+
+<!ELEMENT blockquote %Block;>
+<!ATTLIST blockquote
+ %attrs;
+ cite %URI; #IMPLIED
+ >
+
+<!--=================== Inserted/Deleted Text ============================-->
+
+<!--
+ ins/del are allowed in block and inline content, but its
+ inappropriate to include block content within an ins element
+ occurring in inline content.
+-->
+<!ELEMENT ins %Flow;>
+<!ATTLIST ins
+ %attrs;
+ cite %URI; #IMPLIED
+ datetime %Datetime; #IMPLIED
+ >
+
+<!ELEMENT del %Flow;>
+<!ATTLIST del
+ %attrs;
+ cite %URI; #IMPLIED
+ datetime %Datetime; #IMPLIED
+ >
+
+<!--================== The Anchor Element ================================-->
+
+<!-- content is %Inline; except that anchors shouldn't be nested -->
+
+<!ELEMENT a %a.content;>
+<!ATTLIST a
+ %attrs;
+ %focus;
+ charset %Charset; #IMPLIED
+ type %ContentType; #IMPLIED
+ name NMTOKEN #IMPLIED
+ href %URI; #IMPLIED
+ hreflang %LanguageCode; #IMPLIED
+ rel %LinkTypes; #IMPLIED
+ rev %LinkTypes; #IMPLIED
+ shape %Shape; "rect"
+ coords %Coords; #IMPLIED
+ >
+
+<!--===================== Inline Elements ================================-->
+
+<!ELEMENT span %Inline;> <!-- generic language/style container -->
+<!ATTLIST span
+ %attrs;
+ >
+
+<!ELEMENT bdo %Inline;> <!-- I18N BiDi over-ride -->
+<!ATTLIST bdo
+ %coreattrs;
+ %events;
+ lang %LanguageCode; #IMPLIED
+ xml:lang %LanguageCode; #IMPLIED
+ dir (ltr|rtl) #REQUIRED
+ >
+
+<!ELEMENT br EMPTY> <!-- forced line break -->
+<!ATTLIST br
+ %coreattrs;
+ >
+
+<!ELEMENT em %Inline;> <!-- emphasis -->
+<!ATTLIST em %attrs;>
+
+<!ELEMENT strong %Inline;> <!-- strong emphasis -->
+<!ATTLIST strong %attrs;>
+
+<!ELEMENT dfn %Inline;> <!-- definitional -->
+<!ATTLIST dfn %attrs;>
+
+<!ELEMENT code %Inline;> <!-- program code -->
+<!ATTLIST code %attrs;>
+
+<!ELEMENT samp %Inline;> <!-- sample -->
+<!ATTLIST samp %attrs;>
+
+<!ELEMENT kbd %Inline;> <!-- something user would type -->
+<!ATTLIST kbd %attrs;>
+
+<!ELEMENT var %Inline;> <!-- variable -->
+<!ATTLIST var %attrs;>
+
+<!ELEMENT cite %Inline;> <!-- citation -->
+<!ATTLIST cite %attrs;>
+
+<!ELEMENT abbr %Inline;> <!-- abbreviation -->
+<!ATTLIST abbr %attrs;>
+
+<!ELEMENT acronym %Inline;> <!-- acronym -->
+<!ATTLIST acronym %attrs;>
+
+<!ELEMENT q %Inline;> <!-- inlined quote -->
+<!ATTLIST q
+ %attrs;
+ cite %URI; #IMPLIED
+ >
+
+<!ELEMENT sub %Inline;> <!-- subscript -->
+<!ATTLIST sub %attrs;>
+
+<!ELEMENT sup %Inline;> <!-- superscript -->
+<!ATTLIST sup %attrs;>
+
+<!ELEMENT tt %Inline;> <!-- fixed pitch font -->
+<!ATTLIST tt %attrs;>
+
+<!ELEMENT i %Inline;> <!-- italic font -->
+<!ATTLIST i %attrs;>
+
+<!ELEMENT b %Inline;> <!-- bold font -->
+<!ATTLIST b %attrs;>
+
+<!ELEMENT big %Inline;> <!-- bigger font -->
+<!ATTLIST big %attrs;>
+
+<!ELEMENT small %Inline;> <!-- smaller font -->
+<!ATTLIST small %attrs;>
+
+<!--==================== Object ======================================-->
+<!--
+ object is used to embed objects as part of HTML pages.
+ param elements should precede other content. Parameters
+ can also be expressed as attribute/value pairs on the
+ object element itself when brevity is desired.
+-->
+
+<!ELEMENT object (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST object
+ %attrs;
+ declare (declare) #IMPLIED
+ classid %URI; #IMPLIED
+ codebase %URI; #IMPLIED
+ data %URI; #IMPLIED
+ type %ContentType; #IMPLIED
+ codetype %ContentType; #IMPLIED
+ archive %UriList; #IMPLIED
+ standby %Text; #IMPLIED
+ height %Length; #IMPLIED
+ width %Length; #IMPLIED
+ usemap %URI; #IMPLIED
+ name NMTOKEN #IMPLIED
+ tabindex %Number; #IMPLIED
+ >
+
+<!--
+ param is used to supply a named property value.
+ In XML it would seem natural to follow RDF and support an
+ abbreviated syntax where the param elements are replaced
+ by attribute value pairs on the object start tag.
+-->
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED
+ valuetype (data|ref|object) "data"
+ type %ContentType; #IMPLIED
+ >
+
+<!--=================== Images ===========================================-->
+
+<!--
+ To avoid accessibility problems for people who aren't
+ able to see the image, you should provide a text
+ description using the alt and longdesc attributes.
+ In addition, avoid the use of server-side image maps.
+ Note that in this DTD there is no name attribute. That
+ is only available in the transitional and frameset DTD.
+-->
+
+<!ELEMENT img EMPTY>
+<!ATTLIST img
+ %attrs;
+ src %URI; #REQUIRED
+ alt %Text; #REQUIRED
+ longdesc %URI; #IMPLIED
+ height %Length; #IMPLIED
+ width %Length; #IMPLIED
+ usemap %URI; #IMPLIED
+ ismap (ismap) #IMPLIED
+ >
+
+<!-- usemap points to a map element which may be in this document
+ or an external document, although the latter is not widely supported -->
+
+<!--================== Client-side image maps ============================-->
+
+<!-- These can be placed in the same document or grouped in a
+ separate document although this isn't yet widely supported -->
+
+<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
+<!ATTLIST map
+ %i18n;
+ %events;
+ id ID #REQUIRED
+ class CDATA #IMPLIED
+ style %StyleSheet; #IMPLIED
+ title %Text; #IMPLIED
+ name NMTOKEN #IMPLIED
+ >
+
+<!ELEMENT area EMPTY>
+<!ATTLIST area
+ %attrs;
+ %focus;
+ shape %Shape; "rect"
+ coords %Coords; #IMPLIED
+ href %URI; #IMPLIED
+ nohref (nohref) #IMPLIED
+ alt %Text; #REQUIRED
+ >
+
+<!--================ Forms ===============================================-->
+<!ELEMENT form %form.content;> <!-- forms shouldn't be nested -->
+
+<!ATTLIST form
+ %attrs;
+ action %URI; #REQUIRED
+ method (get|post) "get"
+ enctype %ContentType; "application/x-www-form-urlencoded"
+ onsubmit %Script; #IMPLIED
+ onreset %Script; #IMPLIED
+ accept %ContentTypes; #IMPLIED
+ accept-charset %Charsets; #IMPLIED
+ >
+
+<!--
+ Each label must not contain more than ONE field
+ Label elements shouldn't be nested.
+-->
+<!ELEMENT label %Inline;>
+<!ATTLIST label
+ %attrs;
+ for IDREF #IMPLIED
+ accesskey %Character; #IMPLIED
+ onfocus %Script; #IMPLIED
+ onblur %Script; #IMPLIED
+ >
+
+<!ENTITY % InputType
+ "(text | password | checkbox |
+ radio | submit | reset |
+ file | hidden | image | button)"
+ >
+
+<!-- the name attribute is required for all but submit & reset -->
+
+<!ELEMENT input EMPTY> <!-- form control -->
+<!ATTLIST input
+ %attrs;
+ %focus;
+ type %InputType; "text"
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED
+ checked (checked) #IMPLIED
+ disabled (disabled) #IMPLIED
+ readonly (readonly) #IMPLIED
+ size CDATA #IMPLIED
+ maxlength %Number; #IMPLIED
+ src %URI; #IMPLIED
+ alt CDATA #IMPLIED
+ usemap %URI; #IMPLIED
+ onselect %Script; #IMPLIED
+ onchange %Script; #IMPLIED
+ accept %ContentTypes; #IMPLIED
+ >
+
+<!ELEMENT select (optgroup|option)+> <!-- option selector -->
+<!ATTLIST select
+ %attrs;
+ name CDATA #IMPLIED
+ size %Number; #IMPLIED
+ multiple (multiple) #IMPLIED
+ disabled (disabled) #IMPLIED
+ tabindex %Number; #IMPLIED
+ onfocus %Script; #IMPLIED
+ onblur %Script; #IMPLIED
+ onchange %Script; #IMPLIED
+ >
+
+<!ELEMENT optgroup (option)+> <!-- option group -->
+<!ATTLIST optgroup
+ %attrs;
+ disabled (disabled) #IMPLIED
+ label %Text; #REQUIRED
+ >
+
+<!ELEMENT option (#PCDATA)> <!-- selectable choice -->
+<!ATTLIST option
+ %attrs;
+ selected (selected) #IMPLIED
+ disabled (disabled) #IMPLIED
+ label %Text; #IMPLIED
+ value CDATA #IMPLIED
+ >
+
+<!ELEMENT textarea (#PCDATA)> <!-- multi-line text field -->
+<!ATTLIST textarea
+ %attrs;
+ %focus;
+ name CDATA #IMPLIED
+ rows %Number; #REQUIRED
+ cols %Number; #REQUIRED
+ disabled (disabled) #IMPLIED
+ readonly (readonly) #IMPLIED
+ onselect %Script; #IMPLIED
+ onchange %Script; #IMPLIED
+ >
+
+<!--
+ The fieldset element is used to group form fields.
+ Only one legend element should occur in the content
+ and if present should only be preceded by whitespace.
+-->
+<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
+<!ATTLIST fieldset
+ %attrs;
+ >
+
+<!ELEMENT legend %Inline;> <!-- fieldset label -->
+<!ATTLIST legend
+ %attrs;
+ accesskey %Character; #IMPLIED
+ >
+
+<!--
+ Content is %Flow; excluding a, form and form controls
+-->
+<!ELEMENT button %button.content;> <!-- push button -->
+<!ATTLIST button
+ %attrs;
+ %focus;
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED
+ type (button|submit|reset) "submit"
+ disabled (disabled) #IMPLIED
+ >
+
+<!--======================= Tables =======================================-->
+
+<!-- Derived from IETF HTML table standard, see [RFC1942] -->
+
+<!--
+ The border attribute sets the thickness of the frame around the
+ table. The default units are screen pixels.
+
+ The frame attribute specifies which parts of the frame around
+ the table should be rendered. The values are not the same as
+ CALS to avoid a name clash with the valign attribute.
+-->
+<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
+
+<!--
+ The rules attribute defines which rules to draw between cells:
+
+ If rules is absent then assume:
+ "none" if border is absent or border="0" otherwise "all"
+-->
+
+<!ENTITY % TRules "(none | groups | rows | cols | all)">
+
+<!-- horizontal alignment attributes for cell contents
+
+ char alignment char, e.g. char=':'
+ charoff offset for alignment char
+-->
+<!ENTITY % cellhalign
+ "align (left|center|right|justify|char) #IMPLIED
+ char %Character; #IMPLIED
+ charoff %Length; #IMPLIED"
+ >
+
+<!-- vertical alignment attributes for cell contents -->
+<!ENTITY % cellvalign
+ "valign (top|middle|bottom|baseline) #IMPLIED"
+ >
+
+<!ELEMENT table
+ (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
+<!ELEMENT caption %Inline;>
+<!ELEMENT thead (tr)+>
+<!ELEMENT tfoot (tr)+>
+<!ELEMENT tbody (tr)+>
+<!ELEMENT colgroup (col)*>
+<!ELEMENT col EMPTY>
+<!ELEMENT tr (th|td)+>
+<!ELEMENT th %Flow;>
+<!ELEMENT td %Flow;>
+
+<!ATTLIST table
+ %attrs;
+ summary %Text; #IMPLIED
+ width %Length; #IMPLIED
+ border %Pixels; #IMPLIED
+ frame %TFrame; #IMPLIED
+ rules %TRules; #IMPLIED
+ cellspacing %Length; #IMPLIED
+ cellpadding %Length; #IMPLIED
+ >
+
+<!ATTLIST caption
+ %attrs;
+ >
+
+<!--
+colgroup groups a set of col elements. It allows you to group
+several semantically related columns together.
+-->
+<!ATTLIST colgroup
+ %attrs;
+ span %Number; "1"
+ width %MultiLength; #IMPLIED
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!--
+ col elements define the alignment properties for cells in
+ one or more columns.
+
+ The width attribute specifies the width of the columns, e.g.
+
+ width=64 width in screen pixels
+ width=0.5* relative width of 0.5
+
+ The span attribute causes the attributes of one
+ col element to apply to more than one column.
+-->
+<!ATTLIST col
+ %attrs;
+ span %Number; "1"
+ width %MultiLength; #IMPLIED
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!--
+ Use thead to duplicate headers when breaking table
+ across page boundaries, or for static headers when
+ tbody sections are rendered in scrolling panel.
+
+ Use tfoot to duplicate footers when breaking table
+ across page boundaries, or for static footers when
+ tbody sections are rendered in scrolling panel.
+
+ Use multiple tbody sections when rules are needed
+ between groups of table rows.
+-->
+<!ATTLIST thead
+ %attrs;
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!ATTLIST tfoot
+ %attrs;
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!ATTLIST tbody
+ %attrs;
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!ATTLIST tr
+ %attrs;
+ %cellhalign;
+ %cellvalign;
+ >
+
+
+<!-- Scope is simpler than headers attribute for common tables -->
+<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
+
+<!-- th is for headers, td for data and for cells acting as both -->
+
+<!ATTLIST th
+ %attrs;
+ abbr %Text; #IMPLIED
+ axis CDATA #IMPLIED
+ headers IDREFS #IMPLIED
+ scope %Scope; #IMPLIED
+ rowspan %Number; "1"
+ colspan %Number; "1"
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!ATTLIST td
+ %attrs;
+ abbr %Text; #IMPLIED
+ axis CDATA #IMPLIED
+ headers IDREFS #IMPLIED
+ scope %Scope; #IMPLIED
+ rowspan %Number; "1"
+ colspan %Number; "1"
+ %cellhalign;
+ %cellvalign;
+ >
+
Please sign in to comment.
Something went wrong with that request. Please try again.