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

Accessing a specific XML-node with PHP using SimpleXML

最近我 运行 遇到一个使用简单xml 的问题。 我想要做的是获取多次出现的嵌套节点的值。 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" 
}

我不明白这个输出,因为它采用第一个节点(秒)的格式属性并继续数组中的节点值,同时完全忽略以下节点的格式属性。

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

$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

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

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

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

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

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

一旦您拥有了正确的元素,访问其文本内容就像将其转换为字符串 ((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;
    }
}