所以这个xpath查询让我抓狂.我正在尝试做的是搜索一个特定课程类型的高尔夫球场的xml文件(在这种情况下是与谷歌地图api一起使用的kml文件)并抓取每个匹配的<Placemark>元素,以便我可以创建一个新的xml对象结果,以便我可以进一步使用新查询进行过滤.问题是我似乎无法弄清楚如何获得每个匹配<Placemark>元素
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Document>
<Placemark id="placemark3">
<name>Test Country Club</name>
<description>
<![CDATA[
<div class="contact">Post Office Box 329 <a href="#" target="_blank">website</a></div>
]]>
</description>
<alpha>a</alpha>
<position>2</position>
<type>Public/Daily Fee</type>
<styleUrl>#nineholeStyle</styleUrl>
<Point>
<coordinates>-79.285576,37.111809</coordinates>
</Point>
</Placemark>
</Document>
</kml>';
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
//trying to get any Placemark element where type child matches a specific query
//in this case we want to search for Public/Daily Fee and return the placemark and everything inside it.
$query = $xpath->query("//Placemark[type='Public/Daily Fee']/ancestor::Placemark");;
foreach ($query as $result) {
//eventually want to merge each result into new xml object to be further filtered
}
Run Code Online (Sandbox Code Playgroud)
任何帮助将不胜感激.谢谢
您没有在查询之前注册XML命名空间.
// register it
$xpath->registerNamespace('kml', "http://earth.google.com/kml/2.1");
// and use it, too !
$query = $xpath->query("//kml:Placemark[kml:type='Public/Daily Fee']");
Run Code Online (Sandbox Code Playgroud)
(ancestor::kml:Placemark在你的表达中没有任何意义,我把它留了出来.)
即使所讨论的命名空间是XML文档的默认命名空间(如您的情况),也必须使用XPath查询中的命名空间前缀.
该元素<kml xmlns="http://earth.google.com/kml/2.1">相当于<kml:kml xmlns:kml="http://earth.google.com/kml/2.1">.
但是,XPath查询/kml不等同于/kml:kml.后者将匹配两个元素(当kml命名空间事先注册时),无论你做什么,前者都不匹配它们.
另请注意,您不需要使用XML文档中使用的相同名称空间前缀.
假设XML文档是这样的:
<kml:kml xmlns:kml="http://earth.google.com/kml/2.1">
<kml:Document />
</kml:kml>
Run Code Online (Sandbox Code Playgroud)
然后你仍然可以这样做:
$xpath->registerNamespace('foo', "http://earth.google.com/kml/2.1");
$query = $xpath->query("/foo:kml/foo:Document");
Run Code Online (Sandbox Code Playgroud)
并获得正确的结果.命名空间前缀只是一种简写.