使用 SimpleXML 解析具有命名空间的 XML [duplicate]

Parse XML with Namespace using SimpleXML [duplicate]

提问人:user38968 提问时间:2/28/2009 最后编辑:hakreuser38968 更新时间:9/17/2023 访问量:94401

问:

我把它作为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 命名空间 simplexml

评论

3赞 Ajinkya Kulkarni 12/1/2010
这可能有助于 lornajane.net/posts/2010/...
1赞 hakre 11/23/2013
不起作用是并且从来都不是正确的错误描述。PHP 给出以下错误:“警告:SimpleXMLElement::xpath():未定义的命名空间前缀”。如果你开发软件,你应该听PHP的警告。另请参阅: 如何在 PHP 中获取有用的错误消息?
0赞 IMSoP 4/28/2021
另请参阅参考 - 如何在 SimpleXML 中处理命名空间(带冒号的标记和属性)?

答:

32赞 ax. 3/8/2009 #1

它在 XPath 查询中没有 and the full namespace prefix 的情况下可以工作:registerXPathNamespace

$xml = new SimpleXMLElement($r);

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

评论

10赞 ThW 4/16/2015
是的,也不是,实际上我认为这是一个错误。PHP 会自动注册当前上下文的命名空间。这甚至会覆盖您自己注册的命名空间。您的源基于您加载的文档中使用的前缀。您无法控制的外部来源。可选的前缀,不明确且可以随时更改。命名空间是定义的、唯一且稳定的 - 前缀/别名不是。
23赞 mcrumley 3/12/2009 #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。

5赞 Raf 3/21/2012 #3

使用然后打电话实际上对我不起作用。 我不得不使用这篇精彩文章中提供的解决方案:http://blog.preinheimer.com/index.php?/archives/172-SimpleXML,-Namespaces-Hair-loss.htmlregisterXPathNamespacexpath

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

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

将输出:

在几分钟内学习 QB

8赞 Asad Saeeduddin 12/1/2012 #4

另一种方法是用于解析和操作/访问,这完全绕过了命名空间问题:SimpleXMLDOMDocument

$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;
}
19赞 ewwink 2/5/2014 #5

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

$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;
}

评论

0赞 Álvaro González 2/12/2014
诀窍是至少使用它的第一个参数。如果您事先知道文档结构,您甚至可以手动键入命名空间名称(或其 URI)作为替代。children()getNamespaces()
0赞 PeterM 10/8/2018
为了更容易打字,技巧是强制转换为对象,即您可以使用这个$ns = (object) $xml->getNamespaces(true);$sessionKey = $skey->children($ns->event)->sessionKey;
20赞 Cameron 2/26/2017 #6

在使用 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 作为第二个参数发送到函数:

  $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();