2012-01-06 98 views
0

我想写一个SAX XML解析器在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文件的格式如此,因为最终它将以单个字符串的形式解析数据库的元数据返回。

+0

哪一个是线91? – Tudor 2012-01-06 16:35:56

回答

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可能为空。

4

好吧,我不屑于计数线和91是这一行:

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

所以tempFilenull

+0

myFiles在构造函数中初始化。 – 2012-01-06 16:42:42

3

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

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