Saxon 的 XPath 评估不适用于节点名
XPath evaluation with Saxon doesn't work for nodename
为什么以下 xpath return 在 Java 中对 Saxon 9.6 没有任何结果?
//field
奇怪的是我还评估了 //*
并遍历了将节点名称与 "field" 进行比较的结果,我的文档得到了 889 次匹配。
下面是完整的代码示例:
初始化和运行测试:
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);
test(doc, "//*");
test(doc, "//field");
测试执行代码:
private void test(Document doc, String xpathString) throws Exception {
System.setProperty("javax.xml.xpath.XPathFactory:" + NamespaceConstant.OBJECT_MODEL_SAXON, "net.sf.saxon.xpath.XPathFactoryImpl");
XPathFactory xpf;
xpf = XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON);
XPath xpath = xpf.newXPath();
XPathExpression expr = xpath.compile(xpathString);
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
int fieldHits = 0;
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
String name = node.getNodeName();
fieldHits = "field".equals(nodes.item(i).getNodeName()) ? fieldHits + 1 : fieldHits;
}
System.out.println("#hits total: " + nodes.getLength());
System.out.println("#hits 'field': " + fieldHits);
}
输出:
#hits total: 26256
#hits 'field': 889
#hits total: 0
#hits 'field': 0
示例XML-文件(感谢 wero 我现在知道它与名称空间有关):
<?xml version="1.0" encoding="UTF-8"?>
<?xfa generator="AdobeLiveCycleDesignerES_V9.0.1.0.20091206.1.615263" APIVersion="3.2.9310.0"?>
<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2015-11-17T07:12:49Z" uuid="262c190c-1563-4ae8-ae6e-4c8d59494a3c">
<template xmlns:xliff="urn:oasis:names:tc:xliff:document:1.1" xmlns="http://www.xfa.org/schema/xfa-template/2.8/">
<field name="A"></field>
<field name="B"></field>
<field name="C"></field>
<field name="D"></field>
<field name="E"></field>
<field name="F"></field>
</template>
</xdp:xdp>
最可能的解释是您的 field
元素具有非空命名空间 uri,因此与您的 XPath 表达式不匹配。
编辑:
我猜你的文档声明了默认命名空间
xmlns="http://www.xfa.org/schema/xfa-template/2.8/"
因此 template
和 field
元素位于该命名空间中。
要匹配 field
元素,您需要 tweak 您的 XPath 查询也声明该名称空间或仅搜索本地名称。
请注意,如果您要使用 s9api 接口而不是 JAXP,则可以利用 XPath 2.0 中的功能为 XPath 表达式中的元素名称设置默认命名空间。您的代码将如下所示:
private void test(Document doc, String xpathString) throws Exception {
Processor proc = new Processor(false);
XdmNode docNode = proc.newDocumentBuilder().wrap(doc);
XPathCompiler xpath = proc.newXPathCompiler();
xpath.declareNamespace("", "http://www.xfa.org/schema/xfa-template/2.8/");
XdmValue result = xpath.evaluate(xpathString, docNode);
int fieldHits = 0;
for (XdmItem item : result) {
String name = ((XdmNode)node).getNodeName().getLocalName();
fieldHits = "field".equals(name) ? fieldHits + 1 : fieldHits;
}
System.out.println("#hits total: " + nodes.getLength());
System.out.println("#hits 'field': " + fieldHits);
}
为什么以下 xpath return 在 Java 中对 Saxon 9.6 没有任何结果?
//field
奇怪的是我还评估了 //*
并遍历了将节点名称与 "field" 进行比较的结果,我的文档得到了 889 次匹配。
下面是完整的代码示例:
初始化和运行测试:
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);
test(doc, "//*");
test(doc, "//field");
测试执行代码:
private void test(Document doc, String xpathString) throws Exception {
System.setProperty("javax.xml.xpath.XPathFactory:" + NamespaceConstant.OBJECT_MODEL_SAXON, "net.sf.saxon.xpath.XPathFactoryImpl");
XPathFactory xpf;
xpf = XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON);
XPath xpath = xpf.newXPath();
XPathExpression expr = xpath.compile(xpathString);
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
int fieldHits = 0;
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
String name = node.getNodeName();
fieldHits = "field".equals(nodes.item(i).getNodeName()) ? fieldHits + 1 : fieldHits;
}
System.out.println("#hits total: " + nodes.getLength());
System.out.println("#hits 'field': " + fieldHits);
}
输出:
#hits total: 26256
#hits 'field': 889
#hits total: 0
#hits 'field': 0
示例XML-文件(感谢 wero 我现在知道它与名称空间有关):
<?xml version="1.0" encoding="UTF-8"?>
<?xfa generator="AdobeLiveCycleDesignerES_V9.0.1.0.20091206.1.615263" APIVersion="3.2.9310.0"?>
<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2015-11-17T07:12:49Z" uuid="262c190c-1563-4ae8-ae6e-4c8d59494a3c">
<template xmlns:xliff="urn:oasis:names:tc:xliff:document:1.1" xmlns="http://www.xfa.org/schema/xfa-template/2.8/">
<field name="A"></field>
<field name="B"></field>
<field name="C"></field>
<field name="D"></field>
<field name="E"></field>
<field name="F"></field>
</template>
</xdp:xdp>
最可能的解释是您的 field
元素具有非空命名空间 uri,因此与您的 XPath 表达式不匹配。
编辑:
我猜你的文档声明了默认命名空间
xmlns="http://www.xfa.org/schema/xfa-template/2.8/"
因此 template
和 field
元素位于该命名空间中。
要匹配 field
元素,您需要 tweak 您的 XPath 查询也声明该名称空间或仅搜索本地名称。
请注意,如果您要使用 s9api 接口而不是 JAXP,则可以利用 XPath 2.0 中的功能为 XPath 表达式中的元素名称设置默认命名空间。您的代码将如下所示:
private void test(Document doc, String xpathString) throws Exception {
Processor proc = new Processor(false);
XdmNode docNode = proc.newDocumentBuilder().wrap(doc);
XPathCompiler xpath = proc.newXPathCompiler();
xpath.declareNamespace("", "http://www.xfa.org/schema/xfa-template/2.8/");
XdmValue result = xpath.evaluate(xpathString, docNode);
int fieldHits = 0;
for (XdmItem item : result) {
String name = ((XdmNode)node).getNodeName().getLocalName();
fieldHits = "field".equals(name) ? fieldHits + 1 : fieldHits;
}
System.out.println("#hits total: " + nodes.getLength());
System.out.println("#hits 'field': " + fieldHits);
}