使用 PHP XMLReader 检测 XML 自闭标签

Posted

技术标签:

【中文标题】使用 PHP XMLReader 检测 XML 自闭标签【英文标题】:Detect XML self closing tags with PHP XMLReader 【发布时间】:2018-01-09 10:52:59 【问题描述】:

我想使用 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】:

通过类属性 $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();
        

【讨论】:

如果是这样的话我会很高兴,不幸的是,对我来说它为以下节点返回 false: 你呢创建阅读器时设置任何选项?但是,$hasValue 是正确的,但这并没有帮助,因为有很多没有价值的非自闭合标签。 那么我一定是犯了其他错误。我添加了我的代码,你能看一下吗?

以上是关于使用 PHP XMLReader 检测 XML 自闭标签的主要内容,如果未能解决你的问题,请参考以下文章

PHP XMLReader 获取父节点?

XmlReader - 自关闭元素不会触发 EndElement 事件?

PHP XMLReader 读取、编辑节点、编写 XMLWriter

php xml 文件读取 XMLReader

PHP XMLReader 解析行 2 次

让 PHP 的 XMLReader 不会在无效文档中抛出 php 错误