DTD for HTML

Small, short code snippets that other people may find useful. Do you have a good regex that you would like to share? Share it! Even better, the code can be commented on, and improved.

Moderator: General Moderators

Post Reply
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

DTD for HTML

Post by Ambush Commander »

HTML has always been a bit schizo when it came to DTDs. They used em, but they really didn't, because there were lots of other restrictions involved with it. The closest PHP gives you to working with DTDs is a DOM function for validation, which isn't very useful other times.

Well, no more.

TWP_DTD and it's corresponding children is a comprehensive DTD mapper class for PHP. It supports compiling DTDs into serialized files that can quickly be expanded to propogate arrays that represent the DTD structure, and you can map DTD files to PHP in initialize() functions. All great stuff for the ultimate context based HTML parser.

Or, at least, it would be great, if it was finished. Porting the DTD to PHP takes a long time (and worse, you can't automate it), and I've still got to

* Suddenly realize that the *s and +s after the allowed-inside elements have meaning and must be accounted for
* Do the HTML Transitional one
* Do the sane DTD, which is really what I'm going for
* Do Documentation
* Figure out if I'm barking up the wrong tree

But... ah well. Here's what we have sofar.

Code: Select all

<?php

define('TWP_DTD_ATTRIBUTE_IMPLIED', 1);
define('TWP_DTD_ATTRIBUTE_FIXED',2);
define('TWP_DTD_ATTRIBUTE_REQUIRED', 4);

class TWP_DTD
{
    var $elements = array();
    //$element_name = array
    //     'attributes' = array
    //          $attribute_name => array
    //              'type' => $type_of_value
    //              'default' => CONSTANT-TWP_DTD_ATTRIBUTE
    //              'value' => $default_value or null
    //          ...
    //      'content' = array
    //          $content_type
    //          ...
    //...
    var $magic = array('PCDATA','CDATA','NAME','IGNORE','ID','NUMBER');
    var $defaultCompileDirectory = 'compiled_DTD/';
    var $optionCompileDirectory;
    var $defaultForceCompile = false;
    var $optionForceCompile;
    var $optionName;
    var $defaultName;
    
    function TWP_DTD() {
        $this->setOption('default');
        if ($this->returnCompileStatus()) {
            $this->decompile();
        } else {
            $this->initialize();
            $this->compile();
        }
        $this->filterWhite();
    }
    
    //if the string to the first ? is equal to one of these
    
    function initialize() {
        
    }
    
    function filterWhite() {
        
    }
    
    function setOption($name, $value = true) {
        switch ($name) {
        case 'CompileDirectory':
            if (is_string($value) && (strpos($value,'/') == strlen($value) - 1)) {
                $this->optionCompileDirectory = $value;
            } else {
                trigger_error('Invalid value type, must be string with trailing slash', E_USER_WARNING);
            }
            break;
        case 'ForceCompile':
            if (is_bool($value)) {
                $this->optionForceCompile = $value;
            } else {
                trigger_error('Invalid value type, must be boolean', E_USER_WARNING);
            }
            break;
        case 'Name':
            if (is_string($value)) {
                $this->optionName = $value;
            } else {
                trigger_error('Invalid value type, must be string', E_USER_WARNING);
            }
            break;
        case 'default':
            if ($value) {
                $this->optionCompileDirectory = $this->defaultCompileDirectory;
                $this->optionForceCompile = $this->defaultForceCompile;
                $this->optionName = $this->defaultName;
            }
            break;
        default:
            trigger_error('Unrecognized option name', E_USER_WARNING);
        }
    }
    
    function _apply($elements = array(), $attributes = array(), $content = array()) {
        
        if (is_string($elements)) {
            $elements = (array) $elements;
        }
        
        foreach ($elements as $element) {
            if (!empty($attributes)) {
                if (empty($this->elementsї$element]ї'attributes'])) {
                    $this->elementsї$element]ї'attributes'] = array();
                }
                $this->elementsї$element]ї'attributes'] = 
                    array_merge($this->elementsї$element]ї'attributes'], $attributes);
            }
            $this->elementsї$element]ї'content'] = $content;
        }
        
        return $this->elementsї$element];
    }
    
    function unsetVal($needles,$haystack) {
        if (is_string($needles)) {
            $needles = array($needles);
        }
        foreach($needles as $needle) {
            while(($gotcha = array_search($needle,$haystack)) > -1) {
                unset($haystackї$gotcha]);
            }
        }
        return $haystack;
    }
    
    function checkContext($tag, $tag_tree, $check_all = false) {
        //Check if the tag exists in tag tree
        
        if (!isset($this->elementsї$tag])) {
             return false;
        }
        
        //Set the containing tag
        $last_tag = $tag_treeїsizeof($tag_tree) - 1];
        
        //Make sure tag is inside containing tag's content block
        if (!isset($this->elementsї$last_tag]ї'content']) || !in_array($tag,$this->elementsї$last_tag]ї'content'])) {
            return false;
        }
        
        return true;
    }
    
    function checkAttribute($attribute_array, $tag) {
        $new_attributes = array();
        
        if (isset($this->elementsї$tag]ї'attributes']) && is_array($this->elementsї$tag]ї'attributes'])) {
            foreach($this->elementsї$tag]ї'attributes'] as $key => $value) {
                if (isset($attribute_arrayї$key])) {
                    $new_attributesї$key] = $attribute_arrayї$key];
                }
            }
        }
        
        
        return $new_attributes;
    }
    
    function filterWhiteElements($elements) {
        $new_elements = array();
        foreach($elements as $element) {
            if (isset($this->elementsї$element])) {
                $new_elementsї$element] = $this->elementsї$element];
            }
        }
        return $this->elements = $new_elements;
    } 
    
    function filterWhiteAttributes($attributes, $keypair = false) {
        $new_elements = array();
        if (!$keypair) {
            foreach($this->elements as $element_name => $element) {
                $new_elementsї$element_name]ї'content'] = $elementї'content'];
                foreach($attributes as $attribute) {
                    if (isset($elementї'attributes']ї$attribute])) {
                        $new_elementsї$element_name]ї'attributes']ї$attribute] = $elementї'attributes']ї$attribute];
                    }
                }
            }
        } else {
            foreach($attributes as $element_name => $attribute_array) {
                $new_elementsї$element_name]ї'content'] = $this->elementsї$element_name]ї'content'];
                foreach($attribute_array as $attribute) {
                    if (isset($this->elementsї$element_name]ї'attributes']ї$attribute])) {
                        $new_elementsї$element_name]ї'attributes']ї$attribute] = $this->elementsї$element_name]ї'attributes']ї$attribute];
                    }
                }
            }
        }
        return $this->elements = $new_elements;
    }
    
    function filterWhiteContent($contents, $keypair = false) {
        $new_elements = array();
        if (!$keypair) {
            foreach($this->elements as $element_name => $element) {
                if (isset($this->elementsї$element_name])) {
                    $new_elementsї$element_name]ї'attributes'] = $elementї'attributes'];
                    $new_elementsї$element_name]ї'content'] = array();
                    foreach ($contents as $content) {
                        if (in_array($content, $elementї'content'])) {
                            $new_elementsї$element_name]ї'content']ї] = $content;
                        }
                    }
                }
            }
        } else {
            foreach($contents as $element_name => $content_array) {
               if (isset($this->elementsї$element_name])) {
                    $new_elementsї$element_name]ї'attributes'] = isset($this->elementsї$element_name]ї'attributes']) ? $this->elementsї$element_name]ї'attributes'] : array();
                    $new_elementsї$element_name]ї'content'] = array();
                    foreach ($content_array as $content) {
                        if (isset($this->elementsї$element_name]ї'content']) && in_array($content, $this->elementsї$element_name]ї'content'])) {
                            $new_elementsї$element_name]ї'content']ї] = $content;
                        }
                    }
                }
            }
        }
        return $this->elements = $new_elements;
    }
    
    function returnCompileFile() {
        return $this->optionCompileDirectory.$this->optionName.'.txt';
    }
    
    function compile() {
        $filename = $this->returnCompileFile();
        $serial = serialize($this->elements);
        $fh = fopen($filename,'w');
        fwrite($fh, $serial);
        fclose($fh);
        return $serial;
    }
    
    function decompile() {
        $filename = $this->returnCompileFile();
        $fh = fopen($filename,'r');
        $serial = fread($fh, filesize($filename));
        fclose($fh);
        $this->elements = unserialize($serial);
        return $serial;
    }
    
    function returnCompileStatus() {
        $filename = $this->returnCompileFile();
        if ($this->optionForceCompile) {
            return false;
        } elseif (empty($name)) {
            return false;
        } elseif (file_exists($filename) AND file_size($filename) > 0) {
            return true;
        } else {
            return false;
        }
    }
    
}

?>

Code: Select all

<?php


require_once('TWP_DTD.php');

$TWP_DTD = new TWP_DTD;

class UnitTestCase_TWP_DTD extends UnitTestCase
{
    
    function UnitTestCase_TWP_DTD() {
       
       $this->UnitTestCase('UnitTestCase_TWP_DTD');
       
    }
    
    function setUp() {
        global $TWP_DTD;
        $TWP_DTD->elements = array();
        $TWP_DTD->setOption('default');
    }
    
    function tearDown() {
        
    }
    
    function testWhite() {
        global $TWP_DTD;
        
        $attribute_list = array(
            'id' => array('type'=>array('ID'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'class' => array('type'=>array('CDATA'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'style' => array('type'=>array('CDATA'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'title' => array('type'=>array('CDATA'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onclick' => array('type'=>array('CDATA'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'ondblclick' => array('type'=>array('CDATA'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onmousedown' => array('type'=>array('CDATA'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onmouseup' => array('type'=>array('CDATA'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED)
        );
        
        $TWP_DTD->_apply(
            array('br','hr'),
            $attribute_list,
            array('br','hr','CDATA')
        );
        
        $this->assertEqual($TWP_DTD->elementsї'br']ї'content'],array('br','hr','CDATA'));
        $this->assertEqual($TWP_DTD->elementsї'br']ї'attributes'],$TWP_DTD->elementsї'hr']ї'attributes']);
        $this->assertEqual($TWP_DTD->elementsї'br']ї'attributes'],$attribute_list);
        
        $TWP_DTD->filterWhiteElements(array('br','polote'));
        $this->assertTrue(!isset($TWP_DTD->elementsї'hr']));
        $this->assertTrue(!isset($TWP_DTD->elementsї'polote']));
        $this->assertNotNull($TWP_DTD->elementsї'br']);
        
        $TWP_DTD->_apply(
            array('hr'),
            $attribute_list,
            array('br','hr')
        );
        
        $this->assertNotNull($TWP_DTD->elementsї'hr']);
        $this->assertEqual($TWP_DTD->elementsї'hr']ї'attributes'],$attribute_list);
        
        $TWP_DTD->filterWhiteAttributes(array('id','style','title','class','goofus'));
        
        $this->assertNotNull($TWP_DTD->elementsї'hr']ї'attributes']ї'id']);
        $this->assertTrue(!isset($TWP_DTD->elementsї'hr']ї'attributes']ї'onclick']));
        $this->assertTrue(!isset($TWP_DTD->elementsї'hr']ї'attributes']ї'goofus']));
        
        $TWP_DTD->filterWhiteAttributes(
            array(
                'br' => array(
                    'style','class','nu'
                ),
                'hr' => array(
                    'style','class','id','title'
                )
            ),
            true
        );
        
        
        $this->assertTrue(!isset($TWP_DTD->elementsї'br']ї'attributes']ї'id']));
        $this->assertNotNull($TWP_DTD->elementsї'hr']ї'attributes']ї'id']);
        $this->assertTrue(!isset($TWP_DTD->elementsї'br']ї'attributes']ї'nu']));
        
        $this->assertTrue(in_array('CDATA',$TWP_DTD->elementsї'br']ї'content']));
        $this->assertTrue(in_array('br',$TWP_DTD->elementsї'br']ї'content']));
        
        $TWP_DTD->filterWhiteContent(
            array('CDATA')
        );
        
        $this->assertTrue(in_array('CDATA',$TWP_DTD->elementsї'br']ї'content']));
        $this->assertTrue(!in_array('br',$TWP_DTD->elementsї'br']ї'content']));
        
        $this->assertTrue(!isset($TWP_DTD->elementsї'br']ї'attributes']ї'id']));
        $this->assertNotNull($TWP_DTD->elementsї'hr']ї'attributes']ї'id']);
        
        $TWP_DTD->filterWhiteContent(
            array(
                'br' => array(
                    'CDATA'
                ),
                'hr' => array(
                    'broggle'
                ),
                'asdf' => array(
                    'CDATA'
                )
            ),
            true
        );
        
        $this->assertTrue(in_array('CDATA',$TWP_DTD->elementsї'br']ї'content']));
        $this->assertTrue(!in_array('CDATA',$TWP_DTD->elementsї'hr']ї'content']));
        $this->assertTrue(!in_array('broggle',$TWP_DTD->elementsї'hr']ї'content']));
        
    }
    
    function testCompile() {
        global $TWP_DTD;
        
        $new_object = $TWP_DTD;
        
        $TWP_DTD->compile();
        $TWP_DTD->decompile();
        
        $this->assertEqual($TWP_DTD, $new_object );
    }
    
    
    
}



?>

Code: Select all

<?php

require_once('TWP_DTD.php');

class TWP_DTD_HTML401 extends TWP_DTD
{
    
    var $defaultName = 'TWP_DTD_HTML401';
    var $defaultForceCompile = true;
    
    function TWP_DTD_HTML401() {
        $this->TWP_DTD();
    }
    
    function initialize() {
        
        //////////////
        //Tag Grouping
        $heading = array('h1','h2','h3','h4','h5','h6');
        $list = array('ul','ol');
        $preformatted = array('pre');
        $fontstyle = array('tt','i','b','big','small');
        $phrase = array('em','strong','dfn','code','samp','kbd','var','cite','abbr','acronym');
        $special = array('a','img','br','q','sub','sup','span','bdo','object','script','map');
        $formctrl = array('input','select','textarea','label','button');
        $inline = array_merge(array('PCDATA'), $fontstyle, $phrase,$special, $formctrl);
        $block = array_merge(array('p','dl','div','blockquote','hr','table','address'
        ,'noscript','form','fieldset'),$heading,$list,$preformatted);
        $flow = array_merge($block, $inline);
        $preExclusion = array('img','object','big','small','sub','sup');
        
        /////////////////////////
        //Container Type Grouping
        $e_ListClass = array('CDATA?ListClass');
        $e_ListURI = array('CDATA?ListURI');
        $e_NamedLinkEnd = array('CDATA?NamedLinkEnd');
        $e_ReferenceUsemap = array('CDATA?ReferenceUsemap');
        $e_PropertyValue = array('CDATA?PropertyValue');
        $HTMLFrameset = array('IGNORE');
        $ContentType = array('CDATA?ContentType');
        $ContentTypes = array('CDATA?ContentTypes');
        $Charset = array('CDATA?Charset');
        $Chrasets = array('CDATA?Charsets');
        $LanguageCode = array('NAME?LanguageCode');
        $Character = array('CDATA?Character');
        $LinkTypes = array('CDATA?LinkTypes');
        $MediaDesc = array('CDATA?MediaDesc');
        $URI = array('CDATA?URI');
        $Datetime = array('CDATA?Datetime');
        $Script = array('CDATA?Script');
        $StyleSheet = array('CDATA?StyleSheet');
        $Text = array('CDATA?Text');
        $headMisc = array('script','style','meta','link','object');
        $Shape = array('rect','circle','poly','default');
        $Coords = array('CDATA?Coords');
        $Length = array('CDATA?Length');
        $MultiLength = array('CDATA?MultiLength');
        $MultiLengths = array('CDATA?MultiLengths');
        $Pixels = array('CDATA?Pixels');
        
        ////////////
        //Attributes
        $coreattrs = array(
            'id' => array('type'=>array('ID'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'class' => array('type'=>$e_ListClass,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'style' => array('type'=>$StyleSheet,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'title' => array('type'=>$Text,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED)
        );
        
        $i18n = array(
            'lang' => array('type'=>$LanguageCode,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'dir' => array('type'=>array('ltr','rtl'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED)
        );
        
        $events = array (
            'onclick' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'ondblclick' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onmousedown' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onmouseup' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onmouseover' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onmousemove' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onmouseout' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onkeypress' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onkeydown' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED),
            'onkeyup' => array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED)
        );
        
        $reserved = array();
        $attrs = array_merge($coreattrs,$i18n,$events);
        
        
        
        /////////////////////////
        //User Defined Attributes
        $a_accesskey= array('accesskey'=>array('type'=>$Character,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_archive  = array('archive'=>array('type'=>$e_ListURI,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_charset  = array('charset'=>array('type'=>$Charset,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_coords   = array('coords'=>array('type'=>$Coords,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_classid  = array('classid'=>array('type'=>$URI,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_codebase = array('codebase'=>array('type'=>$URI,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_codetype = array('codetype'=>array('type'=>$ContentType,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_cite     = array('cite'=>array('type'=>$URI,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_data     = array('data'=>array('type'=>$URI,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_datetime = array('datatime'=>array('type'=>$Datetime,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_declare  = array('declare'=>array('type'=>array('declare'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_height   = array('height'=>array('type'=>$Length,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_lang     = array('lang'=>array('type'=>$LanguageCode,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_href     = array('href'=>array('type'=>$URI,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_hreflang = array('hreflang'=>array('type'=>$LanguageCode,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_ismap    = array('ismap'=>array('type'=>array('ismap'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_id       = array('id'=>array('type'=>array('ID'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_longdesc = array('longdesc'=>array('type'=>$URI,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_media    = array('media'=>array('type'=>$MediaDesc,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_nohref   = array('nohref'=>array('type'=>array('nohref'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_name     = array('name'=>array('type'=>$e_NamedLinkEnd,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_onload   = array('onload'=>array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_onunload = array('onunload'=>array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_onblur   = array('onblur'=>array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_onfocus  = array('onfocus'=>array('type'=>$Script,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_rel      = array('rel'=>array('type'=>$LinkTypes,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_rev      = array('rev'=>array('type'=>$LinkTypes,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_shape    = array('shape'=>array('type'=>$Shape,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED,'value'=>'rect'));
        $a_standby  = array('standby'=>array('type'=>$Text,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_type     = array('type'=>array('type'=>$ContentType,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_tabindex = array('tabindex'=>array('type'=>array('NUMBER'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_usemap   = array('usemap'=>array('type'=>$URI,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_value    = array('value'=>array('type'=>$e_PropertyValue,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        $a_valuetype= array('valuetype'=>array('type'=>array('DATA','REF','OBJECT'),'default'=>TWP_DTD_ATTRIBUTE_IMPLIED,'value'=>'DATA'));
        $a_width    = array('width'=>array('type'=>$Length,'default'=>TWP_DTD_ATTRIBUTE_IMPLIED));
        
        
        /////////////////////////
        //Tag Definitions
        
        $this->_apply(
            array_merge($fontstyle, $phrase),
            $attrs,
            $inline
        );
        
        $this->_apply(
            array('sub','sup'),
            $attrs,
            $inline
        );
        
        $this->_apply(
            array('span'),
            array_merge($attrs, $reserved),
            $inline
        );
        
        $this->_apply(
            array('bdo'),
            array_merge($coreattrs,$a_lang,
                array(
                    'dir'=>array('type'=>array('ltr','rtl'),'default'=>TWP_DTD_ATTRIBUTE_REQUIRED)
                )
            ),
            $inline
        );
        
        $this->_apply(
            array('br'),
            $coreattrs,
            array()
        );
        
        
        $this->_apply(
            array('body'),
            array_merge($attrs,array_merge($a_onload,$a_onunload)),
            array_merge($block,array('script','ins','del'))
        );
        
        $this->_apply(
            array('address'),
            $attrs,
            $inline
        );
        
        $this->_apply(
            array('div'),
            array_merge($attrs,$reserved),
            $flow
        );
        
        $this->_apply(
            array('a'),
            array_merge($attrs,$a_charset,$a_type,$a_name,$a_href,$a_hreflang,
                $a_rel,$a_rev,$a_accesskey,$a_shape,$a_coords,$a_tabindex,$a_onfocus,
                $a_onblur
            ),
            $this->unsetVal(array('a'),$inline)
        );
        
        $this->_apply(
            array('map'),
            array_merge(
                $attrs,
                array(
                    'name'=>array('type'=>$e_ReferenceUsemap,'default'=>TWP_DTD_ATTRIBUTE_REQUIRED
                    )
                )
            ),
            array_merge($block,array('AREA'))
        );
        
        $this->_apply(
            array('area'),
            array_merge(
                $attrs,$a_shape,$a_coords,$a_href,$a_nohref,$a_tabindex,$a_accesskey,$a_onfocus,$a_onblur,
                array(
                    'alt'=>array('type'=>$Text,'default'=>TWP_DTD_ATTRIBUTE_REQUIRED)
                )
            ),
            array()
        );
        
        $this->_apply(
            array('link'),
            array_merge(
                $attrs,$a_charset,$a_href,$a_hreflang,$a_type,$a_rel,$a_rev,$a_media
            ),
            array()
        );
        
        $this->_apply(
            array('img'),
            array_merge(
                $attrs,$a_longdesc,$a_name,$a_height,$a_width,$a_usemap,$a_ismap,
                array(
                    'src'=>array('type'=>$URI,'default'=>TWP_DTD_ATTRIBUTE_REQUIRED),
                    'alt'=>array('type'=>$Text,'default'=>TWP_DTD_ATTRIBUTE_REQUIRED)
                )
            ),
            array()
        );
        
        $this->_apply(
            array('object'),
            array_merge(
                $attrs,$a_classid,$a_declare,$a_codebase,$a_data,$a_type,
                $a_codetype,$a_archive,$a_standby,$a_height,$a_width,$a_usemap,
                $a_name, $a_tabindex, $reserved
            ),
            array_merge(array('param'),$flow)
        );
        
        $this->_apply(
            array('param'),
            array_merge(
                $a_id,$a_value,$a_valuetype,$a_type,
                array(
                    'name'=>array('type'=>$e_NamedLinkEnd,'default'=>TWP_DTD_ATTRIBUTE_REQUIRED)
                )
            ),
            array()
        );
        
        $this->_apply(array('hr'),$attrs,array());
        $this->_apply(array('p'),$attrs,$inline);
        $this->_apply($heading,$attrs,$inline);
        
        $this->_apply(
            array('pre'),
            $attrs,
            $this->unsetVal($preExclusion,$inline)
        );
        
        $this->_apply(
            array('q'),
            array_merge($attrs,$a_cite),
            $inline
        );
        
        $this->_apply(
            array('blockquote'),
            array_merge($attrs,$a_cite),
            array_merge($block,array('script'))
        );
        
        $this->_apply(
            array('ins','del'),
            array_merge($attrs,$a_cite,$a_datetime),
            $flow
        );
        
        $this->_apply(array('dl'),$attrs,array('dt','dd'));
        $this->_apply(array('dt'),$attrs,$inline);
        $this->_apply(array('dt'),$attrs,$flow);
        $this->_apply(array('ol'),$attrs,array('li'));
        $this->_apply(array('ul'),$attrs,array('li'));
        $this->_apply(array('li'),$attrs,$flow);
        
        
    }
    
}

?>

Code: Select all

<?php

require_once('TWP_DTD_HTML401.php');

$TWP_DTD_HTML401 = new TWP_DTD_HTML401;

class UnitTestCase_TWP_DTD_HTML401 extends UnitTestCase
{
    
    function UnitTestCase_TWP_DTD_HTML401() {
       
       $this->UnitTestCase('UnitTestCase_TWP_DTD_HTML401');
       
    }
    
    function setUp() {
        global $TWP_DTD_HTML401;
        
    }
    
    function tearDown() {
    }
    
    function testNesting() {
        
        global $TWP_DTD_HTML401;
        
        $this->assertTrue($TWP_DTD_HTML401->checkContext('table',array('div','div')),'div div table - expect true');
        $this->assertTrue($TWP_DTD_HTML401->checkContext('p',array('div','blockquote')), 'div blockquote b - expect true');
        $this->assertTrue($TWP_DTD_HTML401->checkContext('li',array('div','ol')), 'div ol li - expect true');
        $this->assertTrue($TWP_DTD_HTML401->checkContext('tr',array('table')), 'table tr - expect true');
        $this->assertTrue($TWP_DTD_HTML401->checkContext('span',array('div','b')), 'div b span - expect true');
        $this->assertTrue($TWP_DTD_HTML401->checkContext('div',array('div')), 'div div - expect true');
        $this->assertTrue($TWP_DTD_HTML401->checkContext('div',array('body')), 'body div - expect true');
        
        $this->assertFalse($TWP_DTD_HTML401->checkContext('div',array('p')), 'p div - expect false');
        $this->assertFalse($TWP_DTD_HTML401->checkContext('moo',array('b')), 'b moo - expect false');
        $this->assertFalse($TWP_DTD_HTML401->checkContext('div',array('span')), 'span div - expect false');
        $this->assertFalse($TWP_DTD_HTML401->checkContext('b',array('table')), 'table b - expect false');
        
    }
    
    function testAttribute() {
        
        global $TWP_DTD_HTML401;
        
        $this->assertEqual(
            $TWP_DTD_HTML401->checkAttribute(
                array(
                    'style'=>'font-weight:900;'
                ),
                'b'
            ),
            array(
                'style'=>'font-weight:900;'
            )
        );
        
        $this->assertEqual(
            $TWP_DTD_HTML401->checkAttribute(
                array(
                    'onclick'=>'javascript:alert(\'foo\')',
                    'href'=>'http://www.google.com/',
                    'title'=>'Don\'t Click Here',
                    'bobby'=>'asdf'
                ),
                'a'
            ),
            array(
                'onclick'=>'javascript:alert(\'foo\')',
                'href'=>'http://www.google.com/',
                'title'=>'Don\'t Click Here'
            )
            
        );
        
        
    }
    
}


?>
Yes, I know it's a bit hefty. But unavoidable... dang.
Post Reply