为什么我必须在解析RSS提要时初始化我的对象两次

时间:2013-12-19 09:24:25

标签: java android rss saxparser

在我的MainActivity.java中,我编写了用于解析的代码,如

public void parser() {
    try {
        /****** Creating a new instance of the SAX parser ****************/
        SAXParserFactory saxPF = SAXParserFactory.newInstance();
        SAXParser saxParser = saxPF.newSAXParser();
        XMLReader xmlReader = saxParser.getXMLReader();

        URL url = new URL("http://ibnlive.in.com/ibnrss/rss/world/world.xml");

        myXMLHandler = new FeedsXMLHandler();
        xmlReader.setContentHandler(myXMLHandler);
        xmlReader.parse(new InputSource(url.openStream()));     
    } catch (Exception e) {
        e.printStackTrace();
    }
    feedsData = myXMLHandler.getXMLData();
}

我正在使用IBN Live的rss feed

我的处理程序类XMLHandler.java如下:

@Override
public void startElement(String uri, String localName, String qName,
                     Attributes attributes) throws SAXException {
    elementValue = "";
    elementOn = true;

    if (localName.equalsIgnoreCase("rss")) {
        dataArray = new ArrayList<FeedsItems>();
        data = new FeedsItems();
        Log.v("Item", "I am in rss block");
    }

    if (localName.equalsIgnoreCase("channel")) {
       Log.v("Item", "I am in channel block");
    }

    if (localName.equalsIgnoreCase("item")) {
       data = new FeedsItems();
       Log.v("Item", "I am in item block");
    }

    if (localName.equalsIgnoreCase("description")) {
       bufferDesc = new StringBuffer();
       elementOn = true;
    }

    if (localName.equalsIgnoreCase("title")) {
       bufferTitle = new StringBuffer();
       elementOn = true;
    }

    if (localName.equalsIgnoreCase("link")) {
            bufferLink = new StringBuffer();
            elementOn = true;
    }
}

/*********** Method will be called when the tags of the XML end **************/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
    elementOn = false;

    /*** Sets the values after retrieving the values from the XML tags ******/
    if (localName.equalsIgnoreCase("title")) {
        elementOn = false;

        data.setTitle(bufferTitle.toString());
        bufferTitle.delete(0, bufferTitle.length());
        Log.v("title", data.getTitle());
    }
    else if (localName.equalsIgnoreCase("link")) {
        elementOn = false;

        data.setFeedsUrl(bufferLink.toString());
        bufferLink.delete(0, bufferLink.length());
    }
    else if (localName.equalsIgnoreCase("description")) {
        elementOn = false;

        data.setDescription(bufferDesc.toString());
        bufferDesc.delete(0, bufferDesc.length());
    } else if (localName.equalsIgnoreCase("item")) {
        dataArray.add(data);
    }
}

public void characters(char[] ch, int start, int length) throws SAXException {
    if (elementOn) {
        if (bufferDesc != null) {
            bufferDesc.append(new String(ch, start, length).trim());
        }

        if (bufferTitle != null) {
            bufferTitle.append(new String(ch, start, length).trim());
        }

        if (bufferLink != null) {
            bufferLink.append(new String(ch, start, length).trim());
        }

    } else {
        elementValue = new String(ch, start, length);
    }
}

问题是为什么我必须两次初始化我的FeedsItems类,首先是在'rss'块中,第二个在'item'块中?

如果我只在“rss”块中初始化它,那么相同的数据会重复添加到我的AarrayList中,这是响应中的最后一个Feed项,如果我只在'item'块中初始化它会给我以下错误

java.lang.NullPointerException
at com.example.feedsdemo.FeedsXMLHandler.endElement(FeedsXMLHandler.java:83)
at org.apache.harmony.xml.ExpatParser.endElement(ExpatParser.java:160)
at org.apache.harmony.xml.ExpatParser.append(Native Method)
at org.apache.harmony.xml.ExpatParser.parseFragment(ExpatParser.java:521)
at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:482)
at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:320)
at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:277)
at com.example.feedsdemo.NewsFeedsActivity.parser(NewsFeedsActivity.java:65)
at com.example.feedsdemo.NewsFeedsActivity.onCreate(NewsFeedsActivity.java:36)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
at android.app.ActivityThread.access$2300(ActivityThread.java:125)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:0)

试试这个..

@Override
public void startElement(String uri, String localName, String qName,
                     Attributes attributes) throws SAXException {
    elementValue = "";
    elementOn = true;

    if (localName.equalsIgnoreCase("rss")) {
        dataArray = new ArrayList<FeedsItems>();
        data = new FeedsItems();
        bufferLink = new StringBuffer();
        bufferDesc = new StringBuffer();
        bufferTitle = new StringBuffer();
        Log.v("Item", "I am in rss block");
    }    
    else if (localName.equalsIgnoreCase("channel")) {
       Log.v("Item", "I am in channel block");
    }    
    else if (localName.equalsIgnoreCase("item")) {           
       Log.v("Item", "I am in item block");
    }    
    else if (localName.equalsIgnoreCase("description")) {          
       elementOn = true;
    }    
    else if (localName.equalsIgnoreCase("title")) {
       elementOn = true;
    }    
    else if (localName.equalsIgnoreCase("link")) {                
            elementOn = true;
    }
}

答案 1 :(得分:0)

您必须执行两次,因为<channel><item>(以及<image>)都使用<title>标记。如果你没有在

中实现它
if (localName.equalsIgnoreCase("rss")) {
...
}

当您在第一个<title>

中找到第一个<channel>时,您将收到您发布的NullPointerException

你要做的是要么保留两者,要么删除“rss”,并在endElement()中添加一个检查,标题属于<item>,而不是任何其他元素。