6

我有以下 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

4 回答 4

4

子节点由用于空白的元素和文本节点组成。您需要在处理属性之前检查节点类型。您可能还想考虑使用javax.xml.xpath从 Java SE 5 开始的 JDK/JRE 中可用的 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

下面的示例演示如何针对 发出 XPath 语句InputSource以获取 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"));
    }

}
于 2012-07-25T12:18:54.640 回答
3

有三个子节点:

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

所以在处理子节点时,要检查元素节点。

于 2012-07-25T12:19:44.980 回答
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());
                }
            }
        }
于 2012-07-25T12:25:13.573 回答
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;
}

在实用程序类中,但您的里程可能会有所不同。

于 2013-01-12T04:50:10.563 回答