开发者

XPath dealing with intermixed content

开发者 https://www.devze.com 2023-04-06 23:15 出处:网络
How to extract the text of such an element via XPath: <document> some text <subelement>subelement text</subelement>

How to extract the text of such an element via XPath:

<document>
  some text
     <subelement>subelement text</subelement>
  postscript
</document>

The XPath expression:

/document

returns document node text and all its subnodes text:

some text         subelement text    postscript

While the XPath expression:

/document/text()

returns just the first text node:

some text

that is, "postscript" is missing.

Question

Is there a way to get the text of all text nodes that are immediate sons of <document>?

Postscript

Very focused Example, in case you want to test yourself, copy into a main method and fix the imports.

    DocumentBuilder dbuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

开发者_开发百科    String xml = "<?xml version='1.0' encoding='UTF-8'?>" +
                 "<document>"
                 + "some text into document"
                 + "    <subelement>"
                 + "        some text into SUBelement"
                 + "    </subelement>"
                 + "POSTSCRIPT"
                 + "</document>";

    //i'm forced to use an InputSource because parse doesn't take readers directly :-(
    Document doc = dbuilder.parse(new InputSource(new StringReader(xml)));

    //usual way to get an xpath
    XPath xp = XPathFactory.newInstance().newXPath();

    System.out.println(xp.evaluate("/document", doc));

    System.out.println(xp.evaluate("/document/text()",doc));


Just tested

xp.evaluate("/document/text()",doc, XPathConstants.NODESET)

indeed returns all text children but you are executing

xp.evaluate("/document/text()", doc, XPathConstants.STRING)

which seems to only convert the first node in the node set to String. So maybe you need to find another way to convert the NodeSet to String.


This will get you all of the text children. In general, relying on toString() or the methods that try to return String representations will lead to tears when dealing with DOM. It's always safer to "do it fully/do it right."

        NodeList list = (NodeList) xp.evaluate("/document/text()", doc, XPathConstants.NODESET);
        for (int i = 0; i < list.getLength(); i++) {
            System.out.println(list.item(i).getNodeValue());
        }


While the XPath expression:

/document/text()

returns just the first text node:

some text into document

that is, "postscript" is missing.

The XPath expression above returns all text node children of /document, but the XPath.evaluate() method, with no 3rd argument converts its result to a string. In the process, it apparently acts like <xsl:value-of> in that it only converts the first node in the result node-set.

To print the value of all text node children, supply XPathConstants.NODESET as the 3rd argument to XPath.evaluate(). This will give you the nodeset of text nodes as a NodeList. Then you can loop through them and print each one. Or you could try passing the NodeList directly to println(), and see what it prints. :-)


XPath /document/text() will return all child text nodes of document element. In your example: some text and postscript. I think (I don't know Java classes) System.out.println automatically converts node-set to string representation, in this case it simply returns 1st node.

0

精彩评论

暂无评论...
验证码 换一张
取 消