tags:

views:

442

answers:

3

I've written class to parse some xml into an object and it's not working correctly, when I try and get the value of a node I get a null rather than the contents of the node.

Here is a simplified version of my class that just does the xml parsing of a single node:

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XmlReaderCutDown {

    private static Logger logger = Logger.getLogger(CtiButtonsXmlReader.class);

    public static void testXml(String confFile){
     DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
     try {
      DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
      Document doc = docBuilder.parse(new File(confFile));
      doc.getDocumentElement().normalize();
      if (logger.isDebugEnabled()){
       logger.debug("The root element is " + doc.getDocumentElement().getNodeName());
      }

      NodeList rows =  doc.getElementsByTagName("row");

      NodeList topRowButtons = ((Element)rows.item(0)).getElementsByTagName("button");
      logger.debug("Top row has " +topRowButtons.getLength() + " items.");
      Node buttonNode = topRowButtons.item(0);

      NodeList nodeList = ((Element)buttonNode).getElementsByTagName("id");
      logger.debug("Node list count for "+ "id" + " = " + nodeList.getLength());
      Element element = (Element)nodeList.item(0);
      String xx = element.getNodeValue();
      logger.debug(xx);
      String elementValue = ((Node)element).getNodeValue();
      if (elementValue != null) {
       elementValue = elementValue.trim();
      }
      else {
       logger.debug("Value was null");
      }
      logger.debug("Node id = "+ elementValue);

     } catch (ParserConfigurationException e) {

      logger.fatal(e.toString(),e);
     } catch (SAXException e) {
      logger.fatal(e.toString(),e);
     } catch (IOException e) {
      logger.fatal(e.toString(),e);
     } catch (Exception e) {
      logger.fatal(e.toString(),e);
     }

    }


    public static void main(String[] args){
     DOMConfigurator.configure("log4j.xml");

     testXml("test.xml");
    }
}

And here is a stripped down version of my xml file:

<?xml version="1.0"?>
<root>
    <row>
     <button>
      <id>this is an id</id>
      <action>action</action>
      <image-src>../images/img.png</image-src>
      <alt-text>alt txt</alt-text>
      <tool-tip>Tool tip</tool-tip>
     </button>
    </row>
</root>

This is what the logging statments output:

DEBUG XmlReaderCutDown - The root element is root

DEBUG XmlReaderCutDown - Top row has 1 items.

DEBUG XmlReaderCutDown - Node list count for id = 1

DEBUG XmlReaderCutDown -

DEBUG XmlReaderCutDown - Value was null

DEBUG XmlReaderCutDown - Node id = null

Why isn't it getting the text in the xml node?

I'm running using JDK 1.6_10

+4  A: 

Because the element you get is the parent element of the text one, containing the text you need. To access the text of this element, you shall use getTextContent instead of getNodeValue.

For more information, see the table in the Node javadoc.

Valentin Rocher
Thanks that works a charm, one question though why does the code on this page http://www.java-tips.org/java-se-tips/javax.xml.parsers/how-to-read-xml-file-in-java.html work when it uses node value?
Omar Kooheji
Because they get the first child of the element in question, which is the text node. It's globally the same thing that getTextContent does, only safer in the getTextContent case.
Valentin Rocher
You can use nodeValue() on a Text node.
Stephen Denne
+2  A: 

See http://java.sun.com/j2se/1.5.0/docs/api/org/w3c/dom/Node.html . Element.getNodeValue() always returns null. You should use Element.getTextContent()

Pierre
+1  A: 

Consider using XPath as an alternative to manually walking nodes:

  public static void testXml(String confFile)
      throws XPathExpressionException {
    XPathFactory xpFactory = XPathFactory.newInstance();
    XPath xpath = xpFactory.newXPath();

    NodeList rows = (NodeList) xpath.evaluate("root/row",
        new InputSource(confFile), XPathConstants.NODESET);

    for (int i = 0; i < rows.getLength(); i++) {
      Node row = rows.item(i);
      String id = xpath.evaluate("button/id", row);
      System.out.println("id=" + id);
    }
  }

  public static void main(String[] args)
      throws XPathExpressionException {
    testXml("test.xml");
  }
McDowell