使用SimpleXML使用PHP访问特定的XML节点

时间:2015-02-22 01:39:26

标签: php simplexml

最近我遇到了使用simplexml的问题。 我想要做的是获取多次出现的嵌套节点的值。 xml看起来有点像这样:

<response>
  <album id="123">
  [...]
    <duration>
      <value format="seconds">2576</value>
      <value format="mm:ss">42:56</value>
      <value format="hh:mm:ss">00:42:56</value>
      <value format="xs:duration">PT42M56S</value>
    </duration>
  [...]
  </album>
</response>

具体来说,我需要<value format="hh:mm:ss">节点的值。

所以我引用了一个看起来像这样的对象:

$this->webservice->album->duration->value;

现在,如果我var_dump这个结果将是:

object(SimpleXMLElement)#117 (5) { 
  ["@attributes"]=> array(1) { 
    ["format"]=> string(7) "seconds" 
  } 
  [0]=> string(4) "2576" 
  [1]=> string(5) "42:56" 
  [2]=> string(8) "00:42:56" 
  [3]=> string(8) "PT42M56S" 
}

我不理解这个输出,因为它接受第一个节点的format-attribute(秒)并继续使用数组中的node-values,同时完全忽略以下节点的format-attribute。

此外,如果我执行以下操作:

$this->webservice->album->duration->value[2];

导致:

object(SimpleXMLElement)#108 (1) { 
  ["@attributes"]=> array(1) { 
    ["format"]=> string(8) "hh:mm:ss" 
  } 
}

我根本没有值得解决的问题。

我也尝试使用xpath,方法如下:

$this->webservice->album->duration->xpath('value[@format="hh:mm:ss"]');

导致:

array(1) { 
  [0]=> object(SimpleXMLElement)#116 (1) { 
    ["@attributes"]=> array(1) { 
      ["format"]=> string(8) "hh:mm:ss" 
    } 
  } 
}

所以我的问题是: 我究竟做错了什么?的xD

提前感谢任何有用的建议:)

1 个答案:

答案 0 :(得分:2)

您的错误在于完全信任var_dump,而不是尝试使用基于the examples in the manual的元素。

在您第一次尝试时,您访问了$duration_node->value;这可以通过几种不同的方式使用:

  • 如果您使用foreach($duration_node->value as $value_node)进行迭代,则依次获得每个<value>元素
  • 您可以按索引访问特定元素,例如第3个元素$duration_node->value[2]
  • 如果您将其视为单个元素,SimpleXML假设您需要第一个元素,即echo $duration_node->valueecho $duration_node->value[0]相同

您的第二个示例运行良好 - 它找到了<value>元素,其属性为format="hh:mm:ss"xpath()方法总是返回一个数组,因此您需要检查它是否为空,然后查看第一个元素。

获得正确的元素后,访问其文本内容非常简单,只需将其转换为字符串((string)$foo),或将其传递给始终需要字符串的内容(例如echo)。

所以这会奏效:

$xpath_results = $this->webservice->album->duration->xpath('value[@format="hh:mm:ss"]');
if ( count($xpath_results) != 0 ) {
    $value = (string)$xpath_results[0];
}

就像这样:

foreach ( $this->webservice->album->duration->value as $value_node ) {
    if ( $value_node['format'] == 'hh:mm:ss' ) {
        $value = (string)$value_node;
        break;
    }
}