解析嵌套XML节点的属性值


Parsing attribute values of nested XML nodes

我试图在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>

我可以一直从这样的值加载->

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()节点不存在。基本上我要做的就是将所有的名字加载到一个数组中,就像form一样

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

提示:main(): Node no longer exists in…

后接以下代码的行号:

$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();

这很可能是您在编写代码时将自己定位在文档树中的不同位置的标志。

您应该使用$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);
输出:

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
        )
)