我正在尝试对早期 xpath 查询的结果执行 xpath 查询。我可以编写 xpath 查询来提取子元素,然后迭代生成的元素,将它们传递给另一个函数进行进一步处理。当我想应用另一个 xpath 时,我的问题就来了。
给定的 XML
<grandfather>
<mother>
<son>1</son>
<son>2</son>
</mother>
<mother>
<daughter>3</daughter>
</mother>
<mother>
<daughter>4</daughter>
<son>5</son>
</mother>
<grandfather>
我可以获取所有带有 xpath /grandfather/mother
的母节点,但是我可以在单独的函数中使用传递的母节点作为下一个查询的相对根来查询这些母节点吗?
当 XML 有一个命名空间时,问题会变得更加复杂,您需要注册该命名空间才能使 xpath 正常工作。使用 SimpleXML,在第一个 xpath 查询之前注册的命名空间前缀不会保留在查询结果中,因此您必须为后续查询再次注册它。
DOMXpath::evaluate()
的第二个参数是表达式的上下文。下面是一个处理 xml 的小示例:
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('//mother') as $mother) {
var_dump(
$xpath->evaluate('count(daughter)', $mother),
$xpath->evaluate('count(son)', $mother)
);
}
您必须将 Xpath 实例提供给函数以保留命名空间注册。
可以扩展 DOMDocument 和其他 DOMNode 类,以允许在对象级别进行注册。我在FluentDOM中实现了它。
您可以通过在
查询字符串的开头使用 ./
并使用第一个结果节点作为第二个参数,对原始 xpathDocument 相对于第一个结果节点执行第二个查询:
$motherList=$xml->query('/grandfather/mother');
$aMother=$motherList[0];
$daughterList=$xml->query('./daugther',$aMother);