使用 SimpleXML 和 xpath 访问 XML 节点值
Accessing XML node value using SimpleXML and xpath
这些问题很多,请见谅。我都看过了。
我有以下 XML 使用命名空间 http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/ : http://events.manchester.ac.uk/f3vf/calendar/tag:manchester_museum/view:list/p:q_details/calml.xml
的文档
我正在尝试使用 SimpleXML 解析此文档。下面的示例代码尝试从下面访问标题节点 "Discovery Center" 的值。
<ns:calendar xmlns:ns="http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/">
<ns:listView>
<ns:day date="2015-07-08" weekDay="Wed">
<ns:event>
<ns:id xmlns:even="http://www.columbasystems.com/customers/uom/gpp/eventid/" query="{http://www.columbasystems.com/customers/uom/gpp/eventid/}b9v-ib270yqf-nmn54k">even:b9v-ib270yqf-nmn54k</ns:id>
<ns:title>Discovery Centre</ns:title>
...
</ns:event>
</ns:day>
</ns:listView>
</ns:calendar>
PHP :
$feed_uri = 'http://events.manchester.ac.uk/f3vf/calendar/tag:manchester_museum/view:list/p:q_details/calml.xml';
$xml = simplexml_load_file($feed_uri);
$xml->registerXPathNamespace("ns", "http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/");
foreach($xml->xpath('//ns:calendar/ns:listView/ns:day') as $day) {
$events = $day->xpath('//ns:event');
foreach($events as $event) {
var_export($event->xpath('//ns:title'));
}
}
OUTPUTS 几个空数组:
array ( 0 => SimpleXMLElement::__set_state(array( )),
我想我使用的 xpath 有误,我如何获得这些节点的值?
我把xml放在字符串里,改回文件。我希望,其他是清楚的
$str = '<ns:calendar xmlns:ns="http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/">
<ns:listView>
<ns:day date="2015-07-08" weekDay="Wed">
<ns:event>
<ns:id xmlns:even="http://www.columbasystems.com/customers/uom/gpp/eventid/" query="{http://www.columbasystems.com/customers/uom/gpp/eventid/}b9v-ib270yqf-nmn54k">even:b9v-ib270yqf-nmn54k</ns:id>
<ns:title>Discovery Centre</ns:title>
</ns:event>
</ns:day>
</ns:listView>
</ns:calendar>';
$xml = simplexml_load_string($str);
$xml->registerXPathNamespace("ns", "http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/");
foreach($xml->xpath('//ns:calendar/ns:listView/ns:day') as $day) {
echo $day['date'] . ' ';
$events = $day->xpath('.//ns:event');
foreach($events as $event) {
echo $event->xpath('.//ns:title/text()')[0];
}
}
结果
2015-07-08 Discovery Centre
更新
您可以使用前缀 insead full url。并记住在这种情况下如何获取属性值
$cal_items = $xml->children("ns",true);
foreach($cal_items->listView->day as $day) {
echo $day->attributes()['date'] . ' ' ;
foreach($day->event as $event) {
echo $event->title;
}
}
您的输出不是空数组。空数组如下所示:
array()
但是你有这个:
array ( 0 => SimpleXMLElement::__set_state(array( )),
所以,显然 XPath 正在工作,并为您提供结果列表(数组)(SimpleXMLElement 对象)。
问题是 var_export
不太擅长检查 SimpleXMLElement 对象,因此您看不到实际得到的结果。
要获取节点的文本内容,您必须将其转换为字符串 - 显式使用 (string)$node
,或隐式使用 echo
。所以以下将起作用:
foreach($xml->xpath('//ns:calendar/ns:listView/ns:day') as $day) {
$events = $day->xpath('//ns:event');
foreach($events as $event) {
foreach ($event->xpath('//ns:title') as $title ) {
echo $title;
}
}
}
但是,您的 XPath 表达式中确实有一个小错误(与您是否使用 SimpleXML 或任何其他 API 无关)://
前缀总是从文档的根,而不是用作上下文的元素。要搜索 "any depth within the current element",您需要 .//
,例如$day->xpath('.//ns:event')
.
也就是说,您实际上根本不需要像 XPath 这样花哨的东西,因为它不是那么深的结构。所以你可以只使用 SimpleXML's normal access methods, as long as you first select the right namespace using the ->children()
method:
$cal_items = $xml->children("http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/");
foreach($cal_items->listView->day as $day) {
foreach($day->event as $event) {
echo $event->title;
}
}
请注意,您的 XML 包含没有名称空间前缀的属性,例如 <ns:day date="2015-07-09" weekDay="Thu">
;有点不直观,这些是 officially in no namespace at all,因此您必须切换回 null 命名空间才能访问它们:
echo $day->attributes(null)['date'];
这些问题很多,请见谅。我都看过了。
我有以下 XML 使用命名空间 http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/ : http://events.manchester.ac.uk/f3vf/calendar/tag:manchester_museum/view:list/p:q_details/calml.xml
的文档我正在尝试使用 SimpleXML 解析此文档。下面的示例代码尝试从下面访问标题节点 "Discovery Center" 的值。
<ns:calendar xmlns:ns="http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/">
<ns:listView>
<ns:day date="2015-07-08" weekDay="Wed">
<ns:event>
<ns:id xmlns:even="http://www.columbasystems.com/customers/uom/gpp/eventid/" query="{http://www.columbasystems.com/customers/uom/gpp/eventid/}b9v-ib270yqf-nmn54k">even:b9v-ib270yqf-nmn54k</ns:id>
<ns:title>Discovery Centre</ns:title>
...
</ns:event>
</ns:day>
</ns:listView>
</ns:calendar>
PHP :
$feed_uri = 'http://events.manchester.ac.uk/f3vf/calendar/tag:manchester_museum/view:list/p:q_details/calml.xml';
$xml = simplexml_load_file($feed_uri);
$xml->registerXPathNamespace("ns", "http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/");
foreach($xml->xpath('//ns:calendar/ns:listView/ns:day') as $day) {
$events = $day->xpath('//ns:event');
foreach($events as $event) {
var_export($event->xpath('//ns:title'));
}
}
OUTPUTS 几个空数组:
array ( 0 => SimpleXMLElement::__set_state(array( )),
我想我使用的 xpath 有误,我如何获得这些节点的值?
我把xml放在字符串里,改回文件。我希望,其他是清楚的
$str = '<ns:calendar xmlns:ns="http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/">
<ns:listView>
<ns:day date="2015-07-08" weekDay="Wed">
<ns:event>
<ns:id xmlns:even="http://www.columbasystems.com/customers/uom/gpp/eventid/" query="{http://www.columbasystems.com/customers/uom/gpp/eventid/}b9v-ib270yqf-nmn54k">even:b9v-ib270yqf-nmn54k</ns:id>
<ns:title>Discovery Centre</ns:title>
</ns:event>
</ns:day>
</ns:listView>
</ns:calendar>';
$xml = simplexml_load_string($str);
$xml->registerXPathNamespace("ns", "http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/");
foreach($xml->xpath('//ns:calendar/ns:listView/ns:day') as $day) {
echo $day['date'] . ' ';
$events = $day->xpath('.//ns:event');
foreach($events as $event) {
echo $event->xpath('.//ns:title/text()')[0];
}
}
结果
2015-07-08 Discovery Centre
更新 您可以使用前缀 insead full url。并记住在这种情况下如何获取属性值
$cal_items = $xml->children("ns",true);
foreach($cal_items->listView->day as $day) {
echo $day->attributes()['date'] . ' ' ;
foreach($day->event as $event) {
echo $event->title;
}
}
您的输出不是空数组。空数组如下所示:
array()
但是你有这个:
array ( 0 => SimpleXMLElement::__set_state(array( )),
所以,显然 XPath 正在工作,并为您提供结果列表(数组)(SimpleXMLElement 对象)。
问题是 var_export
不太擅长检查 SimpleXMLElement 对象,因此您看不到实际得到的结果。
要获取节点的文本内容,您必须将其转换为字符串 - 显式使用 (string)$node
,或隐式使用 echo
。所以以下将起作用:
foreach($xml->xpath('//ns:calendar/ns:listView/ns:day') as $day) {
$events = $day->xpath('//ns:event');
foreach($events as $event) {
foreach ($event->xpath('//ns:title') as $title ) {
echo $title;
}
}
}
但是,您的 XPath 表达式中确实有一个小错误(与您是否使用 SimpleXML 或任何其他 API 无关)://
前缀总是从文档的根,而不是用作上下文的元素。要搜索 "any depth within the current element",您需要 .//
,例如$day->xpath('.//ns:event')
.
也就是说,您实际上根本不需要像 XPath 这样花哨的东西,因为它不是那么深的结构。所以你可以只使用 SimpleXML's normal access methods, as long as you first select the right namespace using the ->children()
method:
$cal_items = $xml->children("http://www.columbasystems.com/cpng/xmlviewer/cal/1-0/");
foreach($cal_items->listView->day as $day) {
foreach($day->event as $event) {
echo $event->title;
}
}
请注意,您的 XML 包含没有名称空间前缀的属性,例如 <ns:day date="2015-07-09" weekDay="Thu">
;有点不直观,这些是 officially in no namespace at all,因此您必须切换回 null 命名空间才能访问它们:
echo $day->attributes(null)['date'];