tetsunosukeのnotebook

tetsunosukeのメモです

HTMLをSAXで解釈するアレをごにょごにょ。

以前GoogleNotebook解析のためにどんな感じでSAXで読むんだろ?って書いたものの続編。

<?php
require_once 'XML/XML_HTMLSax.php';

class MyHandler{
    var $elements;
    function MyHandler()
    {
        $this->elements = array();
    }


    /** 
     * 要素を開いた段階でその情報(要素の属性と名前)を
     * 連想配列に突っ込む。
     * @todo その際に属性がidやclassなどの重要なもの以外は
     *       全て削除しても良いのではないか。
     */
    function openHandler( &$parser, $name, $attrs )
    {
        array_push($this->elements, array($name=>$attrs));
    }

    /** 
     * 要素を閉じるときにその直前の内容を保持している配列から
     * 処理済である末尾の要素を削除する
     */
    function closeHandler( &$parser, $name )
    {
        array_pop($this->elements);
    }


    /**
     * テキストノードの解釈。
     * 自分自身が現在どこを処理対象としているかで各関数の
     * 判定を行い、その判定が正しければ内容を出力
     */
    function dataHandler( &$parser, $data )
    {

        // 期待する構造のあるデータが取得できたら出力
        if($this->_getSomeTextNode()){
            echo $data;
        }
    }

    /**
     * 連想配列形式で指定したHTMLのノードが含まれるかどうかを返す
     * 取得したいノードごとに$expectedArrayを作る
     * おそらくもう少し「ゆるい」指定にしないとキツいか・・・
     * 多分、idとかしか使わないだろう・・・
     * @see openHandler
     */
    function _getSomeTextNode()
    {
        $expectedArray = 
            array(
                array('root' => array()),
                array('element' => 
                    array(
                        'attr' => 'test',
                        'id'   => 'second'
                    )
                )
            );

        return $this->_isValidArray($this->elements, $expectedArray);
    }

    /**
     * 二つの連想配列がデータとして等しいかどうかを返す
     * @todo 多分serializeしたものを小文字で比較した方が良い
     */
    function _isValidArray($inputArray, $expectedArray)
    {
    /**
     * Example
     *   $expectedArray = array(
     *       array('root' => array()),
     *       array('element' => array('attr' =>  'test', 'id' => 'second'))
     *   );
     */
        return $inputArray === $expectedArray;

    }
}


// Parsing
$handler = new MyHandler();

$parser =& new XML_HTMLSax();
$parser->set_object($handler);
$parser->set_option('XML_OPTION_TRIM_DATA_NODES');

// handlers
$parser->set_element_handler('openHandler', 'closeHandler');
$parser->set_data_handler('dataHandler');
//$contents = file_get_contents("googlenote.html");
$contents = <<<DOC
<root>
<element id="first" attr="attribute">
<child>text</child>
</element>
<element attr="test" id="second">
textnode
</element>
AAAAAAAAAAAAAAAAA
</root>
DOC;

$parser->parse($contents);
?>

なにかこう、ものすごくbrとかの「閉じてないタグ」が問題を引き起こしていることに気づいた。