PHP XML Parser xml_set_default_handler拆分特殊字符

时间:2012-01-02 15:49:48

标签: php xml-parsing

PHP的XML解析器在遇到字符串中的特殊字符时会调用默认处理函数两次,因此会拆分字符串。我试图在XML代码中使用不同的编码以及PHP代码来解决它,但它仍然会拆分字符串:

$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);

xml_set_element_handler($parser, "startTag", "endTag");
xml_set_default_handler($parser, 'defaultHandler');


function startTag($p, $name, $attributes)
{

}

function endTag($p, $name)
{

}

function defaultHandler($parser, $data)
{
    if(strlen(trim($data)) > 0)
        echo '[' . $data . ']' . '<br />';
}                                                                                                                        

XML示例:

<variable name="GZH29" type="integer">
    <label>This is a small test with a special ë character. Let's try an ë character too</label>
</variable>

人们会期待:

[This is a small test with a special ë character. Let's try an ë character too]

但结果是

[This is a small test with a special ]
[ë character. Let's try an ë character too]

我不想分割线,所以不知道解决方案是什么?

1 个答案:

答案 0 :(得分:0)

xml_parser确实在这里创建了多个事件,原因我没有完全理解,我认为这是因为编码自动检测。

您可以通过创建自己的解析器类来处理它。无论如何,这通常是有用的,不仅仅是在这种情况下。但是对于这种情况,特别是你可以将标签的文本放在一起,这些文本分布在多个事件中。

基本工作是使回调函数成为类的公共函数,然后注册这些函数。

然后每次打开label标记时,都会重置临时存储。当文本出现时,它会被添加到该临时存储中。如果label标记然后关闭,您可以将此文本传递给新的“事件”,这次是您要查找的函数的文本:

$variableParser = new VariableParser($parser);

$file = 'data://,'.$xml;
$fp = fopen($file, 'r');
while(!feof($fp)) { $data = fread($fp, 4096); xml_parse($parser, $data, feof($fp)); }


class VariableParser
{
    private $label = ''; # place for the label text
    public function doLabel($text)
    {
        printf("[%s]<br />\n", $text);
    }
    public function __construct($parser = NULL)
    {
        if ($parser) $this->register($parser);
    }
    public function register($parser)
    {
        xml_set_element_handler($parser, array($this, "startTag"), array($this, "endTag"));
        xml_set_default_handler($parser, array($this, 'defaultHandler'));
    }

    public function startTag($parser, $name, $attributes)
    {
        if ($name === 'label') $this->label = '';
    }

    function endTag($parser, $name)
    {
        if ($name === 'label')
        {
            $this->doLabel($this->label);
            $this->label = '';
        }
    }

    function defaultHandler($parser, $data)
    {
        if(strlen(trim($data)) > 0)
        {
            $this->label .= $data;
        }
    }
}