解析嵌套XML节点的属性值

问题描述:

我试图用PHP解析XML,但是我遇到了问题。解析嵌套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'];  
} 

但后来我试图加载这样的符号的名称属性:

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

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

您应该使用$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 
     ) 

) 
+0

@Alan谢谢,我刚刚也注意到了,好像我们在同一时间编辑它。 –

+0

没问题,重要的是,它的现予以更正。 :) –

你得到完整的错误信息是:

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

接着下面的代码的行数:

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

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

如果你被它的名称访问一个子元素,为examle喜欢这里的<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(); 

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

+0

非常感谢您的澄清 – Jachym