使用PHP XMLReader检测XML自关闭标记

时间:2017-08-02 09:35:07

标签: php xml libxml2 xmlreader

我想使用XMLReader解析一个XML文档。我有一个包含所有常量的案例开关。但是,如果标签是自动关闭的,则XMLReader仅触发ELEMENT,而不是ELEMENT,而不是像预期的那样触发END_ELEMENT。

通过类属性检测$ isEmptyElement也不起作用,因为标记具有属性。

因此我的问题:如何在PHP中使用XMLReader检测自关闭XML标记?

相关但没有解决方案: XmlReader - Self-closing element does not fire a EndElement event?

示例节点:

<mynode name="somenamestring" code="intstring" option="intstring3"/>

我的代码:

$xmlReader->open($url,NULL);
$xmlWriter = new XMLWriter();
$xmlWriter->openMemory();
$xmlWriter->startDocument('1.0', 'UTF-8');
$xmlWriter->setIndent(true);
$xmlWriter->setIndentString('    ');
while ($xmlReader->read()) {
    switch ($xmlReader->nodeType) {
        case 1: #element
            $xmlWriter->startElement($xmlReader->name);
            if ($xmlReader->hasAttributes) {
                while ($xmlReader->moveToNextAttribute()) {
                    $xmlWriter->writeAttribute($xmlReader->name,$xmlReader->value);
                }
            }
            if ($xmlReader->isEmptyElement) {
                $xmlWriter->endElement();
            }
            break;

        case 3: #text
            $xmlWriter->text($xmlReader->value);
            break;

        case 4: #cdata
            $xmlWriter->writeCData($xmlReader->value);
            break;

        case 14: #whitespace
            break;

        case 15: #end element
            $xmlWriter->endElement();
            break;

        default:
            print('[WARN] NodeType not in case-switch: '.(string)$xmlReader->nodeType."\n");
            break;
    }
}

1 个答案:

答案 0 :(得分:4)

  

通过类属性检测$ isEmptyElement也不起作用,因为标记具有属性。

这完全错了。带有属性的空元素仍为空,$isEmptyElement将反映出这一点。代码的问题在于您在移动到属性后测试$isEmptyElement。这会将当前节点更改为属性节点,该节点不是空元素。以下内容应该有效:

        $isEmpty = $xmlReader->isEmptyElement;
        if ($xmlReader->hasAttributes) {
            while ($xmlReader->moveToNextAttribute()) {
                ...
            }
        }
        if ($isEmpty) {
            $xmlWriter->endElement();
        }

或者,或者:

        if ($xmlReader->hasAttributes) {
            while ($xmlReader->moveToNextAttribute()) {
               ...
            }
            $xmlReader->moveToElement();
        }
        if ($xmlReader->isEmptyElement) {
            $xmlWriter->endElement();
        }