I'm trying to parse xml using SaxParser which is some times failing to parse url's that is coming in xml feed. I've xml feed some thing like this.
<songs>
<song id="269611">
<start>2015-01-02T04:36:52Z</start>
<title>Beyond Me</title>
<artist>tobyMac</artist>
<logo>http://www.quuit.com/quu/content/themes/base/images/music_none.png</logo>
<lyrics>no</lyrics>
<bio>yes</bio>
<coupon>no</coupon>
<ad>no</ad>
</song>
<song id="77476">
<start>2015-01-2T04:32:51Z</start>
<title>WHOLLY YOURS</title>
<artist>David Crowder Band</artist>
<logo>http://www.quuit.com/imageserver/thumbnail/WHOLLY_YOURSDavid_Crowder_Band.jpeg</logo>
<lyrics>no</lyrics>
<bio>yes</bio>
<coupon>no</coupon>
<ad>no</ad>
</song>
</songs>
When i try to parse the above, some times the url in the logo tag is getting truncated. Instead of http://www.quuit.com/imageserver/thumbnail/WHOLLY_YOURSDavid_Crowder_Band.jpeg this url, i'm just getting Band.jpeg or wder_Band.jpeg etc and some times it gives complete url which is fine. This issue is happening randomly and looks weird. Somebody pls help me on this.
here is the code that i've wrote to parse the above xml:
public class QuuAsyncTask extends AsyncTask<Object, Void, BaseQuuVO> {
private Exception exception;
private QuuServiceDelegate serviceDelegate;
protected BaseQuuVO doInBackground(Object... param) {
BaseQuuVO baseVO = new BaseQuuVO();
try {
QuuDefaultHandler defaultHandler = (QuuDefaultHandler) param[1];
serviceDelegate = (QuuServiceDelegate) param[2];
/** Handling XML */
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
/** Send URL to parse XML Tags */
URL sourceUrl = new URL((String) param[0]);
/** Create handler to handle XML Tags ( extends DefaultHandler ) */
xr.setContentHandler(defaultHandler);
InputSource inputSource = new InputSource(sourceUrl.openStream());
inputSource.setEncoding("ISO-8859-1");
xr.parse(inputSource);
baseVO = (BaseQuuVO) defaultHandler.getData();
return baseVO;
} catch (Exception e) {
this.exception = e;
return null;
}
}
protected void onPostExecute(BaseQuuVO result) {
super.onPostExecute(result);
// TODO: check this.exception
// TODO: do something with the feed
if (result != null) {
serviceDelegate.quuResponseReceived(result);
} else {
serviceDelegate.quuResponseFailure("Problem loading data");
}
}
public class QuuAsyncTask extends AsyncTask<Object, Void, BaseQuuVO> {
private Exception exception;
private QuuServiceDelegate serviceDelegate;
protected BaseQuuVO doInBackground(Object... param) {
BaseQuuVO baseVO = new BaseQuuVO();
try {
QuuDefaultHandler defaultHandler = (QuuDefaultHandler) param[1];
serviceDelegate = (QuuServiceDelegate) param[2];
/** Handling XML */
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
/** Send URL to parse XML Tags */
URL sourceUrl = new URL((String) param[0]);
/** Create handler to handle XML Tags ( extends DefaultHandler ) */
xr.setContentHandler(defaultHandler);
InputSource inputSource = new InputSource(sourceUrl.openStream());
inputSource.setEncoding("ISO-8859-1");
xr.parse(inputSource);
baseVO = (BaseQuuVO) defaultHandler.getData();
return baseVO;
} catch (Exception e) {
this.exception = e;
return null;
}
}
protected void onPostExecute(BaseQuuVO result) {
super.onPostExecute(result);
// TODO: check this.exception
// TODO: do something with the feed
if (result != null) {
serviceDelegate.quuResponseReceived(result);
} else {
serviceDelegate.quuResponseFailure("Problem loading data");
}
}
}
public class PlayListXMLParser extends QuuDefaultHandler {
private List<PlayListSongVO> songsVO;
private String tempVal;
private PlayListSongVO tempPlayListSongVO;
private PlayListsVO playListsVO = new PlayListsVO();
public PlayListXMLParser() {
songsVO = new ArrayList<PlayListSongVO>();
}
@Override
public PlayListsVO getData() {
playListsVO.setSongs(songsVO);
return playListsVO;
}
// Event Handlers
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// reset
tempVal = "";
if (qName.equalsIgnoreCase("song")) {
// create a new instance of employee
tempPlayListSongVO = new PlayListSongVO();
}
}
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("song")) {
// add it to the list
songsVO.add(tempPlayListSongVO);
} else if (qName.equalsIgnoreCase("id")) {
tempPlayListSongVO.setId(tempVal);
} else if (qName.equalsIgnoreCase("start")) {
tempPlayListSongVO.setStart(tempVal);
} else if (qName.equalsIgnoreCase("title")) {
tempPlayListSongVO.setTitle(tempVal);
} else if (qName.equalsIgnoreCase("artist")) {
tempPlayListSongVO.setArtist(tempVal);
} else if (qName.equalsIgnoreCase("logo")) {
tempPlayListSongVO.setLogo(tempVal);
} else if (qName.equalsIgnoreCase("lyrics")) {
tempPlayListSongVO.setLyrics(tempVal);
} else if (qName.equalsIgnoreCase("bio")) {
tempPlayListSongVO.setBio(tempVal);
} else if (qName.equalsIgnoreCase("coupon")) {
tempPlayListSongVO.setCoupon(tempVal);
} else if (qName.equalsIgnoreCase("ad")) {
tempPlayListSongVO.setAd(tempVal);
}
}
}
Update :
public class SongDetailXMLParser extends QuuDefaultHandler {
// private String tempVal;
private SongDetailsVO songDetailsVO;
private StringBuilder tempStringBuilder;
public SongDetailXMLParser() {
}
@Override
public SongDetailsVO getData() {
return songDetailsVO;
}
// Event Handlers
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
tempStringBuilder = new StringBuilder();
if (qName.equalsIgnoreCase("song")) {
// create a new instance
songDetailsVO = new SongDetailsVO();
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
tempStringBuilder.append(ch);
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase("song")) {
// add it to the list
} else if (qName.equalsIgnoreCase("id")) {
songDetailsVO.setId(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("duration")) {
songDetailsVO.setDuration(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("title")) {
songDetailsVO.setTitle(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("artist")) {
songDetailsVO.setArtist(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("logo")) {
songDetailsVO.setLogo(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("amazon")) {
songDetailsVO.setAmazon(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("itunes")) {
songDetailsVO.setItunes(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("videolink")) {
songDetailsVO.setVideolink(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("ringtone")) {
songDetailsVO.setRingtone(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("lyrics")) {
songDetailsVO.setLyrics(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("bio")) {
songDetailsVO.setBio(tempStringBuilder.toString());
} else if (qName.equalsIgnoreCase("share")) {
songDetailsVO.setShare(tempStringBuilder.toString());
}
}
}
Let's take a look on documentation :
void characters(char[] ch, int start, int length) throws SAXException
The Parser will call this method to report each chunk of character data. SAX parsers may return all contiguous character data in a single chunk, or they may split it into several chunks
The application must not attempt to read from the array outside of the specified range.
So the above code is very wrong :
public void characters(char[] ch, int start, int length)
throws SAXException {
tempStringBuilder.append(ch);
}
So is this one as you recreate the String
for every chunk :
public void characters(char[] ch, int start, int length)
throws SAXException {
tempVal = new String(ch, start, length);
}
Try this :
public void characters(char[] ch, int start, int length)
throws SAXException {
tempStringBuilder.append(ch, start, length);
}