I am making an android app that downloads an xml file and creates a list view where the downloaded data are shown. The app was working fine. Suddenly the screen appears empty. I did not make any change. I have a variable that shows the length of the arrayadapter and it appears to be 0. The logcat shows a NullPointerException in the file below:
package com.makemyandroidapp.example.stacksites;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.content.Context;
public class SitesXmlPullParser {
/*static final String KEY_SITE = "site";
static final String KEY_NAME = "name";
static final String KEY_LINK = "link";
static final String KEY_ABOUT = "about"; */
static final String KEY_SITE = "pozicioni";
static final String KEY_KOMPANIA = "kompania";
static final String KEY_POZICIONI = "pozicioni";
static final String KEY_KATEGORIA = "kategoria";
static final String KEY_QYTETI = "qyteti";
static final String KEY_IMAGE_URL = "image";
public static List<StackSite> getStackSitesFromFile(Context ctx) {
// List of StackSites that we will return
List<StackSite> stackSites;
stackSites = new ArrayList<StackSite>();
// temp holder for current StackSite while parsing
StackSite curStackSite = null;
// temp holder for current text value while parsing
String curText = "";
try {
// Get our factory and PullParser
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xpp = factory.newPullParser();
// Open up InputStream and Reader of our file.
FileInputStream fis = ctx.openFileInput("StackSites.xml");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
// point the parser to our file.
xpp.setInput(reader);
// get initial eventType
int eventType = xpp.getEventType();
boolean done = false;
int count=0;
// Loop through pull events until we reach END_DOCUMENT
while (eventType != XmlPullParser.END_DOCUMENT) {
// Get the current tag
String tagname = xpp.getName();
// React to different event types appropriately
switch (eventType) {
case XmlPullParser.START_TAG:
if (tagname.equalsIgnoreCase(KEY_SITE)&&count==0) {
// If we are starting a new <site> block we need
//a new StackSite object to represent it
curStackSite = new StackSite();
count=1;
System.out.println(count);
}
break;
case XmlPullParser.TEXT:
{String s="";
String href="";
s=xpp.getText(); //in case of cdsect this is null otherwise you get the text right here already
if (s==null) { //what would happen if it encounters in fact a cdsect
int event=xpp.nextToken(); //this is the main technical important line
if (event==XmlPullParser.CDSECT) {
s=xpp.getText();
}
}
curText=s;
break;}
case XmlPullParser.END_TAG:
if (tagname.equalsIgnoreCase(KEY_SITE)&&count==1) {
// if </site> then we are done with current Site
// add it to the list.
count=0;
System.out.println(curText);
curStackSite.setPozicioni(curText);
}
else if (tagname.equalsIgnoreCase(KEY_SITE)&&count==0){
stackSites.add(curStackSite);
} else if (tagname.equalsIgnoreCase(KEY_KOMPANIA)) {
// if </name> use setName() on curSite
//curStackSite.setKompania(curText);
System.out.println(curText+"kooooooooooooooooooooooooooooooooooooooot");
curStackSite.setKompania(curText);
System.out.println(curText+"kooooooooooooooooooooooooooooooooooooooot");
} else if (tagname.equalsIgnoreCase(KEY_KATEGORIA)) {
// if </about> use setAbout() on curSite
curStackSite.setKategoria(curText);
} else if (tagname.equalsIgnoreCase(KEY_QYTETI)){
curStackSite.setQyteti(curText);
}
break;
default:
break;
}
//move on to next iteration
eventType = xpp.next();
}
}
catch (Exception e) {
e.printStackTrace();
}
// return the populated list.
return stackSites;
}
}
NullPointerException occurs in this line:
curStackSite.setKompania(curText);
Please help me! Thanks in advance!
I'd say either to try and instancing an object and then "nulling it", before your try statement or making sure that
curStackSite = new StackSite();
Is reachable
You have it within a case within switch, so it may not always come to it. Which means the reference may fail if the object wasn't instanced.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I need to parse xml data in android. I have seen this project: here from github which teaches how to parse xml data in listbox. However, I want to get xml data to different strings. Although, I have used pretty much the same code as in the github project but I only get error and the app stops responding.
Code:
public class Main extends Fragment {
android.view.View myview;
EditText number;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myview = inflater.inflate(R.layout.fragment_screen, container, false);
number = (EditText) myview.findViewById(R.id.number);
XmlParser par = new XmlParser();
number.setText(par.getStackSitesFromFile(getActivity().getBaseContext())
.get(0).getLink()); **Error here**
return myview;
}
}
XmlParser.java
public class XmlParser {
static final String KEY_SITE = "rate";
static final String KEY_NAME = "Name";
static final String KEY_LINK = "Rate";
static final String KEY_ABOUT = "Date";
static final String KEY_IMAGE_URL = "Time";
public static List<HandleXML> getStackSitesFromFile(Context ctx) {
// List of StackSites that we will return
List<HandleXML> stackSites;
stackSites = new ArrayList<HandleXML>();
// temp holder for current StackSite while parsing
HandleXML curStackSite = null;
// temp holder for current text value while parsing
String curText = "";
try {
// Get our factory and PullParser
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xpp = factory.newPullParser();
// Open up InputStream and Reader of our file.
FileInputStream fis = ctx.openFileInput("/sdcard/rates.xml");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
// point the parser to our file.
xpp.setInput(reader);
// get initial eventType
int eventType = xpp.getEventType();
// Loop through pull events until we reach END_DOCUMENT
while (eventType != XmlPullParser.END_DOCUMENT) {
// Get the current tag
String tagname = xpp.getName();
// React to different event types appropriately
switch (eventType) {
case XmlPullParser.START_TAG:
if (tagname.equals("test")) {
curStackSite = new HandleXML();
}
break;
case XmlPullParser.TEXT:
//grab the current text so we can use it in END_TAG event
curText = xpp.getText();
break;
case XmlPullParser.END_TAG:
if (tagname.equalsIgnoreCase("test")) {
stackSites.add(curStackSite);
} else if (tagname.equalsIgnoreCase(KEY_NAME)) {
curStackSite.setName(curText);
} else if (tagname.equals("Rate")) {
curStackSite.setLink(curText);
} else if (tagname.equalsIgnoreCase(KEY_ABOUT)) {
curStackSite.setAbout(curText);
} else if (tagname.equalsIgnoreCase(KEY_IMAGE_URL)) {
curStackSite.setImgUrl(curText);
}
break;
default:
break;
}
eventType = xpp.next();
}
} catch (Exception e) {
e.printStackTrace();
}
// return the populated list.
return stackSites;
}
}
And finally, HandleXml.java
public class HandleXML {
private String name;
private String rate;
private String date;
private String time;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLink() {
return rate;
}
public void setLink(String rate) {
this.rate = rate;
}
public String getAbout() {
return date;
}
public void setAbout(String date) {
this.date = date;
}
public String getImgUrl() {
return time;
}
public void setImgUrl(String time) {
this.time = time;
}
#Override
public String toString() {
return name + rate;
}
}
Xml File:
<?xml version="1.0" encoding="UTF-8"?>
<query xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:count="1" yahoo:created="2016-09-07T05:50:08Z" yahoo:lang="en-US">
<results>
<test>
<Name>EUR/USD</Name>
<Rate>1.1251</Rate>
<Date>9/7/2016</Date>
<Time>0:56am</Time>
</test>
<test>
<Name>EUR/USD</Name>
<Rate>1.1253</Rate>
<Date>9/7/2016</Date>
<Time>0:56am</Time>
</test>
</results>
</query>
The error is in the first fragment of code in: number.setText(par.getStackSitesFromFile(getActivity().getBaseContext()).get(0).getLink());
The arraylist returns empty because FileInputStream fis is set to open a file which contains path separator (/) , and it causes
java.lang.IllegalArgumentException: File /sdcard/rates.xml contains a path separator
. You have to use
FileInputStream fis = new FileInputStream (new File("/sdcard/rates.xml")); instead. Do not forget to close fis by fis.close();
Final code for XmlParser will be:
public class XmlParser {
static final String KEY_SITE = "rate";
static final String KEY_NAME = "Name";
static final String KEY_LINK = "Rate";
static final String KEY_ABOUT = "Date";
static final String KEY_IMAGE_URL = "Time";
FileInputStream fis;
public static List<HandleXML> getStackSitesFromFile() {
// List of StackSites that we will return
List<HandleXML> stackSites;
stackSites = new ArrayList<HandleXML>();
// temp holder for current StackSite while parsing
HandleXML curStackSite = null;
// temp holder for current text value while parsing
String curText = "";
try {
// Get our factory and PullParser
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xpp = factory.newPullParser();
// Open up InputStream and Reader of our file.
fis = new FileInputStream(new File("/sdcard/rates.xml"));
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
// point the parser to our file.
xpp.setInput(reader);
// get initial eventType
int eventType = xpp.getEventType();
// Loop through pull events until we reach END_DOCUMENT
while (eventType != XmlPullParser.END_DOCUMENT) {
// Get the current tag
String tagname = xpp.getName();
// React to different event types appropriately
switch (eventType) {
case XmlPullParser.START_TAG:
if (tagname.equals("test")) {
curStackSite = new HandleXML();
}
break;
case XmlPullParser.TEXT:
//grab the current text so we can use it in END_TAG event
curText = xpp.getText();
break;
case XmlPullParser.END_TAG:
if (tagname.equalsIgnoreCase("test")) {
stackSites.add(curStackSite);
} else if (tagname.equalsIgnoreCase(KEY_NAME)) {
curStackSite.setName(curText);
} else if (tagname.equals("Rate")) {
curStackSite.setLink(curText);
} else if (tagname.equalsIgnoreCase(KEY_ABOUT)) {
curStackSite.setAbout(curText);
} else if (tagname.equalsIgnoreCase(KEY_IMAGE_URL)) {
curStackSite.setImgUrl(curText);
}
break;
default:
break;
}
eventType = xpp.next();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
fis.close();
}catch(Exception e){
Log.i("Problem closing", "Closing fis");
}
// return the populated list.
return stackSites;
}
}
And then set number.setText() like that: number.setText(par.getStackSitesFromFile().get(0).getLink());
I have this XML
<CurrencyExchangeMap>
<CurrencyExchangePoint>
<Address>addr 3</Address>
<Latitude>41.6940265</Latitude>
<Longitude>44.7985044</Longitude>
</CurrencyExchangePoint>
<CurrencyExchangePoint>
<Address>addr 4</Address>
<Latitude>41.7024424</Latitude>
<Longitude>44.8058617</Longitude>
</CurrencyExchangePoint>
<CurrencyExchangePoint>
<Address>addr 5</Address>
<Latitude>41.6954418</Latitude>
<Longitude>44.7046725</Longitude>
</CurrencyExchangePoint>
</CurrencyExchangeMap>
It has 1000+ CurrencyExchangePoint But when I'm parsin them it returns ONLY 167 item. What's wrong? I've checked xml file in stylus studio and by myself and didn't find any error.
List<MapLT> mapLTs = null;
try {
XMLPullParserHandler parserHandler = new XMLPullParserHandler();
mapLTs = parserHandler.parse(getAssets().open("ltlg.xml"));
for (MapLT item : mapLTs) {
LatLng lt = new LatLng(item.getLatitude(), item.getLongitude());
String title = item.getAddress();
googleMap.addMarker(new MarkerOptions().position(lt).title(title));
}
} catch (Exception ex) {
ex.printStackTrace();
}
and my xmlpullparse class:
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
public class XMLPullParserHandler {
List<MapLT> mapLTList;
private MapLT mapLT;
private String text;
public XMLPullParserHandler() {
mapLTList = new ArrayList<MapLT>();
}
public List<MapLT> getMapLT(){
return mapLTList;
}
public List<MapLT> parse(InputStream is){
XmlPullParserFactory factory = null;
XmlPullParser parser = null;
try{
factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
parser = factory.newPullParser();
parser.setInput(is, null);
int eventType = parser.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
String tagname = parser.getName();
switch (eventType){
case XmlPullParser.START_TAG:
if(tagname.equalsIgnoreCase("CurrencyExchangePoint")){
mapLT = new MapLT();
}
break;
case XmlPullParser.TEXT:
text = parser.getText();
break;
case XmlPullParser.END_TAG:
if(tagname.equalsIgnoreCase("CurrencyExchangePoint")){
mapLTList.add(mapLT);
} else if(tagname.equalsIgnoreCase("Address")){
mapLT.setAddress(text);
} else if(tagname.equalsIgnoreCase("Latitude")){
mapLT.setLatitude(Float.parseFloat(text));
} else if(tagname.equalsIgnoreCase("Longitude")){
mapLT.setLongitude(Float.parseFloat(text));
}
break;
default:
break;
}
eventType = parser.next();
}
}catch (Exception ex){
ex.printStackTrace();
}
return mapLTList;
}
}
I can't spot a problem in your code, so my strategy would be to add logs.
Start by printing all the event tags and tag names you get.
Problem was that value of one tag from 6500 was empty..
And it took my 4 hour
I am building a java clone code detector in swing that implemented the ANTLR. This is the Screenshot :
https://www.dropbox.com/s/wnumgsjmpps33v5/SemogaYaAllah.png
if you see the screenshot, there are a main file that compared to another files. The way that I do is compared thats token main file to another file. The problem is, I am failed to get the ID Lexemes or tokens from my lexer class.
This is my ANTLR3JavaLexer
public class Antlr3JavaLexer extends Lexer {
public static final int PACKAGE=84;
public static final int EXPONENT=173;
public static final int STAR=49;
public static final int WHILE=103;
public static final int MOD=32;
public static final int MOD_ASSIGN=33;
public static final int CASE=58;
public static final int CHAR=60;
I ve created a JavaParser.class like this to use that lexer:
public final class JavaParser extends AParser { //Parser is my Abstract Class
JavaParser() {
}
#Override
protected boolean parseFile(JCCDFile f, final ASTManager treeContainer)throws ParseException, IOException {
BufferedReader in = new BufferedReader(new FileReader(f.getFile()));
String filePath = f.getNama(); // getName of file
final Antlr3JavaLexer lexer = new Antlr3JavaLexer();
lexer.preserveWhitespacesAndComments = false;
try {
lexer.setCharStream(new ANTLRReaderStream(in));
} catch (IOException e) {
e.printStackTrace();
return false;
}
//This is the problem
//When I am activated this code pieces, I get the output like this
https://www.dropbox.com/s/80uyva56mk1r5xy/Bismillah2.png
/*
StringBuilder sbu = new StringBuilder();
while (true) {
org.antlr.runtime.Token token = lexer.nextToken();
if (token.getType() == Antlr3JavaLexer.EOF) {
break;
}
sbu.append(token.getType());
System.out.println(token.getType() + ": :" + token.getText());
}*/
final CommonTokenStream tokens = new CommonTokenStream();
tokens.setTokenSource(lexer);
tokens.LT(10); // force load
// Create the parser
Antlr3JavaParser parser = new Antlr3JavaParser(tokens);
StringBuffer sb = new StringBuffer();
sb.append(tokens.toString());
DefaultTableModel model = (DefaultTableModel) Main_Menu.jTable2.getModel();
List<final_tugas_akhir.Report2> theListData = new ArrayList<Report2>();
final_tugas_akhir.Report2 theResult = new final_tugas_akhir.Report2();
theResult.setFile(filePath);
theResult.setId(sb.toString());
theResult.setNum(sbu.toString());
theListData.add(theResult);
for (Report2 report : theListData) {
System.out.println(report.getFile());
System.out.println(report.getId());
model.addRow(new Object[]{
report.getFile(),
report.getId(),
report.getNum(),
});
}
// in CompilationUnit
CommonTree tree;
try {
tree = (CommonTree) parser.compilationUnit().getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
} catch (RecognitionException e) {
e.printStackTrace();
return false;
}
walkThroughChildren(tree, treeContainer, parser.getTokenStream()); //this is my method to check the similiar tokens
in.close();
this.posisiFix(treeContainer); //fix position
return true;
}
Once again, this is the error code my java program link: https://www.dropbox.com/s/80uyva56mk1r5xy/Bismillah2.png.
The tokens always give me a null value.
I am trying to display a text from a news in any category of a newspaper. I use RSS of this newspaper. However when I run the code, sometimes I get the exception message in the above, sometimes it works correctly. Here is my RSS Parser code:
And the rss page that I use is:
RSSFeedParser parser = new RSSFeedParser("http://www.cumhuriyet.com.tr/rss/5");
Feed feed = parser.readFeed();
The RSS parser code:
package main;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.XMLEvent;
public class RSSFeedParser {
static final String TITLE = "title";
static final String DESCRIPTION = "description";
static final String CHANNEL = "channel";
static final String LANGUAGE = "language";
static final String COPYRIGHT = "copyright";
static final String LINK = "link";
static final String AUTHOR = "author";
static final String ITEM = "item";
static final String PUB_DATE = "pubDate";
static final String GUID = "guid";
static final String IMG = "img";
final URL url;
public RSSFeedParser(String feedUrl) {
try {
this.url = new URL(feedUrl);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
public Feed readFeed() {
Feed feed = null;
try {
boolean isFeedHeader = true;
// Set header values intial to the empty string
String description = "";
String title = "";
String link = "";
String language = "";
String copyright = "";
String author = "";
String pubDate = "";
String guid = "";
String img = "";
// First create a new XMLInputFactory
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
// Setup a new eventReader
InputStream in = read();
XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
// read the XML document
while (eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();
if (event.isStartElement()) {
String localPart = event.asStartElement().getName()
.getLocalPart();
switch (localPart) {
case ITEM:
if (isFeedHeader) {
isFeedHeader = false;
feed = new Feed(title, link, description, language,
copyright, pubDate);
}
event = eventReader.nextEvent();
break;
case TITLE:
title = getCharacterData(event, eventReader);
break;
case DESCRIPTION:
description = getCharacterData(event, eventReader);
break;
case LINK:
link = getCharacterData(event, eventReader);
break;
case GUID:
guid = getCharacterData(event, eventReader);
break;
case LANGUAGE:
language = getCharacterData(event, eventReader);
break;
case AUTHOR:
author = getCharacterData(event, eventReader);
break;
case PUB_DATE:
pubDate = getCharacterData(event, eventReader);
break;
case COPYRIGHT:
copyright = getCharacterData(event, eventReader);
break;
}
} else if (event.isEndElement()) {
if (event.asEndElement().getName().getLocalPart() == (ITEM)) {
FeedMessage message = new FeedMessage();
message.setDescription(description);
message.setPubDate(pubDate);
message.setLink(link);
message.setTitle(title);
message.setImg(img);
feed.getMessages().add(message);
event = eventReader.nextEvent();
continue;
}
}
}
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
return feed;
}
private String getCharacterData(XMLEvent event, XMLEventReader eventReader)
throws XMLStreamException {
String result = "";
event = eventReader.nextEvent();
if (event instanceof Characters) {
result = event.asCharacters().getData();
}
return result;
}
private InputStream read() {
try {
return url.openStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Exception message is:
Exception in thread "main" java.lang.RuntimeException: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[5,3]
Message: The element type "meta" must be terminated by the matching end-tag "</meta>".
at main.RSSFeedParser.readFeed(RSSFeedParser.java:112)
at cumhuriyet.Dunya.cumDunya(Dunya.java:32)
at automation.ServerInteraction.main(ServerInteraction.java:83)
Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[5,3]
Message: The element type "meta" must be terminated by the matching end-tag "</meta>".
at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(Unknown Source)
at com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(Unknown Source)
at main.RSSFeedParser.readFeed(RSSFeedParser.java:58)
... 2 more
That looks like it is a live document; i.e. one that changes fairly frequently. There is also no sign of a tag in it.
I can think of two explanations for what is happening:
Sometimes the document is being generated or created incorrectly.
Sometimes you are getting an HTML error page instead of the document
you are expecting, and the XML parser can't cope with a tag in
the HTML's .
To track this down, you are going to have to capture the precise input that is causing the parse to fail.
I ran into this bug when I was trying to implement a simple xml parser derived from Android's "Parsing XML Data" training page. As I am a new Android developer--and an extremely amateur coder--the exception that is thrown when I try to implement my own modified version does not help in directing me towards the problem.
Here is the exact XmlPullParserException that is thrown:
04-06 19:10:42.772 19279-19279/com.example.reader.app E/Main-Activity﹕ expected: START_DOCUMENT {null}articles (position:START_TAG <articles>#2:11 in java.io.InputStreamReader#41ec5dd8)
Here is my test xml file:
<?xml version="1.0" encoding="utf-8"?>
<articles>
<article>
<title>Test Article Number 1</title>
<description>This is a short description of the article.</description>
<text>This is some text.</text>
</article>
<article>
<title>Test Article Number 2</title>
<description>This is a short description of the article.</description>
<text>This is some text.</text>
</article>
</articles>
Here is the onCreate method of my MainActivity.java file that opens the inputStream and instantiates my ArticleListParser class.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
// try to access the data in the xml file
Log.d(TAG, "Starting to execute your code...");
try {
InputStream minputStream = getResources().openRawResource(R.raw.test);
ArticleListParser marticleParser = new ArticleListParser();
List mlistOfArticles = marticleParser.parse(minputStream);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
And here is my ArticleListParser.java class. The instance of this class instantiated by the MainActivity does not make it past the parse() method (i.e., does not execute any other methods which would be triggered by the return readArticles(parser); line in parse())...
package com.example.reader.app;
import android.util.Log;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jasondblack on 4/5/14.
*/
public class ArticleListParser {
// We don't use namespaces
private static final String ns = null;
// log tag
private static final String TAG = "ArticleListParser";
public List parse(InputStream in) throws XmlPullParserException, IOException {
try {
// get a new xml pull parser
XmlPullParser parser = Xml.newPullParser();
// indicate that this xml does not have namespaces
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
// set the input stream of the pull parser
parser.setInput(in, null);
// go to the first element
parser.nextTag();
// start reading the xml
return readArticles(parser);
} finally {
// no matter what, close the input stream
in.close();
}
}
private List readArticles(XmlPullParser parser) throws XmlPullParserException, IOException {
// create List that will be returned
List articles = new ArrayList();
parser.require(XmlPullParser.START_DOCUMENT, ns, "articles");
while(parser.next() != XmlPullParser.END_TAG) {
if(parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String thisName = parser.getName();
if(thisName.equals("article")) {
articles.add(readArticle(parser));
}
else {
skip(parser);
}
}
return articles;
}
public static class Article {
public final String title;
public final String description;
public final String text;
private Article (String thisTitle, String thisDescription, String thisText) {
this.title = thisTitle;
this.description = thisDescription;
this.text = thisText;
}
}
private Article readArticle(XmlPullParser parser) throws XmlPullParserException, IOException {
// make sure the xml parser is at the beginning of a tag
parser.require(XmlPullParser.START_TAG, ns, "article");
String title = null;
String description = null;
String text = null;
// step through xml file until you reach the end tag
while(parser.getEventType() != XmlPullParser.END_TAG) {
// if it is the start tag, continue onto next element in parser
// ??? weird because we have already required a start tag in the first line of this method
if(parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
// get the name of the element in the angled brackets
String name = parser.getName();
// check to see if it is one of the titles we want ... if so extract the contents
if(name.equals("title")) {
title = readTitle(parser);
} else if (name.equals("description")) {
description = readDescription(parser);
} else if (name.equals("text")) {
text = readText(parser);
} else {
skip(parser);
}
}
// return an Article object
return new Article (title, description, text);
}
// TODO: stopped here don't be confused by duplicate methods implement your own readTitle(), readDescription(), readText(), and extractText() [their "readTExt()" method]
// Processes title tags in the feed
private String readTitle(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "title");
String thisTitle = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "title");
return thisTitle;
}
// Processes description tags in the feed.
private String readDescription(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "description");
String thisDescription = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "description");
return thisDescription;
}
// For the tags title and summary, extracts their text values.
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
String result = "";
// TODO: possible that this will snag on my xml because I don't have type="text" in my xml elements
if (parser.next() == XmlPullParser.TEXT) {
result = parser.getText();
parser.nextTag();
}
return result;
}
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
}
If you add the following before your line parser.require() call in readArticles(), you can see that you're not actually at the START_DOCUMENT event at that point.
int eventType = parser.getEventType();
Log.i("TAG", "The event type is: " + eventType);
while (eventType != XmlPullParser.START_DOCUMENT) {
eventType = parser.next();
Log.i("TAG", "The event type is: " + eventType);
}
After commenting out the parser.nextTag(); line in parse(), this logging shows that you're now at START_DOCUMENT. But then the require() call fails with the exception mentioned in your question. It appears that using ns, which is null, for the namespace argument isn't valid. Setting both the namespace and name arguments to null does allow the require() to succeed, but may not be what you want.