Java Dom解析器报告错误的子节点数

时间:2012-07-25 12:11:47

标签: java xml dom children

我有以下xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<users>
<user id="0" firstname="John"/>
</users>

然后我试图用java解析它,但getchildnodes报告错误的子节点数。

Java代码:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(this.file);
document.getDocumentElement().normalize();
Element root = document.getDocumentElement();
NodeList nodes = root.getChildNodes();
System.out.println(nodes.getLength());

结果:3

此外,我正在获取用于访问节点属性的NPE,因此我猜测某些内容非常糟糕。

4 个答案:

答案 0 :(得分:4)

子节点由空格的元素和文本节点组成。您需要在处理属性之前检查节点类型。您可能还需要考虑从Java SE 5开始使用JDK / JRE中提供的javax.xml.xpath API。

示例1

此示例演示如何针对DOM发出XPath语句。

package forum11649396;

import java.io.StringReader;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?><users><user id='0' firstname='John'/></users>";

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.parse(new InputSource(new StringReader(xml)));

        XPathFactory xpf = XPathFactory.newInstance();
        XPath xpath = xpf.newXPath();
        Element userElement = (Element) xpath.evaluate("/users/user", document, XPathConstants.NODE);
        System.out.println(userElement.getAttribute("id"));
        System.out.println(userElement.getAttribute("firstname"));
    }

}

示例2

以下示例演示如何针对InputSource发出XPath语句以获取DOM节点。这样您就不必自己将XML解析为DOM。

package forum11649396;

import java.io.StringReader;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?><users><user id='0' firstname='John'/></users>";

        XPathFactory xpf = XPathFactory.newInstance();
        XPath xpath = xpf.newXPath();
        InputSource inputSource = new InputSource(new StringReader(xml));
        Element userElement = (Element) xpath.evaluate("/users/user", inputSource, XPathConstants.NODE);
        System.out.println(userElement.getAttribute("id"));
        System.out.println(userElement.getAttribute("firstname"));
    }

}

答案 1 :(得分:3)

有三个子节点:

  • 包含换行符的文本节点
  • 元素节点(标记用户)
  • 包含换行符的文本节点

因此,在处理子节点时,请检查元素节点。

答案 2 :(得分:1)

您必须确保考虑节点之间的'\ n',它们计算文本节点。您可以使用if(root.getNodeType() == Node.ELEMENT_NODE)

进行测试
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(this.file);
        document.getDocumentElement().normalize();
        for(Node root = document.getFirstChild(); root != null; root = root.getNextSibling()) {
            if(root.getNodeType() == Node.ELEMENT_NODE) {
                NodeList nodes = root.getChildNodes();
                System.out.println(root.getNodeName() + " has "+nodes.getLength()+" children");
                for(int i=0; i<nodes.getLength(); i++) {
                    Node n = nodes.item(i);
                    System.out.println("\t"+n.getNodeName());
                }
            }
        }

答案 3 :(得分:0)

在尝试访问属性时,我没有注意到有关NPE的最后一个注释的任何答案。

  

此外,我正在获取用于访问节点属性的NPE,因此我猜测某些内容非常糟糕。

由于我在几个网站上看到了以下建议,我认为这是访问属性的常用方法:

String myPropValue = node.getAttributes().getNamedItem("myProp").getNodeValue();

如果节点始终包含myProp属性,则可以正常工作,但如果它没有属性,getAttributes将返回null。此外,如果存在属性但没有myProp属性,则getNamedItem将返回null。

我正在使用

public static String getStrAttr(Node node, String key) {
    if (node.hasAttributes()) {
        Node item = node.getAttributes().getNamedItem(key);
        if (item != null) {
            return item.getNodeValue();
        }
    }

    return null;
}

public static int getIntAttr(Node node, String key) {
    if (node.hasAttributes()) {
        Node item = node.getAttributes().getNamedItem(key);
        if (item != null) {
            return Integer.parseInt(item.getNodeValue());
        }
    }

    return -1;
}

在公用事业类中,但您的里程可能会有所不同。