【问题标题】:Why does PHP treats this DOM object like an array?为什么 PHP 把这个 DOM 对象当作一个数组来对待?
【发布时间】:2019-02-14 13:21:32
【问题描述】:

我正在学习本教程:

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

文字=

来自 = 贾尼

文字=

标题 = 提醒

文字=

body = 这个周末别忘了我!

文字=

【问题讨论】:

  • 那个对象是Iterable,就像一个数组是Iterable

标签: php xml domparser php-7.3


【解决方案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遍历该类。

【讨论】:

    【解决方案2】:

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

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

    Traversable 允许您使用foreach

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

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

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

    Countable 允许您使用count($nodeList) 而不是$nodeList-&gt;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";
    }
    

    【讨论】:

      猜你喜欢
      • 2021-02-16
      • 1970-01-01
      • 2019-12-29
      • 2013-11-02
      • 2010-10-26
      • 1970-01-01
      • 2015-11-09
      • 2013-01-31
      相关资源
      最近更新 更多