为什么PHP将此DOM对象视为数组?

时间:2019-02-14 13:21:32

标签: php xml domparser php-7.3

我正在关注本教程:

  

https://www.w3schools.com/php/php_xml_dom.asp

遍历XML部分是有问题的。 PHP由于某种原因将DOM对象视为数组。此外,var_dump除了长度以外,不返回任何有关对象属性的信息,但是程序输出看起来像是从哪里冒出来的。 foreach可以某种方式遍历对象吗?如果可以的话,因为var_dump没有显示它们,这些属性(节点名称和节点值)包含在哪里?

$xml=new DOMDocument ();
$xml->load('note.xml');

$array_of_nodes=$xml->documentElement->childNodes;

var_dump($array_of_nodes);

foreach($array_of_nodes as $item) {
    echo $item->nodeName."  ".$item->nodeValue."<br>";
}

Var dump函数返回以下内容:

  

object(DOMNodeList)#3(1){[“ length”] => int(9)} #text

但是执行的代码如下:

  

文本=

     

to = Tove

     

文本=

     

from = Jani

     

文本=

     

标题=提醒

     

文本=

     

身体=这个周末别忘了我!

     

文本=

2 个答案:

答案 0 :(得分:1)

childNodesDOMNodeList类型的属性。 var_dump不显示任何内容的原因仅仅是因为var_dump仅显示开发人员通过调用

这样的C函数声明的类属性。
ZEND_API int zend_declare_property(...)
ZEND_API int zend_declare_property_null(...)
ZEND_API int zend_declare_property_bool(...)
ZEND_API int zend_declare_property_long(...)
ZEND_API int zend_declare_property_double(...)
ZEND_API int zend_declare_property_string(...)
ZEND_API int zend_declare_property_stringl(...)

来源:akond的回答:Why doesn't var_dump work with DomDocument objects, while print($dom->saveHTML()) does?

也就是说,DOM扩展的开发人员选择不公开DOMNodeList类的结构。

之所以可以通过DOMNodeList进行迭代,是因为它实现了Traversable接口,该接口表示可以使用foreach通过该类进行迭代。

答案 1 :(得分:0)

DOMNodeList实现了几个接口:TraversableArrayAccessCountable。这允许使用通用语法来访问列表中的节点对象。没有它们,您将需要使用如下特定的方法和属性:

for ($i = 0; $c = $nodeList->length; $i < $c; $i++) {
  $node = $nodeList->item($i);
  //...
}

Traversable允许您使用foreach

foreach ($nodeList as $node) {
  //...
}

ArrayAccess允许您使用数组语法按索引访问节点,它将->item(...)调用替换为[...]

if (isset($nodeList[0])) {
  $node = $nodeList[0];
  //...
}

Countable允许您使用count($nodeList)代替$nodeList->length

Traversable最具视觉冲击力。它大大降低了呼叫的复杂性。但这仅是第一个好处。您可以使用typehints或instanceof针对接口进行验证。这样可以使您的代码脱钩,使其更健壮和可重用。

但是,如果您使用Xpath表达式,则通过DOM循环更容易。如果您以前使用过CSS选择器,则可以将Xpath表达式视为更强大的兄弟。

$document = new DOMDocument();
$document->load('note.xml');
$xpath = DOMXpath($document);

foreach($xpath->evaluate('/note') as $item) {
    echo 'To: ', $xpath->evaluate('string(to)', $item), "\n";
    echo 'From: ', $xpath->evaluate('string(from)', $item), "\n";
    echo 'Title: ', $xpath->evaluate('string(heading)', $item), "\n";
    echo 'Text: ', $xpath->evaluate('string(body)', $item), "\n";
}