如何使用PHP检查XML标记是否为空?

hen*_*ght 2 php xml simplexml

如果我的XML文件的内容是:

<query>
    <results/>
</query>
Run Code Online (Sandbox Code Playgroud)

我正在使用,$obj = simplexml_load_file( $filepath )所以存储了文件内容$obj.

如您所见,结果标记为空,它没有文本或属性.

如何检查结果标记是否为空?

我想过这样做,if ( empty( $obj->results ) )但我不认为这是正确的语法.

hak*_*kre 5

如您所见,结果标记为空,它没有文本或属性.

如何检查结果标记是否为空?

在XML中,根据定义,元素在以下情况下被视为:

[定义:没有内容的元素被认为是空的.]空元素的表示形式是紧跟在结束标记之后的开始标记,或者是空元素标记.[定义:一个空元素标签采用一种特殊形式:] [...它遵循空元素标签的定义,后面加上"/>"]

无论是<results/>或者<results></results>,在XML中称为空元素.请注意,这<results foo="bar"/>也是一个空元素.重要的是此处元素的内容,而不是属性.

那么现在在SimpleXML中,如何确定元素是否没有内容?这实际上非常麻烦.我更倾向于依靠DOM姐妹库,那么它是相当直接的:

<?php

$buffer = <<<XML
<query>
    <results/>
    <results></results>
</query>
XML;

$xml = simplexml_load_string($buffer);

$element = $xml->results[0];
var_dump(dom_import_simplexml($element)->childNodes->length);

$element = $xml->results[1];
var_dump(dom_import_simplexml($element)->childNodes->length);
Run Code Online (Sandbox Code Playgroud)

这个例子只是将$bufferSimpleXML中的小XML文档解析成$xml.然后results通过SimpleXML的DOM姐妹库检查第一个和第二个元素的子数.如果子项数为零,则该元素为空.

$isEmpty = !dom_import_simplexml($element)->childNodes->length;
Run Code Online (Sandbox Code Playgroud)

随着"纯"的SimpleXML你有因为有限的模型中的问题简单简单的 XML提供了这里.例如,SimpleXML不考虑注释,如果它们不是叶节点,则访问文本节点时会遇到问题.您可以(但不能像我在DOM中所示)使用xpath查询解决SimpleXML中的一些限制.例如,如果元素不为空,则仅匹配元素,因此再次计数0表示空元素:

var_dump(count($element->xpath('(.)[./node()]')));
Run Code Online (Sandbox Code Playgroud)

xpath在这里

(.)[./node()]
Run Code Online (Sandbox Code Playgroud)

表示:如果当前元素具有子节点,则仅获取当前元素.因此,如果不为空,则查询返回一个元素,如果为空则返回零元 这是在SimpleXML中检查空元素的一种方法.您可以扩展此原则以检查属性:

(.)[./node()|./@*]
Run Code Online (Sandbox Code Playgroud)

也许有点神秘.但要回答你的问题,那就是要走的路:

$isEmpty = !count($element->xpath('(.)[./node()|./@*]'));
Run Code Online (Sandbox Code Playgroud)

即:具有零属性的空XML元素.

希望这有用,并为您迄今尚未探索过的领域提供一些启示.


这是我在编写答案时创建的一些示例代码沙箱样式(也可以在线试用):

<?php
/**
 * How to check if XML tag is empty using PHP?
 * @link http://stackoverflow.com/a/29614074/367456
 */

$buffer = <<<XML
<query>
    <results/>
    <results afri="cloa&lt;a"/>
    <results><!-- help --></results>
    <results><!-- help -->1<test>222</test></results>
</query>
XML;

$xml = simplexml_load_string($buffer);

$element = $xml->results[0];

// $path   = '*';
// $path   = '.';
// $path   = 'self::*';
// $path   = 'self::*[1]';
// $path   = 'descendant::node()';
// $path   = 'self::*[descendant::node()]';
// $path   = '(.)[descendant::node()]';
// $path   = '(.)[.//node()]';
// $path   = '(.)[child::node()]';
$path   = '(.)[./node()]';
$result = $element->xpath($path);
var_dump(count($result));
foreach ($result as $node) {
    echo $node->asXML(), "\n";
}
echo "------\n";

var_dump(count($element->xpath('(.)[./node()]')));
var_dump(count($element->xpath('(.)[./node()|./@*]')));

var_dump(strlen($element) + $element->children()->count());


$element = $xml->results[1];
var_dump(dom_import_simplexml($element)->childNodes->length);

$dom = dom_import_simplexml($element);
$dom->appendChild($dom->ownerDocument->createTextNode(""));

var_dump($element->children()->count());
Run Code Online (Sandbox Code Playgroud)