Android RSS阅读器在第一段后切断

时间:2013-01-29 17:02:23

标签: android xml xml-parsing rss sax

我正在为学校报纸创建一个应用程序,并在尝试显示完整文章时遇到问题。目前,我有一个从RSS源中提取的文章列表,当点击一个文章时,它会显示文章的内容。但是只有第一段显示在TextView中,无论它有多长。这让我觉得它与<p></p> HTML标记有关。我不熟悉RSS提要或解析XML(这是我第一次尝试它)并且已经四处寻找方法去做我想要完成的事情。

来自:Android TextView cuts off after one paragraph

我是根据上述问题的结果创建此问题的。我认为我的应用程序的问题与TextView及其属性有关,但通过使用我在其中硬编码的纯文本操作得很好。

根据我尝试的评论和事情,问题似乎是应用程序如何从RSS源中读取信息。就像我之前说的那样,这是我第一次在Android中使用RSS提要,而我正在使用示例项目代码(可以在之前的问题中找到)。以下是与RSS提要相关的代码:

的RSSFeed 的.java:

public class RSSFeed {

    private String title = null;
    private String description = null;
    private String link = null;
    private String pubdate = null;
    private String content = null;
    private List<RSSItem> itemList;

    RSSFeed(){
        itemList = new Vector<RSSItem>(0);
    }

    void addItem(RSSItem item){
        itemList.add(item);
    }

    RSSItem getItem(int location){
        return itemList.get(location);
    }

    List<RSSItem> getList(){
        return itemList;
    }

    void setTitle(String value){
        title = value;
    }
    void setDescription(String value){
        description = value;
    }
    void setLink(String value){
        link = value;
    }
    void setPubdate(String value){
        pubdate = value;
    }
    public void setContent(String value) {
        content=value;
    }

    String getTitle(){
        return title;
    }
    String getDescription(){
        return description;
    }
    String getLink(){
        return link;
    }
    String getPubdate(){
        return pubdate;
    }

    String getContent() {
        return content;
    }



}

RSSHandler 的.java:

public class RSSHandler extends DefaultHandler {

// Feed and Article objects to use for temporary storage
private Article currentArticle = new Article();
private List<Article> articleList = new ArrayList<Article>();

// Number of articles added so far
private int articlesAdded = 0;

// Number of articles to download
private static final int ARTICLES_LIMIT = 15;

//Current characters being accumulated
StringBuffer chars = new StringBuffer();


/* 
 * This method is called every time a start element is found (an opening XML marker)
 * here we always reset the characters StringBuffer as we are only currently interested
 * in the the text values stored at leaf nodes
 * 
 * (non-Javadoc)
 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
 */
public void startElement(String uri, String localName, String qName, Attributes atts) {
    chars = new StringBuffer();
}



/* 
 * This method is called every time an end element is found (a closing XML marker)
 * here we check what element is being closed, if it is a relevant leaf node that we are
 * checking, such as Title, then we get the characters we have accumulated in the StringBuffer
 * and set the current Article's title to the value
 * 
 * If this is closing the "Item", it means it is the end of the article, so we add that to the list
 * and then reset our Article object for the next one on the stream
 * 
 * 
 * (non-Javadoc)
 * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
 */
public void endElement(String uri, String localName, String qName) throws SAXException {

    if (localName.equalsIgnoreCase("title"))
    {
        Log.d("LOGGING RSS XML", "Setting article title: " + chars.toString());
        currentArticle.setTitle(chars.toString());

    }
    else if (localName.equalsIgnoreCase("description"))
    {
        Log.d("LOGGING RSS XML", "Setting article description: " + chars.toString());
        currentArticle.setDescription(chars.toString());
    }
    else if (localName.equalsIgnoreCase("pubDate"))
    {
        Log.d("LOGGING RSS XML", "Setting article published date: " + chars.toString());
        currentArticle.setPubDate(chars.toString());
    }
    else if (localName.equalsIgnoreCase("encoded"))
    {
        Log.d("LOGGING RSS XML", "Setting article content: " + chars.toString());
        currentArticle.setEncodedContent(chars.toString());
    }
    else if (localName.equalsIgnoreCase("item"))
    {

    }
    else if (localName.equalsIgnoreCase("link"))
    {
        try {
            Log.d("LOGGING RSS XML", "Setting article link url: " + chars.toString());
            currentArticle.setUrl(new URL(chars.toString()));
        } catch (MalformedURLException e) {
            Log.e("RSA Error", e.getMessage());
        }

    }




    // Check if looking for article, and if article is complete
    if (localName.equalsIgnoreCase("item")) {

        articleList.add(currentArticle);

        currentArticle = new Article();

        // Lets check if we've hit our limit on number of articles
        articlesAdded++;
        if (articlesAdded >= ARTICLES_LIMIT)
        {
            throw new SAXException();
        }
    }
}





/* 
 * This method is called when characters are found in between XML markers, however, there is no
 * guarantee that this will be called at the end of the node, or that it will be called only once
 * , so we just accumulate these and then deal with them in endElement() to be sure we have all the
 * text
 * 
 * (non-Javadoc)
 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
 */
public void characters(char ch[], int start, int length) {
    chars.append(new String(ch, start, length));
}





/**
 * This is the entry point to the parser and creates the feed to be parsed
 * 
 * @param feedUrl
 * @return
 */
public List<Article> getLatestArticles(String feedUrl) {
    URL url = null;
    try {

        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();

        url = new URL(feedUrl);

        xr.setContentHandler(this);
        xr.parse(new InputSource(url.openStream()));


    } catch (IOException e) {
        Log.e("RSS Handler IO", e.getMessage() + " >> " + e.toString());
    } catch (SAXException e) {
        Log.e("RSS Handler SAX", e.toString());
    } catch (ParserConfigurationException e) {
        Log.e("RSS Handler Parser Config", e.toString());
    }

    return articleList;
}

}

的RSSItem 的.java:

public class RSSItem {

private String title = null;
private String description = null;
private String link = null;
private String pubdate = null;
private String content = null;

RSSItem(){
}

void setTitle(String value){
    title = value;
}
void setDescription(String value){
    description = value;
}
void setLink(String value){
    link = value;
}
void setPubdate(String value){
    pubdate = value;
}
public void setContent(String value) {
    content=value;
}

String getTitle(){
    return title;
}
String getDescription(){
    return description;
}
String getLink(){
    return link;
}
String getPubdate(){
    return pubdate;
}

public String getContent() {
    return content;
}



@Override
public String toString() {
    // TODO Auto-generated method stub
    return title;
}

}

AllStoriesFragment 的.java:

public class AllStoriesFragment extends ListFragment {

/*********************************************************************
 * RSS Async Task
 *********************************************************************/
public class RssLoadingTask extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPostExecute(Void result) {
        // TODO Auto-generated method stub
        displayRss();
    }

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        preReadRss();
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        // TODO Auto-generated method stub
        //super.onProgressUpdate(values);
    }

    @Override
    protected Void doInBackground(Void... arg0) {
        // TODO Auto-generated method stub
        readRss();
        return null;
    }

}
/*********************************************************************
 * End RSS Async Task
 *********************************************************************/

private RSSFeed myRssFeed = null;

TextView feedTitle;
TextView feedDescription;

/*********************************************************************
 * Custom Array Adapter 
 *********************************************************************/

public class MyCustomAdapter extends ArrayAdapter<RSSItem> {

        public MyCustomAdapter(Context context, int textViewResourceId, List<RSSItem> list) {
            super(context, textViewResourceId, list);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub
            //return super.getView(position, convertView, parent);

            View row = convertView;

            if(row==null){
                LayoutInflater inflater=getActivity().getLayoutInflater();
                row=inflater.inflate(R.layout.row, parent, false);
            }
            //Set Item Title
            TextView listTitle=(TextView)row.findViewById(R.id.listtitle);
            listTitle.setText(myRssFeed.getList().get(position).getTitle());

            //Set Item PubDate
            TextView listPubdate=(TextView)row.findViewById(R.id.listpubdate);
            listPubdate.setText(myRssFeed.getList().get(position).getPubdate());

            if (position%2 == 0){
                listTitle.setBackgroundColor(0xff101010);
                listPubdate.setBackgroundColor(0xff101010);
            }
            else{
                listTitle.setBackgroundColor(0xff080808);
                listPubdate.setBackgroundColor(0xff080808);
            }

            return row;
        }
    }
    /*********************************************************************
     * End Custom Array Adapter 
     *********************************************************************/

   /** Called when the fragment is first created. */
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View v =  inflater.inflate(R.layout.fragment_allstories, null);
        Log.d("MainActivity", "AllStoriesFragment started.");

        feedTitle = (TextView)v.findViewById(R.id.feedtitle);
        feedDescription = (TextView)v.findViewById(R.id.feeddescription);
        startReadRss();

        return v ;
    }

   private void startReadRss(){
       new RssLoadingTask().execute();
   }

   private void preReadRss(){
       setListAdapter(null);

       Toast.makeText(getActivity(), "Reading RSS, Please wait.", Toast.LENGTH_LONG).show();
   }

   private void readRss(){
       try {
           URL rssUrl = new URL("http://www.campusslate.com/feed/");
           InputSource myInputSource = new InputSource(rssUrl.openStream());

           SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
           SAXParser mySAXParser = mySAXParserFactory.newSAXParser();

           RSSHandler myRSSHandler = new RSSHandler();

           XMLReader myXMLReader = mySAXParser.getXMLReader();

           myXMLReader.setContentHandler(myRSSHandler);
           myXMLReader.parse(myInputSource);

           myRssFeed = myRSSHandler.getFeed();
       } 
       catch (MalformedURLException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       } 
       catch (ParserConfigurationException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       } 
       catch (SAXException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       } 
       catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }
    }

   private void displayRss(){

       if (myRssFeed!=null){
           MyCustomAdapter adapter = new MyCustomAdapter(getActivity(), R.layout.row, myRssFeed.getList());
           setListAdapter(adapter);
       }
   }


   public void onListItemClick(ListView l, View v, int position, long id) {
       // TODO Auto-generated method stub
       Intent intent = new Intent(getActivity(), ShowDetails.class);
       intent.putExtra("keyPubdate", myRssFeed.getItem(position).getPubdate());
       intent.putExtra("keyLink", myRssFeed.getItem(position).getLink());
       intent.putExtra("keyTitle", myRssFeed.getItem(position).getTitle());
       intent.putExtra("keyContent", myRssFeed.getItem(position).getContent());
       startActivity(intent);
   }

   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
    // TODO Auto-generated method stub
    switch(item.getItemId()){
    case (0): readRss();
      break;
    default:
      break;
    }

    return true;
   }
}

ShowDetails.java发布在另一个问题中,尽管代码可能与我目前的代码略有不同。现在的问题是列表中的每个项目都是从RSS Feed中读取的最后一项。

如果我有足够的声誉,会发布图片。

1 个答案:

答案 0 :(得分:0)

XML元素可能有多个文本节点。您的代码假定只有一个。请在characters()回调中使用追加操作,而不是设置操作。