Pergunta

I have been developing an Android RSS Reader Application and have had a problem with fetching HTML content from description node.

I tried to fetch the data from following XML.

        <description>
    <p><a href="http://in.news.yahoo.com/search-arizona-girl-6-turns-back-her-tucson-021230195.html">
   <img src="http://l.yimg.com/bt/api/res/1.2/t8X__zdk6shihpWw0Nenfw--/YXBwaWQ9eW5ld3M7Zmk9ZmlsbDtoPTg2O3B4b2ZmPTUwO3B5b2ZmPTA7cT04NTt3PTEzMA--/http://media.zenfs.com/en_us/News/Reuters/2012-04-24T021230Z_1_CDEE83N064W00_RTROPTP_2_USA-MISSING-ARIZONA.JPG" 
width="130" height="86" alt="Handout photo of Isabel Mercedes Celis" align="left" title="Handout photo of Isabel Mercedes Celis" border="0" />

</a>
      TUCSON, Arizona (Reuters) - The search for a missing 6-year-old Arizona girl who a               authorities said may have been snatched from her bedroom in Tucson entered its third day on  Monday as search dogs shifted investigators' attention back to the child's home. The  parents of first-grader Isabel Mercedes Celis told detectives she was last seen on Friday  night when they tucked her into bed, and was found to have vanished when a family member   entered her room the next morning to awaken her, police said. ...
    </p>
  <br clear="all"/>
 </description>

it display blank when I fetch data. I paste my whole code below..

I am fetching Rss from this url: http://in.news.yahoo.com/rss/crime

RSSActivity.java

package com.satyampv.dsta;


import java.util.ArrayList;
import java.util.HashMap;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;


import android.app.ListActivity;
import android.os.Bundle;

import android.text.util.Linkify;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.SimpleAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class AstroRssActivity extends ListActivity {
    /** Called when the activity is first created. */
    //static final String URL = "http://findyourfate.com/rss/dailyhoroscope-feed.asp?sign=Taurus";

    //static final String URL = "http://my.horoscope.com/astrology/daily-horoscopes-rss.html";
    static final String URL = "http://in.news.yahoo.com/rss/crime";
    // XML node keys
    static final String KEY_ITEM = "item"; // parent node
    static final String KEY_TITLE = "title";
    static final String KEY_DESC = "description";
    static final String KEY_LINK = "link";



    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();

        XMLParser parser = new XMLParser();
        String xml = parser.getXMLFromURL(URL);// getting XML
        Document doc = parser.getDocumentElement(xml);// getting DOM element

        NodeList nl = doc.getElementsByTagName(KEY_ITEM);
        // looping through all item nodes <item>
        for (int i = 0; i < nl.getLength(); i++) {
            // creating new HashMap
            HashMap<String, String> map = new HashMap<String, String>();
            Element e = (Element) nl.item(i);

            // adding each child node to HashMap key => value

            map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
            map.put(KEY_DESC, parser.getValue(e, KEY_DESC));
            map.put(KEY_LINK,parser.getValue(e, KEY_LINK));


            // adding HashList to ArrayList
            menuItems.add(map);
        }

        // Adding menuItems to ListView
        ListAdapter adapter = new SimpleAdapter(this, menuItems,
                R.layout.list_item,
                new String[] { KEY_TITLE, KEY_DESC, KEY_LINK }, new int[] {
                        R.id.name, R.id.desciption, R.id.link });

        setListAdapter(adapter);

XMLParser.java

package com.satyampv.dsta;

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;


import android.util.Log;

public class XMLParser {


    public XMLParser() {

    }

    public String getXMLFromURL(String url) {

        String xml = null;

        try {
            // Default HTTP Client

            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);

            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();

            xml = EntityUtils.toString(httpEntity);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // return XML
        return xml;
    }

    // Getting xml Dom element @param xml String

    public Document getDocumentElement(String xml) {

        Document doc = null;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        try {

            DocumentBuilder db = dbf.newDocumentBuilder();

            InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xml));
            doc = db.parse(is);
        } catch (ParserConfigurationException e) {
            Log.e("Error", e.getMessage());
            return null;
        } catch (SAXException e) {

            Log.e("Error", e.getMessage());
            return null;

        } catch (IOException e) {
            Log.e("Error", e.getMessage());
            return null;
        }

        return doc;
    }


    public String getValue(Element item,String str){
        NodeList n = item.getElementsByTagName(str);
        return this.getElementValue(n.item(0));
    }
    // Getting node Value
    // @params ele element

    public final String getElementValue(Node elem) {
        Node child;

        if (elem != null) {

            if (elem.hasChildNodes()) {
                for (child = elem.getFirstChild(); child != null; child = child
                        .getNextSibling())
                {
                    if (child.getNodeType() == Node.TEXT_NODE) {
                        return child.getNodeValue();
                    }
                }

            }
        }

        return "";

    }
}
Foi útil?

Solução

if your description Node contains HTML tags, it does not contain any TEXT_NODE type child, which is why it returns empty.

Check what type are the child nodes in your description Node to see what to do of these.

Edit

One solution is using getTextContent ( http://docs.oracle.com/javase/1.5.0/docs/api/org/w3c/dom/Node.html#getTextContent%28%29 ) instead of searching for a Text node. Instead of:

if (elem.hasChildNodes()) {
    for (child = elem.getFirstChild(); child != null; child = child.getNextSibling()) {
        if (child.getNodeType() == Node.TEXT_NODE) {
            return child.getNodeValue();
        }
    }
}

you can simply go :

return elem.getTextContent();

Later, you can parse the HTML using Html.fromHtml() :

HashMap<String, Spanned> map = new HashMap<String, Spanned>();

and

map.put(KEY_DESC, Html.fromHtml(parser.getValue(e, KEY_DESC)));

(see http://developer.android.com/reference/android/text/Html.html#fromHtml%28java.lang.String%29 )

Edit2

And replace

ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();

with

ArrayList<HashMap<String, Spanned>> menuItems = new ArrayList<HashMap<String, Spanned>>();

Moreover, I think SimpleAdapter expects Strings for TextViews, so you may need a ViewBinder to put Spanned in the TextView:

SimpleAdapter adapter = new SimpleAdapter(...);
adapter.setViewBinder(new SimpleAdapter.ViewBinder() {
    public boolean setViewValue(View view, Object data, String textRepresentation) {
        if (data instanceof Spanned && view instanceof TextView) {
            ((TextView) view).setText((Spanned) data));
        }
    }
}

Outras dicas

Check this example.Its a simple RSS reader and very easy to understand... http://droidapp.co.uk/?p=166

The best way to display HTML content in android is using Webview.So display the data inside description node using webview.It will display both the text and also images.Here is a sample code...

    WebView Description;
    Description = (WebView)findViewById(R.id.webView1);
    Description.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
    Description.getSettings().setJavaScriptEnabled(true);
    Description.getSettings().setBuiltInZoomControls(true);





    Bundle mybundle = getIntent().getExtras();
    Integer NewsNumber = mybundle.getInt("number");

    final String CurrentTitle = Arrays.Title[NewsNumber];
    String CurrentDescription = Arrays.Description[NewsNumber];


    NewsTitle.setText(CurrentTitle);

    Description.loadDataWithBaseURL (null, "<html>"+CurrentDescription+"</html>", "text/html", "UTF-8",
    null); 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top