我正在尝试用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文件的格式是这样的,因为最终它将以单个字符串的形式解析从数据库返回的元数据。
答案 0 :(得分:4)
好的,我已经打算计算线数,91就是这条线:
tempFile.setID(Integer.parseInt(tempVal));
所以tempFile
是null
。
答案 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();
}
}