使用Java DOM解析XML

4

我刚开始学习Java,我的任务是使用当前网址http://belbooner.site40.net/testXmls/details.xml通过http解析一个xml文件。

我创建了一些类来使用Dom方法进行解析,但在试图获取节点值时出现了java.lang.NullPointerException错误。以下是代码:

import java.security.KeyStore.Builder;
import java.util.*;
import java.io.*;
import java.net.*;
import javax.swing.text.Document;
import javax.xml.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.*;
import org.w3c.dom.CharacterData;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;


public class RequestResponse {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        URL url = new URL("http://belbooner.site40.net/testXmls/details.xml");
        RequestResponse req= new RequestResponse();
        req.getHTTPXml(url);
    }

     void getHTTPXml(URL url) throws ParserConfigurationException, IOException, SAXException {

                //URL url = new URL("http://belbooner.site40.net/testXmls/details.xml");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("POST");
                conn.setRequestProperty("ACCEPT","application/xml");
                InputStream xml = conn.getInputStream();


                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = factory.newDocumentBuilder();
                org.w3c.dom.Document document = builder.parse(xml);

                System.out.println(document);
                String doctype = conn.getContentType(); 
                System.out.print(doctype);

                NodeList root = document.getChildNodes();

                Node server = getNodes("server",root);
                Node check = getNodes("check", server.getChildNodes());
                NodeList nodes = check.getChildNodes();

                String checkid= getNodeValue("checkid", nodes);
                System.out.println(checkid);


                conn.disconnect();  

                //return (Document) DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xml);


     }


    Node getNodes(String tagName, NodeList nodes) {
        for(int i=0; i< nodes.getLength();i++) {
            Node node= nodes.item(i);
            if(node.getNodeName().equalsIgnoreCase(tagName)) {
                return node;
            }

        }
        return null;
    }

    String getNodeValue(String tagName, NodeList nodes ) {
        for ( int i = 0; i < nodes.getLength(); i++ ) {
            Node node = nodes.item(i);
            if (node.getNodeName().equalsIgnoreCase(tagName)) {
                NodeList childNodes = node.getChildNodes();
                for (int y = 0; y < childNodes.getLength(); y++ ) {
                     Node data = childNodes.item(y);
                     if ( data.getNodeType() == Node.TEXT_NODE ) {
                         return data.getNodeValue();
                     }
                     if(data instanceof CharacterData) {
                         CharacterData cd= (CharacterData) data;
                         return cd.getData();
                     }
                 }

            }
        }
        return "";
    }








    }

我得到的堆栈跟踪如下:
application/xmlException in thread "main" java.lang.NullPointerException at 
RequestResponse.getHTTPXml(RequestResponse.java:45) at
RequestResponse.main(RequestResponse.java:22)

在将Node server = getNodes("server",root);更改为`时,需要注意:
    Node resultNode = getNodes("result", root);
    Node server = getNodes("server", resultNode.getChildNodes());`

   `application/xmlException in thread "main" java.lang.NullPointerException
        at RequestResponse.getHTTPXml(RequestResponse.java:49)
        at RequestResponse.main(RequestResponse.java:22)

`

请帮我找出问题所在。


3
请提供NullPointerException的堆栈跟踪信息,以便更好地理解问题。 - Henrik Aasted Sørensen
你能分享一下你遇到空指针的那行代码吗? - Narendra Pathai
应用程序/ XML异常 在主线程中的java.lang.NullPointerException 在RequestResponse.java的第45行 在RequestResponse.java的第22行调用main函数。 - Arshak92
请打印错误堆栈跟踪。 - Bhavik Ambani
@Arshak92:我已经为您编辑了帖子,将堆栈跟踪添加到问题中,并回答了您的问题。 - pabrantes
2个回答

3
问题在于Node server = getNodes("server",root);返回了null。
为什么会发生这种情况呢?看看你是如何实现getNodes的。
Node getNodes(String tagName, NodeList nodes) {
    for(int i=0; i< nodes.getLength();i++) {
        Node node= nodes.item(i);
        if(node.getNodeName().equalsIgnoreCase(tagName)) {
            return node;
        }
    }
    return null;
}

您正在将文档根目录作为输入,它是一个单独的“Result”节点,您要遍历它并比较节点的名称是否为“server”,但实际上永远不会是这种情况,因此您将返回null并获得NPE。
您的节点查找必须按以下方式进行:
 NodeList root = document.getChildNodes();
// Keep in mind that you have the following structure:
// result
//   server
//    checks
//     check
//      checkId
//     check
//      checkId

Node resultNode = getNodes("result", root);
Node server = getNodes("server", resultNode.getChildNodes());
Node checks = getNodes("checks", server.getChildNodes());
NodeList childNodes = checks.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
    Node possibleCheck = childNodes.item(i);
    if (possibleCheck.getNodeName().equals("check")) {
    String checkid = getNodeValue("checkid", possibleCheck.getChildNodes());
    System.out.println(checkid);
    }
}

通过这种方式,您将遍历正确的节点列表。

我无法更改为root.getChildNodes(),因为它不是一个正确的节点,也许你想说的是NodeList。正如你所看到的,还有另一个名为root的NodeList,我不能从NodeList中获取NodeList。 - Arshak92
@Arshak92:你说得对,抱歉,我看到根节点有一个“Node”。我已经编辑了我的答案。 - pabrantes
我认为问题出在getNodes方法上,导致了这样的异常,我会集中精力解决它。 - Arshak92
@Arshak92:请重新编辑您的问题,附上更新后的代码和异常信息,这样我或其他 StackOverflow 成员可以帮助您。另外,在我完全帮助您之前,请取消接受我的答案。 - pabrantes
@Arshak92:很可能你的错误在于 getNodes("check", server.getChildNodes()); 节点名称应该是 "checks" 而不是 "check"。 - pabrantes
显示剩余2条评论

2
使用XPath解析XML比普通迭代更高效、更灵活。 IBM的XPath教程
Orielly的XPath参考教程
Oracle Java的XPath参考教程
请尝试下面的代码。
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class RequestResponse {
    public static void main(String[] args) throws ParserConfigurationException,
            IOException, SAXException {
        URL url = new URL("http://belbooner.site40.net/testXmls/details.xml");
        RequestResponse req = new RequestResponse();
        req.getHTTPXml(url);
    }

    void getHTTPXml(URL url) throws ParserConfigurationException, IOException,
            SAXException {
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("ACCEPT", "application/xml");
        InputStream xml = conn.getInputStream();

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        org.w3c.dom.Document document = builder.parse(xml);

        System.out.println(document);
        String doctype = conn.getContentType();
        System.out.println(doctype);

        XPathFactory pathFactory = XPathFactory.newInstance();
        XPath path = pathFactory.newXPath();
        XPathExpression expression;
        try {
            expression = path.compile("/result/server/checks/check/checkid");
            NodeList nodeList = (NodeList) expression.evaluate(document,
                    XPathConstants.NODESET);

            String checkids[] = getNodeValue(nodeList);
            for (String checkid : checkids) {
                System.out.print(checkid + ", ");
            }

        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        conn.disconnect();

    }

    String[] getNodeValue(NodeList nodes) {
        String checkIds[] = new String[nodes.getLength()];
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            checkIds[i] = node.getTextContent();
        }
        return checkIds;
    }

} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接