1

I am building an RSS feed parser using XmlPullParser in Android Studio. I would like to display the feed images in my app, however I am having trouble retrieving the url attribute value in the <media:thumbnail> tag. As a note: I am only retrieving things inside <item>. After doing considerable research, I learned it has something to do with XML namespaces. I setNamespaceAware(true), with no luck. All my other elements are being retrieved properly, but I keep getting null for my imageLink variable. I have also tried setting

else if (name.equalsIgnoreCase("media:thumbnail")) {
    imageLink = xmlPullParser.getAttributeValue(null, "url");
}

to "media:thumbnail" or "thumbnail".

Link to the RSS feed: https://www.goal.com/feeds/en/news

A snippet of the XML code:

<item>
  <title>
    <![CDATA[Mexico boss Martino responds after USMNT's Berhalter calls on referee to take control of Gold Cup final]]>
  </title>
  <pubDate>Sat, 31 Jul 2021 20:30:03 GMT</pubDate>
  <link>
  <![CDATA[https://www.goal.com/en/news/mexico-boss-martino-responds-after-usmnts-berhalter-calls-on/1h5obazjxkl3c1hrevc53ovtfy]]>
  </link>
  <guid isPermaLink="false">urn:perform:article:1h5obazjxkl3c1hrevc53ovtfy</guid>
  <description>
    <![CDATA[The two managers went back and forth when discussing each team's ability to manipulate the match official]]>
  </description>
  <category>@Geo; Everywhere</category>
  <category>@Targeting</category>
  <category>@Google Newsstand</category>
  <category>@Apple News</category>
  <category>@News2021</category>
  <category>@News - original</category>
  <category>@Manager/coach quotes</category>
  <media:content url="http://images.daznservices.com/di/library/GOAL/36/54/martino-berhalter-split_1bbaicsveobrw1xcg0fsjk04ra.png?t=43319131" type="image/jpeg" />
  <media:thumbnail url="http://images.daznservices.com/di/library/GOAL/36/54/martino-berhalter-split_1bbaicsveobrw1xcg0fsjk04ra.png?t=43319131" />
  <media:content url="http://images.daznservices.com/di/library/GOAL/36/54/martino-berhalter-split_1bbaicsveobrw1xcg0fsjk04ra.png?t=43319131" type="image/jpeg" />
  <media:thumbnail url="http://images.daznservices.com/di/library/GOAL/36/54/martino-berhalter-split_1bbaicsveobrw1xcg0fsjk04ra.png?t=43319131" />
  <media:content url="http://images.daznservices.com/di/library/GOAL/36/54/martino-berhalter-split_1bbaicsveobrw1xcg0fsjk04ra.png?t=43319131" type="image/jpeg" />
  <media:thumbnail url="http://images.daznservices.com/di/library/GOAL/36/54/martino-berhalter-split_1bbaicsveobrw1xcg0fsjk04ra.png?t=43319131" />
  <media:content url="http://images.daznservices.com/di/library/GOAL/36/54/martino-berhalter-split_1bbaicsveobrw1xcg0fsjk04ra.png?t=43319131" type="image/jpeg" />
  <media:thumbnail url="http://images.daznservices.com/di/library/GOAL/36/54/martino-berhalter-split_1bbaicsveobrw1xcg0fsjk04ra.png?t=43319131" />
  <df:language>en</df:language>
  <dc:language>en</dc:language>
  <df:authors/>
  <dc:creator/>
</item>

This is my code

public List<RssFeedModel> parseFeed(InputStream inputStream) throws XmlPullParserException, IOException {
    String title = null;
    String link = null;
    String description = null;
    String imageLink = null;
    boolean isItem = false;
    List<RssFeedModel> items = new ArrayList<>();

    try {
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XmlPullParser xmlPullParser = factory.newPullParser();
        xmlPullParser.setInput(inputStream, "UTF-8");

        while (xmlPullParser.next() != XmlPullParser.END_DOCUMENT) {
            int eventType = xmlPullParser.getEventType();

            String name = xmlPullParser.getName();
            if (name == null)
                continue;
            if (eventType == XmlPullParser.END_TAG) {
                if (name.equalsIgnoreCase("item")) {
                    isItem = false;
                }
                continue;
            }
            if (eventType == XmlPullParser.START_TAG) {
                if (name.equalsIgnoreCase("item")) {
                    isItem = true;

                    continue;
                }
            }
            Log.d("MyXmlParser", "Parsing name ==> " + name);
            String result = "";
            if (xmlPullParser.next() == XmlPullParser.TEXT) {
                result = xmlPullParser.getText();
                xmlPullParser.nextTag();
            }

            if (name.equalsIgnoreCase("title")) {
                title = result;
            } else if (name.equalsIgnoreCase("link")) {
                link = result;
            } else if (name.equalsIgnoreCase("description")) {
                description = result;
            } else if (name.equalsIgnoreCase("thumbnail")) {//for image
                imageLink = xmlPullParser.getAttributeValue(null, "url");
            }

            if (title != null && link != null && description != null) {
                if (isItem) {
                    RssFeedModel item = new RssFeedModel(title, link, description, imageLink);
                    items.add(item);
                } else {
                    mFeedTitle = title;
                    mFeedLink = link;
                    mFeedDescription = description;
                }
            }
        }
        return items;
    } finally {
        inputStream.close();
    }
}
2
  • 1
    It's 2021. Life is too short to use XmlPullParser. Use Moshi. If you insist upon using XmlPullParser, then I think you need to be passing the namespace URI as the first parameter to getAttributeValue(), since you have enabled namespaces. "http://search.yahoo.com/mrss/" appears to be the URI, based upon the full XML document. Commented Jul 31, 2021 at 21:53
  • Thanks for your reply. I passed the namespace URI to getAttributeValue() but that didn't work either. This is for an assignment which specifically requires XmlPullParser, but I will keep Moshi in mind for future work. Much appreciated again. Commented Aug 1, 2021 at 1:31

1 Answer 1

0

Just answering my own question for future reference:

public List<RssFeedModel> parseFeed(InputStream inputStream) throws XmlPullParserException, IOException {

/**
 * Declares the variables to hold article title, link and description
 * Declares List to hold all items once parsed
 */
String title = null;
String link = null;
String description = null;
String imageLink = null;
List<RssFeedModel> items = new ArrayList<>();

/**Logic for parsing through the XML*/
try {
    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    factory.setNamespaceAware(true);
    XmlPullParser xpp = factory.newPullParser();
    xpp.setInput(inputStream, null);

    /**Retrieves eventType (START_DOCUMENT, START_TAG, END_DOCUMENT)*/
    int eventType = xpp.getEventType();
    /**Only checks items that are within the <item></item> tags*/
    boolean insideItem = false;

    while (eventType != XmlPullParser.END_DOCUMENT) {
        if (eventType == XmlPullParser.START_TAG) {
            if (xpp.getName().equalsIgnoreCase("item")) {
                insideItem = true;
            } else if (xpp.getName().equalsIgnoreCase("title")) {
                if (insideItem) {
                    title = xpp.nextText();
                }
            } else if (xpp.getName().equalsIgnoreCase("description")) {
                if (insideItem) {
                    description = xpp.nextText();
                }
            } else if (xpp.getName().equalsIgnoreCase("link")) {
                if (insideItem) {
                    link = xpp.nextText();
                }
            } else if (xpp.getName().equalsIgnoreCase("thumbnail")) {
                if (insideItem) {
                    imageLink = xpp.getAttributeValue(null, "url");
                }
            }

            /**Once cursor arrives at the END_TAG, save parsed items into List*/
        } else if (eventType == XmlPullParser.END_TAG) {
            if(xpp.getName().equalsIgnoreCase("item")){
                if (insideItem) {
                    RssFeedModel item = new RssFeedModel(title, link, description, imageLink);
                    items.add(item);
                }else if (xpp.getName().equalsIgnoreCase("channel")){
                    insideItem = false;
                }
            }
        }
        eventType = xpp.next();
    }

    return items;
} finally {
    inputStream.close();
}

}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.