3

I want to make a progress bar while importing my articles from an XML feed.

The parsing works fine, but for my progress bar I need to quickly know the total # of <item>s in the feed so I can determine percentage that have been loaded.

My thought was, it would be a lot faster to just do this in PHP and add the "count" to the feed itself - something like this:

<?xml version="1.0" encoding="utf-8"?>
<channel>
<title>My Apps Feed</title>
<link>http://link_to_this_fiel</link>
<language>en-us</language>
<count>42</count>

But then I need to be able to quickly access that "count" number.

At the moment, I have an RSSHandler.java that's being called like this:

//Add all items from the parsed XML
for(NewsItem item : parser.getParsedItems())
{
    //...

Note: Min API level 8 for my app

Dave
  • 28,833
  • 23
  • 113
  • 183

2 Answers2

0

You can use Xpath to get specific node value in XML. Sample would be:

SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(.....); // get document for your xml here
Element elem = (Element) XPath.selectSingleNode(doc, "channel/count");
System.out.println(elem.getValue());

This way you can directly get count value. But I'm not sure this is the efficient and faster way to do this. As an option you can use this. Also spend some time in reading this: SAX parsing - efficient way to get text nodes

Community
  • 1
  • 1
Harry Joy
  • 58,650
  • 30
  • 162
  • 207
  • I should have mentioned in my question, but my minSdk level (or whatever that's called) is 8. Appears XPath requires 17. – Dave Jan 29 '13 at 15:50
0

SAX reads the tags in the order they come in. Make sure to put your tag at the beginning of the XML, otherwise you will need to parse it all anyways. For easier parsing, I'd put it into an attribute of a self-closing tag with a unique name. Then you wait until the SAX parser calls your startElement method, check if the tag name matches the name of your count tag, extract the attribute, and display it to the user.

If you want to stop the parser after displaying the count, you can throw a SAXException to do so.

I assume you already know how to do the parsing work off the main thread, as you mention a progress bar and imply that parsing can take some time (and doing long tasks on the main thread gives you ANRs). In case someone stumbles upon this question who doesn't know: You can use AsyncTask and the publishProgress (called in the "worker" thread by your code) and onProgressUpdate (called by Android on the UI thread once you call publishProgress) methods to take care of that.

Jan Schejbal
  • 4,000
  • 19
  • 40
  • So you're suggesting I run the import, then throw an exception to retrieve the count, then run the import again? – Dave Jan 28 '13 at 16:40
  • If you already use SAX in an AsyncTask for parsing and want to import the file anyways, just add a special case for the count tag to your startElement method. This special case should set a "total items" variable and otherwise ignore the tag. Then whenever you finished parsing an item, you check if that var is set, and use publishProgress to update the bar. You only need to throw the exception if you don't want to parse, or it is too hard to implement something like this due to some other constraints. – Jan Schejbal Jan 28 '13 at 21:46