简体   繁体   中英

Java XPath resolver for documents with namespaces

I need to query XML documents using XPath expressions in a Java application. I have created the following classes, which accepts a file (location of the XML document on a local hard drive) and an XPath

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
 
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
 
public class Try 
{
    public static void main(String[] args) throws Exception 
    {
        //Get DOM Node for XML
        String fileName= "xmd.xml";
        Document document = getDocument(fileName);
         
        String xpathExpression = "";
             
        /*******Get attribute values using xpath******/
         
        
        xpathExpression = "//isebel:story/dc:title/text()";
        System.out.println( evaluateXPath(document, xpathExpression) );
        
    }
     
    private static List<String> evaluateXPath(Document document, String xpathExpression) throws Exception 
    {
        // Create XPathFactory object
        XPathFactory xpathFactory = XPathFactory.newInstance();
         
        // Create XPath object
        XPath xpath = xpathFactory.newXPath();
        
        List<String> values = new ArrayList<>();
        try
        {
            // Create XPathExpression object
            XPathExpression expr = xpath.compile(xpathExpression);
             
            // Evaluate expression result on XML document
            NodeList nodes = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
             
            for (int i = 0; i < nodes.getLength(); i++) {
                values.add(nodes.item(i).getNodeValue());
            }
                 
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return values;
    }
 
    private static Document getDocument(String fileName) throws Exception 
    {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(fileName);
        return doc;
    }
    class NamespaceResolver implements NamespaceContext 
    {
        //Store the source document to search the namespaces
        private Document sourceDocument;
     
        public NamespaceResolver(Document document) {
            sourceDocument = document;
        }
     
        //The lookup for the namespace uris is delegated to the stored document.
        public String getNamespaceURI(String prefix) {
            if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
                return sourceDocument.lookupNamespaceURI(null);
            } else {
                return sourceDocument.lookupNamespaceURI(prefix);
            }
        }
     
        public String getPrefix(String namespaceURI) {
            return sourceDocument.lookupPrefix(namespaceURI);
        }
     
        @SuppressWarnings("rawtypes")
        public Iterator getPrefixes(String namespaceURI) {
            return null;
        }
    }
}

Suppose now that I have the following XML document.

<?xml version='1.0' encoding='UTF-8'?>
<isebel:story xmlns:isebel="http://www.isebel.eu/ns/isebel" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:html="http://www.w3.org/1999/xhtml" xml:id="xmd-s001-000-000-069" xml:lang="deu">
  <dc:identifier>de.wossidia.xmd-s001-000-000-069</dc:identifier>
  <isebel:purl>https://apps.wossidia.de/webapp/run/node/XMD-S001-000-000-069</isebel:purl>
  <dc:title>[69] Mit Peitsche und Knüppel</dc:title>
  <dc:title xml:lang="nds"/>
  <dc:title xml:lang="deu"/>
  <isebel:contents>
    <isebel:content xml:lang="nds">De Kutscher hett bi Vierecksch deent. Vierecksch het twee böse Jungens hatt, de hebben de Pier de Swänz afsnäden. Se hebben dat up sienen, dennʼ Kutscher sienen Schalm daan (ego: d. h. Kutscher als Täter angegeben, d. h. gesagt, er habe es getan). Dor het Vierecksch dennʼ Kutscher slagen, dat de Schoh vull Bloot stahn hebben bet up de Schänen. Dor het he sik verdrunken inʼn Radenschen See. De mööt hier jo begraben warden (nescit, wo). De ward jo haalt. As se kamen bi ʼn Kirchhoff, koenen keen Pier em trecken, un dor warden von sülben de Klocken gahn. Dor warden Ossen vorspannt, de trecken em hen na ʼn Gerichtsbarg (in Wattmannshagen), dor is he begraben. De Swester het ʼn drögen Hasselstock hatt, dennʼ steckt se em up sien Graff un seggt: Wenn de utgräunt, is ehr Broder selig storben. De is utgräunt, dor is se ruhig wäst.

Erzähler: Frau Oppermann, Hohenfelde b. Laiendorf, Kreis Neustrelitz; Aufzeichner: Wossidlo, 15. 6. 1913.</isebel:content>
    <isebel:content xml:lang="deu">Der Kutscher hat bei der alten Viereck gedient. Die alte Viereck hat zwei böse Jungen gehabt. Die haben den Pferden die Schwänze abgeschnitten. Sie haben das aber auf den Kutscher geschoben. Da hat die Vierecken den Kutscher geschlagen, daß die Schuhe voll Blut gestanden haben bis an die Schienbeine. Da hat er sich im Radenschen See ertränkt. Er muß ja hier begraben werden (Erzähler weiß nicht wo). Er wird ja auch geholt. Als sie beim Kirchhof vorbeikommen, können ihn die Pferde nicht ziehen und die Glocken beginnen von selbst zu läuten. Da werden Ochsen vorgespannt, die ziehen ihn bis zum Gerichtsberg. In Wattmannshagen ist er begraben. Die Schwester hat einen trocknen Haselstock gehabt, den steckt sie auf sein Grab und sagt: wenn der ausschlägt, ist ihr Bruder selig gestorben. Er ist ausgeschlagen, da ist sie ruhig gewesen.</isebel:content>
  </isebel:contents>
</isebel:story>

and I want as aresult to get:

[[69] Mit Peitsche und Knüppel]

it dose not work can someone pls help

Your XML is not namespace-well-formed : It uses undefined namespace prefixes.

First fix your XML. Then fix your getNamespaceURI() method to return the right namespace URI for each used namespace prefix.

See How does XPath deal with XML namespaces? for an example of a working getNamespaceURI() method.

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