【问题标题】:Parse XML with Namespace using SimpleXML [duplicate]使用 SimpleXML 使用命名空间解析 XML [重复]
【发布时间】:2010-10-10 09:42:12
【问题描述】:

我有这个作为 xml:

<root xmlns:event="http://www.webex.com/schemas/2002/06/service/event">
    <event:event>
        <event:sessionKey></event:sessionKey>
        <event:sessionName>Learn QB in Minutes</event:sessionName>
        <event:sessionType>9</event:sessionType>
        <event:hostWebExID></event:hostWebExID>
        <event:startDate>02/12/2009</event:startDate>
        <event:endDate>02/12/2009</event:endDate>
        <event:timeZoneID>11</event:timeZoneID>
        <event:duration>30</event:duration>
        <event:description></event:description>
        <event:status>NOT_INPROGRESS</event:status>
        <event:panelists></event:panelists>
        <event:listStatus>PUBLIC</event:listStatus>
    </event:event>
    ...
</root>

如何循环遍历所有 event:event 节点并显示,例如,所有 event:SessionKey 的?

这不起作用:

$xml = new SimpleXMLElement($r);
$xml->registerXPathNamespace('e', 'http://www.webex.com/schemas/2002/06/service/event');

foreach($xml->xpath('//e:event') as $event) {
 var_export($event->xpath('//e:sessionKey'));
}

【问题讨论】:

标签: php xml namespaces simplexml


【解决方案1】:

它确实可以在没有 registerXPathNamespace 和 xpath 查询中的完整命名空间前缀的情况下工作:

$xml = new SimpleXMLElement($r);

foreach($xml->xpath('//event:event') as $event) {
 var_export($event->xpath('event:sessionKey'));
}

【讨论】:

  • 是也不是,实际上我认为这是一个错误。 PHP 自动注册当前上下文的命名空间。这甚至会覆盖您自己注册的命名空间。您的来源基于您加载的文档中使用的前缀。您无法控制的外部来源。可选的、不明确的并且可以随时更改的前缀。命名空间已定义、唯一且稳定 - 前缀/别名不是。
【解决方案2】:

您必须为您使用的每个 simpleXMLElement 对象注册命名空间。

$xml = new SimpleXMLElement($r);
$xml->registerXPathNamespace('e', 'http://www.webex.com/schemas/2002/06/service/event');

foreach($xml->xpath('//e:event') as $event) {
    $event->registerXPathNamespace('e', 'http://www.webex.com/schemas/2002/06/service/event');
    var_export($event->xpath('//e:sessionKey'));
}

命名空间也应该在 xml 文件中的某处声明。

<event:event xmlns:event="http://www.webex.com/schemas/2002/06/service/event">
...

所描述的方法 ax 也有效。如果您知道 xml 文件将始终使用相同的前缀,则可以跳过 registerXPathNamespace。

【讨论】:

    【解决方案3】:

    这里的替代方案对我有用。

    $xml = simplexml_load_string($r);
    $ns = $xml->getNamespaces(true);
    
    foreach ($xml->children($ns['event'])->event as $skey) {
        $sessionKey = $skey->children($ns['event'])->sessionKey;
        echo $sessionKey;
    }
    

    【讨论】:

    • 诀窍是使用children() 至少带有它的第一个参数。如果您事先知道文档结构,您甚至可以手动输入命名空间名称(或其 URI)来替代getNamespaces()
    • 为了更简单的打字技巧是投射到对象,即$ns = (object) $xml-&gt;getNamespaces(true);然后你可以像$sessionKey = $skey-&gt;children($ns-&gt;event)-&gt;sessionKey;一样使用它
    【解决方案4】:

    使用 simplexml 做了很多工作,我就是这样做的。

    如果您已经有一个元素并且只想获取它的不同命名空间的子元素,那么魔术技巧,比如这样的结构:

    <entry>
    <title type="text">My test entry</title>
    <gd:when startTime="2017-02-26T02:00:00Z" endTime="2017-02-26T03:00:00Z"/>
    <gc:notes type="string">A type</gc:notes>
    </entry>
    

    是将TRUE作为第二个参数发送给children函数:

      $title = (string) $entry->title;
      $gd = $entry->children('gd', TRUE);
      $attrs = $gd->when->attributes();
      $startTime = (string) $attrs->startTime;
      $gc = $entry->children('gc', TRUE);
      $notes = (string) $gc->notes();
    

    【讨论】:

      【解决方案5】:

      另一种方法是使用SimpleXML 进行解析,使用DOMDocument 进行操作/访问,这完全绕过了命名空间问题:

      $xml = new SimpleXMLElement($r);
      $xml = dom_import_simplexml($xml);
      $nodelist= $xml->getElementsByTagName('event');  
      for($i = 0; $i < $nodelist->length; $i++) {
          $sessions = $nodelist->item($i)->getElementsByTagName('sessionKey');
          echo $sessions->item(0)->nodeValue;
      }
      

      【讨论】:

        【解决方案6】:

        使用registerXPathNamespace 然后调用xpath 实际上对我不起作用。 我不得不采用这篇很棒的帖子中提供的解决方案:http://blog.preinheimer.com/index.php?/archives/172-SimpleXML,-Namespaces-Hair-loss.html

        所以在你的情况下,这个:

        echo $xml->children('http://www.webex.com/schemas/2002/06/service/event')->sessionName;
        

        将输出:

        在几分钟内了解 QB

        【讨论】:

          猜你喜欢
          • 2013-04-30
          • 1970-01-01
          • 1970-01-01
          • 2016-09-22
          • 1970-01-01
          相关资源
          最近更新 更多