Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.getTextContent() is there a way to get text content of the current node, not the descendant's text

Tags:

java

dom

xml

Node.getTextContent() returns the text content of the current node and its descendants.

is there a way to get text content of the current node, not the descendant's text.

Example

<paragraph>
    <link>XML</link>
    is a 
    <strong>browser based XML editor</strong>
    editor allows users to edit XML data in an intuitive word processor.
</paragraph>

expected output

paragraph = is a editor allows users to edit XML data in an intuitive word processor.
link = XML
strong = browser based XML editor

i tried below code

String str =            "<paragraph>"+
                            "<link>XML</link>"+
                            " is a "+ 
                            "<strong>browser based XML editor</strong>"+
                            "editor allows users to edit XML data in an intuitive word processor."+
                        "</paragraph>";

        org.w3c.dom.Document domDoc = null;
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder;

        try {
            docBuilder = docFactory.newDocumentBuilder();
            ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
            domDoc = docBuilder.parse(bis);         
        } catch (ParserConfigurationException e1) {         
            e1.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }       

        DocumentTraversal traversal = (DocumentTraversal) domDoc;
        NodeIterator iterator = traversal.createNodeIterator(
                domDoc.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true);

        for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {           
            String tagname = ((Element) n).getTagName();
            System.out.println(tagname + "=" + ((Element)n).getTextContent());
        }

but it gives the output like this

paragraph=XML is a browser based XML editoreditor allows users to edit XML data in an intuitive word processor.
link=XML
strong=browser based XML editor

note the paragraph element contains the text of link and strong tag, which i dont want. please suggest some ideas?

like image 392
Sark Avatar asked Aug 30 '12 06:08

Sark


2 Answers

What you want is to filter children of your node <paragraph> to only keep ones with node type Node.TEXT_NODE.

This is an example of method that will return you the desired content

public static String getFirstLevelTextContent(Node node) {
    NodeList list = node.getChildNodes();
    StringBuilder textContent = new StringBuilder();
    for (int i = 0; i < list.getLength(); ++i) {
        Node child = list.item(i);
        if (child.getNodeType() == Node.TEXT_NODE)
            textContent.append(child.getTextContent());
    }
    return textContent.toString();
}

Within your example it means:

String str = "<paragraph>" + //
        "<link>XML</link>" + //
        " is a " + //
        "<strong>browser based XML editor</strong>" + //
        "editor allows users to edit XML data in an intuitive word processor." + //
        "</paragraph>";
Document domDoc = null;
try {
    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
    ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
    domDoc = docBuilder.parse(bis);
} catch (Exception e) {
    e.printStackTrace();
}
DocumentTraversal traversal = (DocumentTraversal) domDoc;
NodeIterator iterator = traversal.createNodeIterator(domDoc.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true);
for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
    String tagname = ((Element) n).getTagName();
    System.out.println(tagname + "=" + getFirstLevelTextContent(n));
}

Output:

paragraph= is a editor allows users to edit XML data in an intuitive word processor.
link=XML
strong=browser based XML editor

What it does is iterating on all the children of a Node, keeping only TEXT (thus excluding comments, node and so on) and accumulating their respective text content.

There is no direct method in Node or Element to get only the text content at first level.

like image 127
Alex Avatar answered Oct 02 '22 14:10

Alex


If you change the last for loop into the following one it behaves as you wanted

for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {           
    String tagname = ((Element) n).getTagName();
    StringBuilder content = new StringBuilder();
    NodeList children = n.getChildNodes();
    for(int i=0; i<children.getLength(); i++) {
        Node child = children.item(i);
        if(child.getNodeName().equals("#text"))
            content.append(child.getTextContent());
    }
    System.out.println(tagname + "=" + content);
}
like image 29
halex Avatar answered Oct 02 '22 14:10

halex