解析嵌套XML节点的属性值

时间:2015-09-25 16:33:56

标签: php xml parsing

我试图在PHP中解析XML,但我遇到了问题。

所以XML看起来像这样(简化)

<weatherdata>
 <forecast>
 <tabular>
   <time from="2015-09-25T20:00:00" to="2015-09-25T23:00:00" period="3">
      <symbol number="4" numberEx="4" name="Cloudy" var="04" />
   </time>
   <time from="2015-09-25T23:00:00" to="2015-09-26T05:00:00" period="0">
      <symbol number="9" numberEx="46" name="Light rain" var="46" />
   </time>

.....

我能够从这样的值加载所有时间 - &gt;:

foreach($xml->forecast->tabular as $forecastItem){
    $attr = $forecastItem->attributes();
    $froms[] = $attr['from'];       
}

但后来我尝试加载符号的name属性,如下所示:

foreach($xml->forecast->tabular as $forecastItem){
    $attr = $forecastItem->attributes();
    $froms[] = $attr['from'];
    $attr2 = $forecastItem->symbol->attributes();
    $names[] = $attr2['name'];
}

它显示了一个错误,即main()节点不存在。基本上我想做的是将所有名称加载到数组中,就像froms一样。

2 个答案:

答案 0 :(得分:2)

您收到的完整错误消息是:

  

警告:main():节点不再存在于...

后跟以下代码的行号:

$attr2 = $forecastItem->symbol->attributes();

您可能不清楚错误实际上是什么。为了更好地理解它,你必须对你在这里使用的 SimpleXmlElement 的内部工作有所了解。

如果你通过它的名字访问子元素,那么就像这里的<symbol>元素一样:

$forecastItem->symbol

SimpleXML扩展将动态创建节点作为临时节点,只要不存在这样的子元素。这样做是为了允许动态添加它。例如:

$forecastItem->symbol = 'hello world!';

echo $forecastItem->asXML();

会显示:

<tabular>
   <time from="2015-09-25T20:00:00" to="2015-09-25T23:00:00" period="3">
      <symbol number="4" numberEx="4" name="Cloudy" var="04"/>
   </time>
   <time from="2015-09-25T23:00:00" to="2015-09-26T05:00:00" period="0">
      <symbol number="9" numberEx="46" name="Light rain" var="46"/>
   </time>
 <symbol>hello world!</symbol></tabular>
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

这也解释了为什么你的代码不起作用。由于符号元素只是暂时的,并且您没有设置它,SimpleXML只是试图告诉您,此节点不再存在 。当你尝试从不存在的节点中读取属性时,这是正确的:

$forecastItem->symbol->attributes(); // no write, but a read operation

因此,如果节点存在,那么它将按预期工作,例如这个现有的符号元素:

$forecastItem->time->symbol->attributes();

编写代码时,最有可能是您在文档树中的其他位置找到的符号。

答案 1 :(得分:1)

您应该使用$xml->forecast->tabular->children()来遍历xml的子项:

<?php

$data = '<weatherdata>
 <forecast>
 <tabular>
   <time from="2015-09-25T20:00:00" to="2015-09-25T23:00:00" period="3">
      <symbol number="4" numberEx="4" name="Cloudy" var="04" />
   </time>
   <time from="2015-09-25T23:00:00" to="2015-09-26T05:00:00" period="0">
      <symbol number="9" numberEx="46" name="Light rain" var="46" />
   </time>
  </tabular>
  </forecast>
  </weatherdata>';

$xml = simplexml_load_string($data);

$froms = array();
$names = array();

foreach($xml->forecast->tabular->children() as $forecastItem){
    $attr = $forecastItem->attributes();
    $froms[] = $attr['from'];
    $attr2 = $forecastItem->symbol->attributes();
    $names[] = $attr2['name'];
}

print_r($froms);
print_r($names);

Output

Array
(
    [0] => SimpleXMLElement Object
        (
            [0] => 2015-09-25T20:00:00
        )

    [1] => SimpleXMLElement Object
        (
            [0] => 2015-09-25T23:00:00
        )

)
Array
(
    [0] => SimpleXMLElement Object
        (
            [0] => Cloudy
        )

    [1] => SimpleXMLElement Object
        (
            [0] => Light rain
        )

)