我试图找出使用SimpleXML解析相当复杂的XML的最有效方法,并且当文档中存在名称空间时我就陷入困境。
好的,所以我的XML看起来像这样:
<ns:event xmls:ns="http://example.com/event/1.1">
<ns:eventinfo>
<ns:start year="2011" month="9" />
<ns:eventnames>
<ns:eventname>Superevent</ns:eventname>
</ns:eventnames>
</ns:eventinfo>
<ns:eventlocale>My place</ns:eventlocale>
</ns:event>
我可以通过以下方式从“普通”标签中提取信息:
$data = simplexml_load_string($xml);
foreach ($data->children('ns', true) as $children) {
$child = $children->children('ns',true);
$eventname = ($child->eventname);
}
这会将$ eventname作为Superevent。但是,这种方法不适用于属性......
但如果没有任何名称空间,我会轻易地提取属性,例如:
$startyear = $data->$start['year'];
那么 - 任何人都有想法轻松解决这个问题?任何信息或想法将不胜感激。
答案 0 :(得分:1)
您是否考虑过使用SimpleXML's xpath功能?
// your data example missed an 'n' in xmlns, so reposted, just to be sure
// with some additional ns:event elements in a root element
$xml = '<?xml version="1.0" encoding="utf-8"?>
<root>
<ns:event xmlns:ns="http://example.com/event/1.1">
<ns:eventinfo>
<ns:start year="2011" month="9" />
<ns:eventnames>
<ns:eventname>Superevent</ns:eventname>
</ns:eventnames>
</ns:eventinfo>
<ns:eventlocale>My place</ns:eventlocale>
</ns:event>
<ns:event xmlns:ns="http://example.com/event/1.1">
<ns:eventinfo>
<ns:start year="2011" month="8" />
<ns:eventnames>
<ns:eventname>Another Superevent</ns:eventname>
</ns:eventnames>
</ns:eventinfo>
<ns:eventlocale>Your place</ns:eventlocale>
</ns:event>
</root>';
$data = simplexml_load_string($xml);
$data->registerXPathNamespace( 'ns', 'http://example.com/event/1.1' );
# '//ns:event' means: find ns:event elements anywhere in the document
# '/ns:event' would mean: find ns:event elements that are direct children of the root
$events = $data->xpath( '//ns:event' );
foreach( $events as $event )
{
# from now on, we are using $event (ns:event elements) as our contexts to query
# '.' means: from our current context node find...
# '/ns:eventinfo[1]' means: find the first ns:eventinfo element that is a direct child of the preceding expression
# '/ns:eventnames[1]' means: same as previous but ns:eventnames element
# '/ns:eventname[1]' means: same as previous but ns:eventname element
$eventname = $event->xpath( './ns:eventinfo[1]/ns:eventnames[1]/ns:eventname[1]' );
# '/@year' means: the year attribute that is a direct child of the preceding expression
$year = $event->xpath( './ns:eventinfo[1]/ns:start[1]/@year' );
# '/@month' means: same as previous but month attribute
$month = $event->xpath( './ns:eventinfo[1]/ns:start[1]/@month' );
$eventlocale = $event->xpath( './ns:eventlocale[1]' );
# echo the first elements from the results found by our xpath queries
echo 'Event "' . $eventname[ 0 ] . '" taking place at ' . $eventlocale[ 0 ] . ' sometime in ' . $month[ 0 ] . '/' . $year[ 0 ] . '<br>';
}
修改强>
我在上一个例子中所做的事情是相当冗长的。这应该可以在循环内部工作,因为您已经在echo
语句中已经找到了第一个找到的节点:
# relative to our context node '.' find all descendants '//' that is an ns:eventname element
$eventname = $event->xpath( './/ns:eventname' );
# relative to our context node '.' find all descendants '//' that is a year attribute of an ns:start element
$year = $event->xpath( './/ns:start/@year' );
# relative to our context node '.' find all descendants '//' that is a month attribute of an ns:start element
$month = $event->xpath( './/ns:start/@month' );
# relative to our context node '.' find all children '/' that is an ns:eventlocale element
$eventlocale = $event->xpath( './ns:eventlocale' );
答案 1 :(得分:0)
您可以使用类似于使用simplexml_load_string之前的内容:
$xml = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $xml);
有关替换参数(“$ 1 $ 2 $ 3”)的说明,请参阅http://php.net/manual/en/function.preg-replace.php。
这会将<ns:eventinfo>
更改为<nseventinfo>
答案 2 :(得分:0)
答案 3 :(得分:0)
您可以按代码访问eventname:
$data->children("http://example.com/event/1.1")->eventinfo->children("http://example.com/event/1.1")->eventnames->children("http://example.com/event/1.1")->eventname
有关如何使用子级和使用命名空间解析XML的更多详细信息,请参阅我的帖子Parse XML with namespace by SimpleXML in PHP。 XML是从Salesforce输出消息生成的,其中包含XML命名空间。我使用SimpleXML在children()的帮助下解析它。