tags:

views:

7090

answers:

2

I can't fetch text value with Node.getNodeValue(), Node.getFirstChild().getNodeValue() or with Node.getTextContent(). My XML is like

<add job="351">
 <tag>foobar</tag>
 <tag>foobar2</tag>
</add>

And i'm trying to get tag value (non-text element fetching works fine). My Java code sounds like

        Document doc = db.parse(new File(args[0]));
        Node n = doc.getFirstChild();
        NodeList nl = n.getChildNodes();   
        Node an,an2;

        for (int i=0; i < nl.getLength(); i++) {
            an = nl.item(i);
            if(an.getNodeType()==Node.ELEMENT_NODE) {
                NodeList nl2 = an.getChildNodes();

                for(int i2=0; i2<nl2.getLength(); i2++) {
                   an2 = nl2.item(i2);
                       // DEBUG PRINTS
                       System.out.println(an2.getNodeName() + ": type (" + an2.getNodeType() + "):");
                       if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getTextContent());
                       if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getNodeValue());
                       System.out.println(an2.getTextContent());
                       System.out.println(an2.getNodeValue());

                }

            }
        }

It prints out

     tag type (1): 
     tag1
     tag1
     tag1
     null
     #text type (3):
     _blank line_
     _blank line_
     ...

Thanks for the help.

Emilio

+1  A: 

I'd print out the result of an2.getNodeName() as well for debugging purposes. My guess is that your tree crawling code isn't crawling to the nodes that you think it is. That suspicion is enhanced by the lack of checking for node names in your code.

EDIT: Other than that, the javadoc for Node defines "getNodeValue()" to return null for Nodes of type Element. Therefore, you really should be using getTextContent(). I'm not sure why that wouldn't give you the text that you want.

Perhaps iterate the children of your tag node and see what types are there?

EDIT2:

Tried this code and it works for me:

String xml = "<add job=\"351\">\n" +
             "    <tag>foobar</tag>\n" +
             "    <tag>foobar2</tag>\n" +
             "</add>";
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
ByteArrayInputStream bis = new ByteArrayInputStream(xml.getBytes());
Document doc = db.parse(bis);
Node n = doc.getFirstChild();
NodeList nl = n.getChildNodes();
Node an,an2;

for (int i=0; i < nl.getLength(); i++) {
    an = nl.item(i);
    if(an.getNodeType()==Node.ELEMENT_NODE) {
        NodeList nl2 = an.getChildNodes();

        for(int i2=0; i2<nl2.getLength(); i2++) {
           an2 = nl2.item(i2);
               // DEBUG PRINTS
               System.out.println(an2.getNodeName() + ": type (" + an2.getNodeType() + "):");
               if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getTextContent());
               if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getNodeValue());
               System.out.println(an2.getTextContent());
               System.out.println(an2.getNodeValue());
        }

    }
}

Output was:

#text: type (3): foobar foobar
#text: type (3): foobar2 foobar2

jsight
now i'm printing also .getNodeName().. and it returns the right value (tag)
Emilio
My tag element doesn't have childs :/ If I try simply with an2.getFirstChild().getTextContent() or similar it throw a NullPointerException
Emilio
Try just using getChildElements instead of getFirstChild(). Perhaps getFirstChild() is skipping over Element typed nodes for some reason?
jsight
I've just tried.. same result
Emilio
+1  A: 

If your XML goes quite deep, you might want to consider using XPath, which comes with your JRE, so you can access the contents far more easily using:

String text = xp.evaluate("//add[@job='351']/tag[position()=1]/text()", 
    document.getDocumentElement());

Full example:

import static org.junit.Assert.assertEquals;
import java.io.StringReader;    
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;    
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

public class XPathTest {

    private Document document;

    @Before
    public void setup() throws Exception {
        String xml = "<add job=\"351\"><tag>foobar</tag><tag>foobar2</tag></add>";
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        document = db.parse(new InputSource(new StringReader(xml)));
    }

    @Test
    public void testXPath() throws Exception {
        XPathFactory xpf = XPathFactory.newInstance();
        XPath xp = xpf.newXPath();
        String text = xp.evaluate("//add[@job='351']/tag[position()=1]/text()",
                document.getDocumentElement());
        assertEquals("foobar", text);
    }
}
toolkit
Unfortunatly is an educational job and i must use DOM apis :/
Emilio
Can you use the JDOM API? It's much easier to work with.
jdigital