In my xml, i have <ns5:Name>mil & carbon</ns5:Name>
From my java code i am retrieving that value by
public class MasterdataParser extends MasterdataBaseParser {
protected MasterdataParser(InputStream response) {
super(response);
}
public MasterData parse() {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
MasterData masterData;
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(this.getInputStream());
Element root = dom.getDocumentElement();
masterData = new MasterData();
NodeList list;
Element element;
NodeList childNodeList;
Node node;
String nodeName;
list = root.getElementsByTagName(PREFIX+CATEGORY);
for (int i=0;i<list.getLength();i++){
element = (Element) list.item(i);
childNodeList = element.getChildNodes();
Category category = new Category();
for (int j = 0; j < childNodeList.getLength(); j++) {
node = childNodeList.item(j);
nodeName = node.getNodeName();
if (nodeName.equalsIgnoreCase(PREFIX+CATEGORY_ID)) {
try{
category.setId(node.getFirstChild().getNodeValue());
} catch (NullPointerException ex) {
category.setId(null);
}
}
if (nodeName.equalsIgnoreCase(PREFIX+CATEGORY_NAME)) {
try{
// System.out.println("Masterdataparser category name html "+Html.fromHtml(node.getFirstChild().getNodeValue())); // Not worked
System.out.println("URL Decoder "+URLDecoder.decode(node.getFirstChild().getNodeValue(), "UTF-8")); // Not worked
category.setName(node.getFirstChild().getNodeValue());
} catch (NullPointerException ex) {
category.setName(null);
}
}
}
public abstract class MasterdataBaseParser implements MasterdataParserInterface {
static final String CATEGORY = "Category";
static final String CATEGORY_ID = "Id";
static final String CATEGORY_NAME = "Name";
final InputStream response;
protected MasterdataBaseParser(InputStream response){
this.response = response;
}
protected InputStream getInputStream() {
return response;
}
}
But it displays only "mil" and it is not taking "&" as "&". But i want to display "mil & carbon". How to do this one? Advance thanks for any help
Here is an example of how i do things with one class parser and several xml stream :
public class RSSHandler extends DefaultHandler {
int RSS_ID;
ContentValues parsedValues = new ContentValues();
private String parsedString = null;
protected DataController _dataController;
private StringBuffer parsedBuffer = new StringBuffer();
public void setRssId(int rssId) {
RSS_ID = rssId;
}
public void setDataController(DataController dataController) {
_dataController = (DataController) dataController;
}
#Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
}
#Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
parsedString = parsedString.trim();
switch (RSS_ID) {
case (0):
if (localName.equals("Application")) {
_dataController.insertRowInTable(RSS_ID, parsedValues);
}
else {
parsedValues.put(localName, parsedString);
}
break;
case (1):
if (localName.equals("tab")) {
_dataController.insertRowInTable(RSS_ID, parsedValues);
}
else {
parsedValues.put(localName, parsedString);
}
break;
case (2):
if (localName.equals("category")) {
_dataController.insertRowInTable(RSS_ID, parsedValues);
}
else {
parsedValues.put(localName, parsedString);
}
break;
case (3):
if (localName.equals("item")) {
_dataController.insertRowInTable(RSS_ID, parsedValues);
}
else {
parsedValues.put(localName, parsedString);
}
break;
case (4):
if (localName.equals("event")) {
_dataController.insertRowInTable(RSS_ID, parsedValues);
}
else {
parsedValues.put(localName, parsedString);
}
break;
case (5):
if (localName.equals("album")) {
_dataController.insertRowInTable(RSS_ID, parsedValues);
}
else {
parsedValues.put(localName, parsedString);
}
break;
case (6):
if (localName.equals("picture")) {
_dataController.insertRowInTable(RSS_ID, parsedValues);
}
else {
parsedValues.put(localName, parsedString);
}
break;
case (7):
if (localName.equals("location")) {
_dataController.insertRowInTable(RSS_ID, parsedValues);
}
else {
parsedValues.put(localName, parsedString);
}
break;
default:
break;
}
parsedString = "";
parsedBuffer = new StringBuffer();
}
#Override
public void characters(char ch[], int start, int length) {
parsedBuffer.append(ch, start, start + length);
parsedString = parsedBuffer.toString();
}
}
DataController is just a global class to acces methods and attributes.
public void insertRowInTable(int tableId, ContentValues myRow) {
String myTable = _tableNameList.get(tableId);
_dataBaseHelper.createRowInTable(myTable, myRow);
}
public void createRowInTable(String tableName, ContentValues values) {
try {
myDataBase.insert(tableName, null, values);
}
catch (Exception e) {
//catch
}
}
While parsing xml, by default "&" is behaving as "Escape sequence"(In android lower version like 2.2) that's why i can't able to parse that "mil & carbon". So before parsing, i replaced "&" with "ampersand"(In words) under the file and after fetching that node as "mil ampersand carbon" then replacing the "ampersand" with "&"(symbol). And lots of thanks to "Yume" sir
Related
I created an app that is going to download an xml file,then parse it, and adapt it to a list view, but I faced a problem in parsing xml, first thing first:
MainActivity.java
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downloadData downloadData = new downloadData();
downloadData.execute("http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topfreeapplications/limit=10/xml");
}
private class downloadData extends AsyncTask<String, Void, String> {
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
ParseApplications parseApplications = new ParseApplications();
parseApplications.parse(s);
}
#Override
protected String doInBackground(String... params) {
String rssFeed = downloadXML(params[0]);
if (rssFeed == null) {
}
return rssFeed;
}
private String downloadXML(String urlPath) {
StringBuilder xmlResult = new StringBuilder();
try {
URL url = new URL(urlPath);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
int charsRead;
char[] inputBuffer = new char[500];
while (true) {
charsRead = reader.read(inputBuffer);
if (charsRead < 0) {
break;
}
if (charsRead > 0) {
xmlResult.append(String.copyValueOf(inputBuffer), 0, charsRead);
}
}
reader.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return xmlResult.toString();
}
}
}
MainActivity.class work well in term of downloading XML, but when it comes to parsing xml, although it parses it,but return no value:
ParseApplications.java
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.StringReader;
import java.util.ArrayList;
public class ParseApplications {
private ArrayList<FeedEntry> applications;
public ParseApplications() {
this.applications = new ArrayList<>();
}
public ArrayList<FeedEntry> getApplications() {
return applications;
}
public boolean parse(String xmlData) {
boolean status = true;
FeedEntry currentRecord = null;
boolean inEntry = false;
String textValue = "";
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader(xmlData));
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
String tagName = xpp.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
if ("entry".equalsIgnoreCase(tagName)) {
inEntry = true;
currentRecord = new FeedEntry();
}
break;
case XmlPullParser.TEXT:
textValue = xpp.getText();
break;
case XmlPullParser.END_TAG:
if (inEntry) {
if ("entry".equalsIgnoreCase(tagName)) {
applications.add(currentRecord);
inEntry = false;
} else if ("name".equalsIgnoreCase(tagName)) {
currentRecord.setName(textValue);
} else if ("artist".equalsIgnoreCase(tagName)) {
currentRecord.setArtist(textValue);
} else if ("releaseDate".equalsIgnoreCase(tagName)) {
currentRecord.setReleaseDate(textValue);
} else if ("image".equalsIgnoreCase(tagName)) {
currentRecord.setImageURL(textValue);
} else if ("summary".equalsIgnoreCase(tagName)) {
currentRecord.setSummary(textValue);
}
}
break;
default:
//Nothing to do
eventType = xpp.next();
}
}
} catch (Exception e) {
status = false;
e.printStackTrace();
}
return status;
}
}
here is the other class:
FeedEntry.java
public class FeedEntry {
private String name;
private String artist;
private String releaseDate;
private String summary;
private String imageURL;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(String releaseDate) {
this.releaseDate = releaseDate;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getImageURL() {
return imageURL;
}
public void setImageURL(String imageURL) {
this.imageURL = imageURL;
}
#Override
public String toString() {
return "name='" + name + '\n' +
", artist='" + artist + '\n' +
", releaseDate='" + releaseDate + '\n' +
", imageURL='" + imageURL;
}
}
I think I am a quiet bit late but still, it can help other also. So I am posting my answer. Please check the parse method once you are stuck at first tag only.It should be like this
public boolean parse(String xmlData) {
boolean status = true;
FeedEntry currentRecord = null;
boolean inEntry = false;
String textValue = "";
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader(xmlData));
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
String tagName = xpp.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
if (tagName.equalsIgnoreCase("entry")) {
inEntry = true;
currentRecord = new FeedEntry();
}
break;
case XmlPullParser.TEXT:
textValue = xpp.getText();
break;
case XmlPullParser.END_TAG:
if (inEntry) {
if (tagName.equalsIgnoreCase("entry")) {
applications.add(currentRecord);
inEntry = false;
} else if (tagName.equalsIgnoreCase("name")) {
currentRecord.setName(textValue);
} else if (tagName.equalsIgnoreCase("artist")) {
currentRecord.setArtist(textValue);
} else if (tagName.equalsIgnoreCase("releaseDate")) {
currentRecord.setReleaseDate(textValue);
} else if (tagName.equalsIgnoreCase("image")) {
currentRecord.setImageURL(textValue);
} else if (tagName.equalsIgnoreCase("summary")) {
currentRecord.setSummary(textValue);
}
}
break;
default:
//Nothing to do
break;
}
eventType = xpp.next(); // this should come after switch case
}
} catch (
Exception e
)
{
status = false;
e.printStackTrace();
}
return status;
}
In the XmlPullParser.END_TAG: case:
Try to remove "inEntry = false;"
I'm trying to make an ANDROID app that reads RSS feeds so I used this tutorial ( http://android-er.blogspot.com/2010/05/simple-rss-reader-ii-implement-with.html ) and implemented it to my own url rss feeder. But the description tag isn't being shown..mostly cz in the xml of the feeder the description tags are CDATA. how can i parse the description cdata in my rss??Thanks!
here is my RSSHandler code :
import org.xml.sax.Attributes;
import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler;
public class RSSHandler extends DefaultHandler {
final int state_unknown = 0;
final int state_title = 1;
final int state_description = 2;
final int state_link = 3;
final int state_pubdate = 4;
int currentState = state_unknown;
RSSFeed feed;
RSSItem item;
boolean itemFound = false;
RSSHandler(){
}
RSSFeed getFeed(){
return feed;
}
#Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
feed = new RSSFeed();
item = new RSSItem();
}
#Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
if (localName.equalsIgnoreCase("item")){
itemFound = true;
item = new RSSItem();
currentState = state_unknown;
}
else if (localName.equalsIgnoreCase("title")){
currentState = state_title;
}
else if (localName.equalsIgnoreCase("description")){
currentState = state_description;
}
else if (localName.equalsIgnoreCase("link")){
currentState = state_link;
}
else if (localName.equalsIgnoreCase("pubdate")){
currentState = state_pubdate;
}
else{
currentState = state_unknown;
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
if (localName.equalsIgnoreCase("item")){
feed.addItem(item);
}
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
String strCharacters = new String(ch,start,length);
if (itemFound==true){
// "item" tag found, it's item's parameter
switch(currentState){
case state_title:
item.setTitle(strCharacters);
break;
case state_description:
item.setDescription(strCharacters);
break;
case state_link:
item.setLink(strCharacters);
break;
case state_pubdate:
item.setPubdate(strCharacters);
break;
default:
break;
}
}
else{
// not "item" tag found, it's feed's parameter
switch(currentState){
case state_title:
feed.setTitle(strCharacters);
break;
case state_description:
feed.setDescription(strCharacters);
break;
case state_link:
feed.setLink(strCharacters);
break;
case state_pubdate:
feed.setPubdate(strCharacters);
break;
default:
break;
}
}
currentState = state_unknown;
}
and here is my RSSReader code :
public class AndroidRssReader extends ListActivity {
private RSSFeed myRssFeed = null;
//private ArrayList<RSSItem> myRssFeed = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
//URL rssUrl = new URL("http://www.gov.hk/en/about/rss/govhkrss.data.xml");
URL rssUrl = new URL("http://www.merehbi.com/online/index.php?option=com_content&view=category&layout=blog&id=58&Itemid=155&lang=ar&format=feed&type=rss");
SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
XMLReader myXMLReader = mySAXParser.getXMLReader();
RSSHandler myRSSHandler = new RSSHandler();
myXMLReader.setContentHandler(myRSSHandler);
InputSource myInputSource = new InputSource(rssUrl.openStream());
myXMLReader.parse(myInputSource);
myRssFeed = myRSSHandler.getFeed();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (myRssFeed!=null)
{
TextView feedTitle = (TextView)findViewById(R.id.feedtitle);
TextView feedDescribtion = (TextView)findViewById(R.id.feeddescribtion);
TextView feedPubdate = (TextView)findViewById(R.id.feedpubdate);
TextView feedLink = (TextView)findViewById(R.id.feedlink);
feedTitle.setText(myRssFeed.getTitle());
feedDescribtion.setText(myRssFeed.getDescription());
feedPubdate.setText(myRssFeed.getPubdate());
feedLink.setText(myRssFeed.getLink());
ArrayAdapter<RSSItem> adapter =
new ArrayAdapter<RSSItem>(this,
android.R.layout.simple_list_item_1,myRssFeed.getList());
setListAdapter(adapter);
}
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this,ShowDetails.class);
Bundle bundle = new Bundle();
bundle.putString("keyTitle", myRssFeed.getItem(position).getTitle());
bundle.putString("keyDescription", myRssFeed.getItem(position).getDescription());
bundle.putString("keyLink", myRssFeed.getItem(position).getLink());
bundle.putString("keyPubdate", myRssFeed.getItem(position).getPubdate());
intent.putExtras(bundle);
startActivity(intent);
}
}
i use this tutorial and its codes
http://www.androidhive.info/2011/11/android-xml-parsing-tutorial/
and change some code by this answer
https://stackoverflow.com/a/8489223/3636653
public static void main(String[] args) throws Exception {
File file = new File("data.xml");
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(file);
NodeList nodes = doc.getElementsByTagName("topic");
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
NodeList title = element.getElementsByTagName("title");
Element line = (Element) title.item(0);
System.out.println("Title: " + getCharacterDataFromElement(line));
}
}
public static String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "";
}
I parse some RSS feed (tried with different ones...) and everytime pretty randomly characters get cut of.
What am I doing wrong? Why does it work in some instances and in other ones it doesn't?
Is there another way of doing it? The XML will (in most of the cases) include UTF-8 characters (like ä,ö,ü etc.) so the solution should work with those characters too.
If you need any more information (More code, more detailed information etc.) please let me know!
Here is my Code:
public class RSSHandler extends DefaultHandler {
final int state_unknown = 0;
final int state_title = 1;
final int state_description = 2;
final int state_link = 3;
final int state_pubdate = 4;
int currentState = state_unknown;
StringBuilder strCharacters;
RSSFeed feed;
RSSItem item;
boolean inEntity = false;
String entityName = "";
boolean itemFound = false;
public RSSHandler() {
strCharacters = new StringBuilder();
}
public RSSFeed getFeed() {
return feed;
}
#Override
public void startDocument() throws SAXException {
feed = new RSSFeed();
item = new RSSItem();
}
#Override
public void endDocument() throws SAXException {
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
strCharacters = new StringBuilder();
if (localName.equalsIgnoreCase("item")) {
itemFound = true;
item = new RSSItem();
currentState = state_unknown;
} else if (localName.equalsIgnoreCase("title")) {
currentState = state_title;
} else if (localName.equalsIgnoreCase("description")) {
currentState = state_description;
} else if (localName.equalsIgnoreCase("link")) {
currentState = state_link;
} else if (localName.equalsIgnoreCase("pubdate")) {
currentState = state_pubdate;
} else {
currentState = state_unknown;
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (itemFound == true) {
switch (currentState) {
case state_title:
item.setTitle(strCharacters.toString());
break;
case state_description:
break;
case state_link:
item.setLink(strCharacters.toString());
break;
case state_pubdate:
String dateStr = strCharacters.toString();
SimpleDateFormat curFormater = new SimpleDateFormat(
"EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
Date dateObj = null;
try {
dateObj = curFormater.parse(dateStr);
SimpleDateFormat postFormater = new SimpleDateFormat(
"dd.MM.yyyy HH:mm");
String newDateStr = postFormater.format(dateObj);
item.setPubdate(newDateStr);
} catch (ParseException e) {
e.printStackTrace();
}
break;
default:
break;
}
} else {
switch (currentState) {
case state_title:
feed.setTitle(strCharacters.toString());
break;
case state_description:
break;
case state_link:
feed.setLink(strCharacters.toString());
break;
case state_pubdate:
feed.setPubdate(strCharacters.toString());
break;
default:
break;
}
}
currentState = state_unknown;
if (localName.equalsIgnoreCase("item")) {
feed.addItem(item);
}
}
public void startEntity(String name) throws SAXException {
inEntity = true;
entityName = name;
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
strCharacters = new StringBuilder();
if (inEntity) {
inEntity = false;
strCharacters.append("&" + entityName + ";");
} else {
for (int i = start; i < start + length; i++) {
strCharacters.append(ch[i]);
}
}
// strCharacters.append(ch, start, length);
}
}
You are creating a new StringBuilder on each characters() call. This is incorrect. There many be several calls to characters() per element -- you need to concatenate all those results, not just collect the last piece.
Ok I got the code for a feed parser from the ibm website. It works perfectly on the emulator,however on the phone it just stops at one point.
The code is:
package org.developerworks.android;
import java.util.List;
public interface FeedParser {
List<Message> parse();
}
public abstract class BaseFeedParser implements FeedParser {
// names of the XML tags
static final String PUB_DATE = "pubDate";
static final String DESCRIPTION = "description";
static final String LINK = "link";
static final String TITLE = "title";
static final String ITEM = "item";
final URL feedUrl;
protected BaseFeedParser(String feedUrl){
try {
this.feedUrl = new URL(feedUrl);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
protected InputStream getInputStream() {
try {
return feedUrl.openConnection().getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public class SaxFeedParser extends BaseFeedParser {
protected SaxFeedParser(String feedUrl){
super(feedUrl);
}
public List<Message> parse() {
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
RssHandler handler = new RssHandler();
parser.parse(this.getInputStream(), handler);
return handler.getMessages();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
import static org.developerworks.android.BaseFeedParser.*;
public class RssHandler extends DefaultHandler{
private List<Message> messages;
private Message currentMessage;
private StringBuilder builder;
public List<Message> getMessages(){
return this.messages;
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
super.characters(ch, start, length);
builder.append(ch, start, length);
}
#Override
public void endElement(String uri, String localName, String name)
throws SAXException {
super.endElement(uri, localName, name);
if (this.currentMessage != null){
if (localName.equalsIgnoreCase(TITLE)){
currentMessage.setTitle(builder.toString());
} else if (localName.equalsIgnoreCase(LINK)){
currentMessage.setLink(builder.toString());
} else if (localName.equalsIgnoreCase(DESCRIPTION)){
currentMessage.setDescription(builder.toString());
} else if (localName.equalsIgnoreCase(PUB_DATE)){
currentMessage.setDate(builder.toString());
} else if (localName.equalsIgnoreCase(ITEM)){
messages.add(currentMessage);
}
builder.setLength(0);
}
}
#Override
public void startDocument() throws SAXException {
super.startDocument();
messages = new ArrayList<Message>();
builder = new StringBuilder();
}
#Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, name, attributes);
if (localName.equalsIgnoreCase(ITEM)){
this.currentMessage = new Message();
}
}
}
public class AndroidSaxFeedParser extends BaseFeedParser {
public AndroidSaxFeedParser(String feedUrl) {
super(feedUrl);
}
public List<Message> parse() {
final Message currentMessage = new Message();
RootElement root = new RootElement("rss");
final List<Message> messages = new ArrayList<Message>();
Element channel = root.getChild("channel");
Element item = channel.getChild(ITEM);
item.setEndElementListener(new EndElementListener(){
public void end() {
messages.add(currentMessage.copy());
}
});
item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setTitle(body);
}
});
item.getChild(LINK).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setLink(body);
}
});
item.getChild(DESCRIPTION).setEndTextElementListener(new
EndTextElementListener(){
public void end(String body) {
currentMessage.setDescription(body);
}
});
item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setDate(body);
}
});
try {
Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8,
root.getContentHandler());
} catch (Exception e) {
throw new RuntimeException(e);
}
return messages;
}
}
public class XmlPullFeedParser extends BaseFeedParser {
public XmlPullFeedParser(String feedUrl) {
super(feedUrl);
}
public List<Message> parse() {
List<Message> messages = null;
XmlPullParser parser = Xml.newPullParser();
try {
// auto-detect the encoding from the stream
parser.setInput(this.getInputStream(), null);
int eventType = parser.getEventType();
Message currentMessage = null;
boolean done = false;
while (eventType != XmlPullParser.END_DOCUMENT && !done){
String name = null;
switch (eventType){
case XmlPullParser.START_DOCUMENT:
messages = new ArrayList<Message>();
break;
case XmlPullParser.START_TAG:
name = parser.getName();
if (name.equalsIgnoreCase(ITEM)){
currentMessage = new Message();
} else if (currentMessage != null){
if (name.equalsIgnoreCase(LINK)){
currentMessage.setLink(parser.nextText());
} else if (name.equalsIgnoreCase(DESCRIPTION)){
currentMessage.setDescription(parser.nextText());
} else if (name.equalsIgnoreCase(PUB_DATE)){
currentMessage.setDate(parser.nextText());
} else if (name.equalsIgnoreCase(TITLE)){
currentMessage.setTitle(parser.nextText());
}
}
break;
case XmlPullParser.END_TAG:
name = parser.getName();
if (name.equalsIgnoreCase(ITEM) &&
currentMessage != null){
messages.add(currentMessage);
} else if (name.equalsIgnoreCase(CHANNEL)){
done = true;
}
break;
}
eventType = parser.next();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return messages;
}
}
private String writeXml(List<Message> messages){
XmlSerializer serializer = Xml.newSerializer();
StringWriter writer = new StringWriter();
try {
serializer.setOutput(writer);
serializer.startDocument("UTF-8", true);
serializer.startTag("", "messages");
serializer.attribute("", "number", String.valueOf(messages.size()));
for (Message msg: messages){
serializer.startTag("", "message");
serializer.attribute("", "date", msg.getDate());
serializer.startTag("", "title");
serializer.text(msg.getTitle());
serializer.endTag("", "title");
serializer.startTag("", "url");
serializer.text(msg.getLink().toExternalForm());
serializer.endTag("", "url");
serializer.startTag("", "body");
serializer.text(msg.getDescription());
serializer.endTag("", "body");
serializer.endTag("", "message");
}
serializer.endTag("", "messages");
serializer.endDocument();
return writer.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
If you don't understand the code,it's fully explained here: http://www.ibm.com/developerworks/opensource/library/x-android/
My problem on the phone starts on the MessageList.java like this:
It first calls: loadFeed(ParserType.ANDROID_SAX);
Then the function:
private void loadFeed(ParserType type){
try{
Log.i("AndroidNews", "ParserType="+type.name());
FeedParser parser = FeedParserFactory.getParser(type);
long start = System.currentTimeMillis();
messages = parser.parse();
long duration = System.currentTimeMillis() - start;
Log.i("AndroidNews", "Parser duration=" + duration);
String xml = writeXml();
Log.i("AndroidNews", xml);
List<String> titles = new ArrayList<String>(messages.size());
for (Message msg : messages){
titles.add(msg.getTitle());
}
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(this, R.layout.row,titles);
this.setListAdapter(adapter);
} catch (Throwable t){
Log.e("AndroidNews",t.getMessage(),t);
}
}
At the messages = parser.parse(); line the code just stops,no error and the screen remains black on my phone.
All the code was designed for android 1.5! My phone and the emulator have android 2.3.3!
KEEP IN MIND THAT: On the emulator the code works! On my phone it stops at the messages = parser.parse(); line.
Can someone give me a solution or something?
Try doing the parsing logic in a async task.
I am new to android and i am trying to build a RSS reader for Android. I have built all the classes and XML files but its not giving the required output. Its just showing the message
No RSS feed available.
Please can some one suggest what should i do.
Here is the code which i took from the tutorial and tried to manipulate-
public final String RSSFEEDOFCHOICE = "http://blog.01synergy.com/feed/";
public final String tag = "RSSReader";
private RSSFeed feed = null;
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
// go get our feed!
feed = getFeed(RSSFEEDOFCHOICE);
// display UI
UpdateDisplay();
}
private RSSFeed getFeed(String urlToRssFeed)
{
try
{
// setup the url
URL url = new URL(urlToRssFeed);
// create the factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// create a parser
SAXParser parser = factory.newSAXParser();
// create the reader (scanner)
XMLReader xmlreader = parser.getXMLReader();
// instantiate our handler
RSSHandler theRssHandler = new RSSHandler();
// assign our handler
xmlreader.setContentHandler(theRssHandler);
// get our data via the url class
InputSource is = new InputSource(url.openStream());
// perform the synchronous parse
xmlreader.parse(is);
// get the results - should be a fully populated RSSFeed instance, or null on error
return theRssHandler.getFeed();
}
catch (Exception ee)
{
// if we have a problem, simply return null
return null;
}
}
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
menu.add(0,0,0, "Choose RSS Feed");
menu.add(0,1,0, "Refresh");
Log.i(tag,"onCreateOptionsMenu");
return true;
}
public boolean onOptionsItemSelected(Menu item){
switch (((View) item).getId()) {
case 0:
Log.i(tag,"Set RSS Feed");
return true;
case 1:
Log.i(tag,"Refreshing RSS Feed");
return true;
}
return false;
}
private void UpdateDisplay()
{
TextView feedtitle = (TextView) findViewById(R.id.feedtitle);
TextView feedpubdate = (TextView) findViewById(R.id.feedpubdate);
ListView itemlist = (ListView) findViewById(R.id.itemlist);
if (feed == null)
{
feedtitle.setText("No RSS Feed Available");
return;
}
feedtitle.setText(feed.getTitle());
feedpubdate.setText(feed.getPubDate());
ArrayAdapter<RSSItem> adapter = new ArrayAdapter<RSSItem>(this,android.R.layout.simple_list_item_1,feed.getAllItems());
itemlist.setAdapter(adapter);
itemlist.setOnItemClickListener(this);
itemlist.setSelection(0);
}
public void onItemClick(AdapterView parent, View v, int position, long id)
{
Log.i(tag,"item clicked! [" + feed.getItem(position).getTitle() + "]");
Intent itemintent = new Intent(this,ShowDescription.class);
Bundle b = new Bundle();
b.putString("title", feed.getItem(position).getTitle());
b.putString("description", feed.getItem(position).getDescription());
b.putString("link", feed.getItem(position).getLink());
b.putString("pubdate", feed.getItem(position).getPubDate());
itemintent.putExtra("android.intent.extra.INTENT", b);
startSubActivity(itemintent,0);
}
private void startSubActivity(Intent itemintent, int i) {
// TODO Auto-generated method stub
}
}
This is my first approach to RSS Reader, It's no so dynamic and has boilerplate code but worked well for myself.
Usage:
RssParser parser = new RssParser(feedUrl);
Log.i("LOG", "Description: " + parser.getItem(3).description); //4th item's description
Class:
package com.uncocoder.course.app.feed_reader;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
public class RssParser extends DefaultHandler {
private StringBuilder content;
private boolean inChannel;
private boolean inImage;
private boolean inItem;
private ArrayList<Item> items = new ArrayList<Item>();
private Channel channel = new Channel();
private Item lastItem;
public RssParser(String url) {
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
URL sourceUrl = new URL(url);
xr.setContentHandler(this);
xr.parse(new InputSource(sourceUrl.openStream()));
}
catch (ParserConfigurationException e) {
e.printStackTrace();
}
catch (SAXException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
public class Item {
public String title;
public String description;
public String link;
public String category;
public String pubDate;
public String guid;
}
public class Channel {
public String title;
public String description;
public String link;
public String lastBuildDate;
public String generator;
public String imageUrl;
public String imageTitle;
public String imageLink;
public String imageWidth;
public String imageHeight;
public String imageDescription;
public String language;
public String copyright;
public String pubDate;
public String category;
public String ttl;
}
#Override
public void startDocument() throws SAXException {
Log.i("LOG", "StartDocument");
}
#Override
public void endDocument() throws SAXException {
Log.i("LOG", "EndDocument");
}
#Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if (localName.equalsIgnoreCase("image")) {
inImage = true;
}
if (localName.equalsIgnoreCase("channel")) {
inChannel = true;
}
if (localName.equalsIgnoreCase("item")) {
lastItem = new Item();
items.add(lastItem);
inItem = true;
}
content = new StringBuilder();
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (localName.equalsIgnoreCase("image")) {
inImage = false;
}
if (localName.equalsIgnoreCase("channel")) {
inChannel = false;
}
if (localName.equalsIgnoreCase("item")) {
inItem = false;
}
if (localName.equalsIgnoreCase("title")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.title = content.toString();
} else if (inImage) {
channel.imageTitle = content.toString();
} else if (inChannel) {
channel.title = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("description")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.description = content.toString();
} else if (inImage) {
channel.imageDescription = content.toString();
} else if (inChannel) {
channel.description = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("link")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.link = content.toString();
} else if (inImage) {
channel.imageLink = content.toString();
} else if (inChannel) {
channel.link = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("category")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.category = content.toString();
} else if (inChannel) {
channel.category = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("pubDate")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.pubDate = content.toString();
} else if (inChannel) {
channel.pubDate = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("guid")) {
if (content == null) {
return;
}
lastItem.guid = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("url")) {
if (content == null) {
return;
}
channel.imageUrl = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("width")) {
if (content == null) {
return;
}
channel.imageWidth = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("height")) {
if (content == null) {
return;
}
channel.imageHeight = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("language")) {
if (content == null) {
return;
}
channel.language = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("copyright")) {
if (content == null) {
return;
}
channel.copyright = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("ttl")) {
if (content == null) {
return;
}
channel.ttl = content.toString();
content = null;
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (content == null) {
return;
}
content.append(ch, start, length);
}
public Item getItem(int index) {
return items.get(index);
}
}
Check following link, It's open source RSS reader for Android, You can download code for reference
http://code.google.com/p/android-rss/
There is a tutorial (including complete source code) on how to build an Android RSS reder here:
part 1 (complete application)
part 2 (application updated to parse image tags from desciption)
part 3 (application update with Android 3.0)
The tutorial uses SAX parser and includes a complete Android project that accesses an RSS feed and then displays the feed in a list view.
There still seems to be a lot of people interested in this - so if you are looking for an Android 3.0+ with fragments/async tasks etc, as well as complete application code, I have updated the posts again, and they can be found here!
You can download and check my project on google-play.
This project is about some turkish sport channels feeds. Lots of channels are in one application.
You can check source code of project on github.
Parse this type of Rss Feeds easily using XmlPullParser
public class RSSParser {
public static ArrayList<Pojo> getParserData(String Data){
try {
RSSXMLTag currentTag = null;
ArrayList<Pojo> postDataList = new ArrayList<>();
XmlPullParserFactory factory = XmlPullParserFactory
.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader(Data));
int eventType = xpp.getEventType();
Pojo pdData = null;
SimpleDateFormat dateFormat = new SimpleDateFormat(
"EEEE, DD MMM yyyy ");
while (eventType != XmlPullParser.END_DOCUMENT) {
int i = 0;
if (eventType == XmlPullParser.START_DOCUMENT) {
} else if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equals("item")) {
pdData = new Pojo();
currentTag = RSSXMLTag.IGNORETAG;
} else if (xpp.getName().equals("title")) {
currentTag = RSSXMLTag.TITLE;
} else if (xpp.getName().equals("link")) {
currentTag = RSSXMLTag.LINK;
} else if (xpp.getName().equals("pubDate")) {
currentTag = RSSXMLTag.DATE;
} else if (xpp.getName().equals("creator")) {
currentTag = RSSXMLTag.CREATOR;
} else if (xpp.getName().equals("category")) {
currentTag = RSSXMLTag.CATEGORY;
} else if (xpp.getName().equals("description")) {
currentTag = RSSXMLTag.DESCRIPTION;
}
} else if (eventType == XmlPullParser.END_TAG) {
if (xpp.getName().equals("item")) {
// format the data here, otherwise format data in
// Adapter
Date postDate = dateFormat.parse(pdData.postDate);
pdData.postDate = dateFormat.format(postDate);
postDataList.add(pdData);
} else {
currentTag = RSSXMLTag.IGNORETAG;
}
} else if (eventType == XmlPullParser.TEXT) {
String content = xpp.getText();
content = content.trim();
Log.d("debug", content);
if (pdData != null) {
switch (currentTag) {
case TITLE:
if (content.length() != 0) {
if (pdData.postTitle != null) {
pdData.postTitle += content;
} else {
pdData.postTitle = content;
}
}
break;
case LINK:
if (content.length() != 0) {
if (pdData.postLink != null) {
pdData.postLink += content;
} else {
pdData.postLink = content;
}
}
break;
case DATE:
if (content.length() != 0) {
if (pdData.postDate != null) {
pdData.postDate += content;
} else {
pdData.postDate = content;
}
}
break;
case CATEGORY:
if (content.length() != 0) {
if (pdData.postCategory != null) {
i = i + 1;
if (i == 1) {
pdData.postCategory = content;
}
} else {
i = i + 1;
if (i == 1) {
pdData.postCategory = content;
}
}
}
break;
case DESCRIPTION:
if (content.length() != 0) {
if (pdData.postDescription != null) {
String s = content;
String string = s.substring(s.indexOf("src=\"") + 5, s.indexOf("\" class=\""));
pdData.postDescription += string;
} else {
String s = content;
String string = s.substring(s.indexOf("src=\"") + 5, s.indexOf("\" class=\""));
pdData.postDescription = string;
}
}
break;
case CREATOR:
if (content.length() != 0) {
if (pdData.postCreator != null) {
pdData.postCreator += content;
} else {
pdData.postCreator = content;
}
}
break;
default:
break;
}
}
}
eventType = xpp.next();
}
return postDataList;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public enum RSSXMLTag {
IGNORETAG, TITLE, LINK, DATE,CREATOR,CATEGORY, DESCRIPTION;
}
public class Pojo {
public String getPostTitle() {
return postTitle;
}
public void setPostTitle(String postTitle) {
this.postTitle = postTitle;
}
public String getPostLink() {
return postLink;
}
public void setPostLink(String postLink) {
this.postLink = postLink;
}
public String getPostDate() {
return postDate;
}
public void setPostDate(String postDate) {
this.postDate = postDate;
}
public String getPostCategory() {
return postCategory;
}
public void setPostCategory(String postCategory) {
this.postCategory = postCategory;
}
public String getPostDescription() {
return postDescription;
}
public void setPostDescription(String postDescription) {
this.postDescription = postDescription;
}
public String getPostCreator() {
return postCreator;
}
public void setPostCreator(String postCreator) {
this.postCreator = postCreator;
}
public String postTitle;
public String postLink;
public String postDate;
public String postCategory;
public String postDescription;
public String postCreator;
}
}