SAX XML Parser抛出空指针异常

时间:2012-01-06 16:33:48

标签: java xml nullpointerexception sax saxparser

我正在尝试用Java编写SAX XML Parser并且我一直得到一个空指针异常,我似乎无法弄清楚如何修复。这是堆栈跟踪:

Exception in thread "main" java.lang.NullPointerException
    at SAXParserExample.endElement(SAXParserExample.java:91)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at javax.xml.parsers.SAXParser.parse(Unknown Source)
    at javax.xml.parsers.SAXParser.parse(Unknown Source)
    at SAXParserExample.parseDocument(SAXParserExample.java:43)
    at SAXParserExample.runExample(SAXParserExample.java:29)
    at SAXParserExample.main(SAXParserExample.java:107)

以下是SAX Parser的主要类:

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

public class SAXParserExample extends DefaultHandler{

    List<DataRow> myFiles;

    private String tempVal;

    //to maintain context
    private DataRow tempFile;


    public SAXParserExample(){
        myFiles = new ArrayList<DataRow>();
    }

    public void runExample() {
        parseDocument();
        printData();
    }

    private void parseDocument() {

        //get a factory
        SAXParserFactory spf = SAXParserFactory.newInstance();
        try {

            //get a new instance of parser
            SAXParser sp = spf.newSAXParser();

            //parse the file and also register this class for call backs
            sp.parse("./src/filelist.xml", this);

        }catch(SAXException se) {
            se.printStackTrace();
        }catch(ParserConfigurationException pce) {
            pce.printStackTrace();
        }catch(IOException ie) {
            ie.printStackTrace();
        }
    }

    /**
     * Iterate through the list and print
     * the contents
     */
    private void printData(){

        System.out.println("No of Files '" + myFiles.size() + "'.");

        Iterator<DataRow> it = myFiles.iterator();
        while(it.hasNext()) {
            System.out.println(it.next().toString());
        }
    }


    //Event Handlers
    public void startElement(String uri, String localName, String qName) throws SAXException {
        //reset
        tempVal = "";
        if(qName.equalsIgnoreCase("DATAROW")) {
            //create a new instance of Datarow
            tempFile = new DataRow();
        }
    }


    public void characters(char[] ch, int start, int length) throws SAXException {
        tempVal = new String(ch,start,length);
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {

        if(qName.equalsIgnoreCase("DATAROW")) {
            //add it to the list
            myFiles.add(tempFile);

        }else if (qName.equalsIgnoreCase("ID")) {
            tempFile.setID(Integer.parseInt(tempVal));
        }else if (qName.equalsIgnoreCase("FILENAME")) {
            tempFile.setFileName(tempVal);
        }else if (qName.equalsIgnoreCase("SEARCHKEY")) {
            tempFile.setSearchKey(tempVal);
        }else if (qName.equalsIgnoreCase("DATEADDED")) {
            tempFile.setDateAdded(tempVal);
        }else if (qName.equalsIgnoreCase("APPLICATIONID")) {
            tempFile.setApplicationID(tempVal);
        }else if (qName.equalsIgnoreCase("DISPLAYFILENAME")) {
            tempFile.setDisplayFileName(tempVal);
        }
    }

    public static void main(String[] args){
        SAXParserExample spe = new SAXParserExample();
        spe.runExample();
    }
}

这是主类中使用的DataRow类:

public class DataRow {

    private String fileName = "", searchKey = "", dateAdded = "", applicationID = "", displayFileName = "";

    private int id = 0;

    public DataRow(){

    }

    public DataRow(int id, String fileName, String searchKey, String dateAdded, String applicationID, String displayFileName) {
        this.id  = id;
        this.fileName = fileName;
        this.searchKey = searchKey;
        this.dateAdded = dateAdded;
        this.applicationID = applicationID;
        this.displayFileName = displayFileName;

    }
    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public int getID() {
        return id;
    }

    public void setID(int id) {
        this.id = id;
    }

    public String getSearchKey() {
        return searchKey;
    }

    public void setSearchKey(String searchKey) {
        this.searchKey = searchKey;
    }

    public String getDateAdded() {
        return dateAdded;
    }

    public void setDateAdded(String dateAdded) {
        this.dateAdded = dateAdded;
    }   

    public String getApplicationID() {
        return applicationID;
    }

    public void setApplicationID(String applicationID) {
        this.applicationID = applicationID;
    }

    public String getDisplayFileName() {
        return displayFileName;
    }

    public void setDisplayFileName(String displayFileName) {
        this.displayFileName = displayFileName;
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("File Details - ");
        sb.append("ID:" + getID());
        sb.append(", ");
        sb.append("Filename:" + getFileName());
        sb.append(", ");
        sb.append("Search Key:" + getSearchKey());
        sb.append(", ");
        sb.append("Date Added:" + getDateAdded());
        sb.append(", ");
        sb.append("Application ID:" + getApplicationID());
        sb.append(", ");
        sb.append("Display Filename:" + getDisplayFileName());
        sb.append(".");

        return sb.toString();
    }
}

这是我试图解析的XML文件:

<DATAROW><ID>61</ID><FILENAME>TestFile.txt</FILENAME><SEARCHKEY>12345</SEARCHKEY><DATEADDED>2012-1-6 9.12.32.0</DATEADDED><APPLICATIONID>PCIS</APPLICATIONID><DISPLAYFILENAME>TestFile.txt</DISPLAYFILENAME></DATAROW><DATAROW><ID>44</ID><FILENAME>TestFile.txt</FILENAME><SEARCHKEY>12345</SEARCHKEY><DATEADDED>2012-2-5 14.39.50.0</DATEADDED><APPLICATIONID>PCIS</APPLICATIONID><DISPLAYFILENAME>TestFile.txt</DISPLAYFILENAME></DATAROW>

XML文件的格式是这样的,因为最终它将以单个字符串的形式解析从数据库返回的元数据。

4 个答案:

答案 0 :(得分:4)

好的,我已经打算计算线数,91就是这条线:

tempFile.setID(Integer.parseInt(tempVal));

所以tempFilenull

答案 1 :(得分:3)

从异常中可以看出,您正在尝试取消引用值为null的变量。为什么不查看第91行并打印出所有用于查看哪些变量为null的变量。我的猜测是永远不会分配tempFile,这意味着它在第91行上为空。

答案 2 :(得分:2)

我没有使用SAX很长一段时间,所以可能是错的,但我的猜测是你应该使用localName,而不是qname,因为没有合格的名字(即有一些名字) XML中的名称空间,如'namespace:name')。因此,提供的qname很可能是null,因为您访问它进行比较,就会得到一个NPE。

根据javadoc(http://docs.oracle.com/javase/1.4.2/docs/api/org/xml/sax/helpers/DefaultHandler.html#endElement(java.lang.String,java。 lang.String,java.lang.String)),如果XML文档中没有提供的qname,则它可能为空。

答案 3 :(得分:0)

您的覆盖功能

public void startElement(String uri, String localName, String qName) throws SAXException{...}

应该是

public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException{...}

将其更改为如下,效果很好

public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
        //reset
        tempVal = "";
        if(qName.equalsIgnoreCase("DATAROW")) {
            //create a new instance of Datarow
            tempFile = new DataRow();
        }
    }