简体   繁体   中英

XPath evaluation with Saxon doesn't work for nodename

Why doesn't the following xpath return any results with Saxon 9.6 in Java?

//field

The strange part is I also evaluated //* and looped over the results comparing the nodeNames with "field" and got 889 hits for my document.

Full codeexample below:

Initializing and running the test:

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);


test(doc, "//*");
test(doc, "//field");

Test execution code:

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);
}

Output:

#hits total: 26256
#hits 'field': 889
#hits total: 0
#hits 'field': 0

Example XML-File (thanks to wero I now know it has something to do with namespaces):

<?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>

The most likely explanation is that your field elements have a non-null namespace uri and therefore aren't matched by your XPath expression.

EDIT:

As I guessed your document declares the default namespace

xmlns="http://www.xfa.org/schema/xfa-template/2.8/"

and so the template and field elements are in that namespace.

To match the field elements you either need to tweak your XPath query to also declare that namespace or search for the local name only.

Note that if you were to use the s9api interface instead of JAXP, you could take advantage of the ability in XPath 2.0 to set a default namespace for element names in the XPath expression. Your code would then look like this:

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM