【问题标题】:SAX XML Parser throwing Null Pointer ExceptionSAX XML 解析器抛出空指针异常
【发布时间】:2012-02-04 09:02:05
【问题描述】:

我正在尝试用 Java 编写一个 SAX XML 解析器,但我不断收到一个空指针异常,我似乎无法弄清楚如何修复。这是堆栈跟踪:

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 解析器的主要类:

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 文件采用这种格式,因为最终它将解析从数据库以单个字符串形式返回的元数据。

【问题讨论】:

    标签: java xml nullpointerexception sax saxparser


    【解决方案1】:

    好的,我已经费心数了几行,91 是这一行:

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

    所以tempFilenull

    【讨论】:

    • myFiles 在构造函数中被初始化。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我已经有一段时间没有使用 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) ),如果提供的 qname 在 XML 文档中不可用,则可能为空。

      【讨论】:

        【解决方案4】:

        你的覆盖函数

        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();
                }
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-22
          相关资源
          最近更新 更多