对于给定的XML和XPath,在线XPath测试程序的工作方式类似于下面的代码(与任何内容都不匹配):http://www.xpathtester.com/xpath
import java.io.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
class test {
public static void main(String[] args) throws Exception {
XPathExpression expr = XPathFactory.newInstance().newXPath().compile(
"/A[namespace-uri() = 'some-namespace']"); // This does not select anything, replacing A with * does
// This XPath selects as expected (in all parsers mentioned): /*[namespace-uri() = 'some-namespace']
String xml = "<A xmlns=\"some-namespace\"> </A>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
Document doc = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
System.out.println("Number of nodes selected: " + nodes.getLength());
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println("Node name: " + nodes.item(i).getNodeName());
}
}
}
无论文档工厂是否支持名称空间,上述代码都不会选择任何内容 .
这是根据XPath标准吗?还是实施的细微差别?
This资源提到以下内容:
实际上,当XML文档使用默认命名空间时,即使目标文档没有,XPath表达式也必须使用前缀 .
为了验证这一点,我更改了XPath以包含如下前缀: /p:A[namespace-uri() = 'some-namespace']
并添加了一个名称空间解析器,它返回URI some-namespace作为前缀p, and that worked .
问题:
1)是否有一种方法可以使没有前缀的XPath表达式适用于具有默认命名空间的文档?
2)[第二个XPath测试器] [3]如何工作? (此测试仪不符合标准)
Note :在我的应用程序中,我无法控制收到的文档和XPath . 但两者都保证有效 .
1 回答
Freeformatter.com XPath异常
对于您的示例XML,
这个XPath,
should select nothing ,但在Freeformatter.com,它选择
这是 WRONG .
因此,全程停止,请勿使用 Freeformatter.com . Don 't try to work around this – simply don' t使用该服务,因为无法信任它以一致的方式评估XPath .
一般来说
XPath名称空间
您可以
通过
local-name()
[不推荐]击败名称空间荣誉名称空间通过
local-name()
和namespace-uri()
[确定,但详细],或者通过托管语言库的各种机制定义名称空间前缀[首选,但每个XPath托管系统各不相同]
有关更多详细信息,包括如何在许多不同托管语言中定义名称空间前缀的示例,请参阅 How does XPath deal with XML namespaces?
对于给定的,固定的XPath可以选择忽略命名空间吗?
如果你想让
//A
从上面的示例XML中选择一个节点并且仍然符合XPath,那么答案确实是 no .