从PHP中使用多个名称空间的XML内容中检索值数组

时间:2016-11-22 09:49:50

标签: php arrays xml xpath xml-namespaces

我发布了另一个问题,我的错误是不完整的。 我有一个带有多个命名空间的XML,但我需要访问foreach中的值。

我的XML数组是:

<ArrayOfSession xmlns:i='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://schemas.datacontract.org/2004/07/Vista.Online.BackOffice.Api.Models.V1'> 
<Session>
  <AreComplimentariesAllowed>true</AreComplimentariesAllowed>
  <Attributes xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <d3p1:string>0000000009</d3p1:string>
    <d3p1:string>0000000011</d3p1:string>
  </Attributes>
</Session>
</ArrayOfSession>

我在另一位用户的帮助下:Retrieving an array of values from an XML content with a namespace in PHP

通过这个答案,我尝试了一些变化。这是我目前的一个,它不起作用:

$xml->registerXPathNamespace('i', 'http://www.w3.org/2001/XMLSchema-instance');
$xml->registerXPathNamespace('j', 'http://schemas.datacontract.org/2004/07/Vista.Online.BackOffice.Api.Models.V1');
$xml->registerXPathNamespace('ns', 'http://schemas.microsoft.com/2003/10/Serialization/Arrays');

foreach($xml->xpath('//ns:d3p1') as $header){
    var_export($header->xpath('//Attributes/ns:string'));
}

我也尝试过:

foreach($xml->xpath('//ns:d3p1') as $header){
        var_export($header->xpath('//ns:string'));
    }

这让我很难过!

在我目前正在使用的其余代码版本中,我正在使用以下内容检索元素:

foreach($xml->Session as $event){
    // Do Something with $event->AreComplimentariesAllowed
}

这很好用,但我无法访问那些属性元素。

一如既往地感谢。

1 个答案:

答案 0 :(得分:0)

在致电SimpleXMLElement之前,您必须在每个xpath()上注册名称空间。您可以在$xml变量上注册它们,但不能在$header上注册。

您的XML也有默认命名空间。您为它注册前缀j,但不在表达式中使用前缀。最后这里没有元素d3p1。这只是文档中的名称空间前缀。

所以迭代Session元素,然后迭代string

中的Attributes
$sessions = new SimpleXMLElement($xml);
$sessions->registerXPathNamespace(
  'j', 
  'http://schemas.datacontract.org/2004/07/Vista.Online.BackOffice.Api.Models.V1'
);

foreach($sessions->xpath('//j:Session') as $session) {
  $session->registerXPathNamespace(
    'j', 
    'http://schemas.datacontract.org/2004/07/Vista.Online.BackOffice.Api.Models.V1'
  );
  $session->registerXPathNamespace(
    'ns', 
    'http://schemas.microsoft.com/2003/10/Serialization/Arrays'
  );
  var_export($session->xpath('.//j:Attributes/ns:string'));
}

在DOM中,这看起来不同:

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$xpath->registerNamespace(
  'j', 
  'http://schemas.datacontract.org/2004/07/Vista.Online.BackOffice.Api.Models.V1'
);
$xpath->registerNamespace(
  'ns', 
  'http://schemas.microsoft.com/2003/10/Serialization/Arrays'
);

foreach ($xpath->evaluate('//j:Session') as $session) {
  var_export(
    iterator_to_array($xpath->evaluate('.//j:Attributes/ns:string', $session))
  );
}

它有一个专用的Xpath对象,因此名称空间注册只需要进行一次。