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

Why does PHP treats this DOM object like an array?

我正在学习本教程:

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

遍历 XML 部分是有问题的。 PHP 出于某种原因将 DOM 对象视为数组。此外,var_dump returns 除了长度之外没有任何关于对象属性的信息,但是程序输出看起来像是凭空冒出来的。 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 转储函数returns 这个:

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

但是执行的代码是这样的:

text =

to = Tove

text =

from = Jani

text =

heading = Reminder

text =

body = Don't forget me this weekend!

text =

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视觉冲击力最强。大大降低了调用的复杂度。但这只是第一个好处。您可以使用类型提示或 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";
}

childNodesDOMNodeList 类型的 属性。 var_dump 不显示任何内容的原因很简单,因为 var_dump 只显示那些 class 开发人员通过调用 [=18= 这样的 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 class 的结构。

您可以遍历 DOMNodeList 的原因是因为它实现了 Traversable 接口,该接口表明 class 可以通过使用 foreach 进行遍历。