Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing XML feed die with "Element is already used"

I'm trying to parse an XML feed using SimpleXML in Android: http://backend.deviantart.com/rss.xml?type=deviation&q=by%3Aspyed+sort%3Atime+meta%3Aall

Sample here:

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        <title>DeviantArt: spyed's</title>
        <link>http://www.deviantart.com/?order=5&amp;q=by%3Aspyed</link>
        <description>DeviantArt RSS for sort:time by:spyed</description>
        <language>en-us</language>
        <copyright>Copyright 2015, DeviantArt.com</copyright>
        <pubDate>Thu, 20 Aug 2015 07:45:31 PDT</pubDate>
        <generator>DeviantArt.com</generator>
        <docs>http://blogs.law.harvard.edu/tech/rss</docs>
        <atom:icon>http://st.deviantart.net/minish/touch-icons/android-192.png</atom:icon>
        <atom:link type="application/rss+xml" rel="self" href="http://backend.deviantart.com/rss.xml?q=sort%3Atime+by%3Aspyed&amp;type=deviation" />
        <atom:link rel="next" href="http://backend.deviantart.com/rss.xml?q=sort%3Atime+by%3Aspyed&amp;type=deviation&amp;offset=60" />
        <item>
            <title>Happy 15th Birthday!</title>
            <link>http://spyed.deviantart.com/journal/Happy-15th-Birthday-552416478</link>
            <guid isPermaLink="true">http://spyed.deviantart.com/journal/Happy-15th-Birthday-552416478</guid>
            <pubDate>Sun, 09 Aug 2015 01:41:54 PDT</pubDate>
            <media:title type="plain">Happy 15th Birthday!</media:title>
            <media:keywords />
            <media:rating>nonadult</media:rating>
            <media:category label="Personal">journals/personal</media:category>
            <media:credit role="author" scheme="urn:ebu">spyed</media:credit>
            <media:credit role="author" scheme="urn:ebu">http://a.deviantart.net/avatars/s/p/spyed.gif</media:credit>
            <media:copyright url="http://spyed.deviantart.com">Copyright 2015 spyed</media:copyright>
            <media:description type="html" />
            <media:content url="http://spyed.deviantart.com/journal/Happy-15th-Birthday-552416478" medium="document" />
            <media:text type="html">In April I wrote a post reflecting on my 15 years at DeviantArt, since the project began in April of 2000 and was launched to the public on August 7th. I went back and re-read what I wrote, and wow, speaking of audacious I'm pretty hardcore in this post. I write from my heart sometimes and then I hit post and that's that. So for our official 15th Birthday I wanted to re-share a link to that post:&lt;br /&gt;&lt;br /&gt;And then today, I wrote this reflection for you as a toast &amp;amp; thanks for all the llamas:&lt;br /&gt;&lt;br /&gt;Happy 15th Birthday DeviantArt! We are evolving, and soon we will be able to share exactly how you can be a part of our transformation, ensuring that the De</media:text>
            <description />
        </item>
        <item>
            <title>The Floor is Open</title>
            <link>http://spyed.deviantart.com/journal/The-Floor-is-Open-548845475</link>
            <guid isPermaLink="true">http://spyed.deviantart.com/journal/The-Floor-is-Open-548845475</guid>
            <pubDate>Sat, 25 Jul 2015 11:38:46 PDT</pubDate>
            <media:title type="plain">The Floor is Open</media:title>
            <media:keywords />
            <media:rating>nonadult</media:rating>
            <media:category label="Personal">journals/personal</media:category>
            <media:credit role="author" scheme="urn:ebu">spyed</media:credit>
            <media:credit role="author" scheme="urn:ebu">http://a.deviantart.net/avatars/s/p/spyed.gif</media:credit>
            <media:copyright url="http://spyed.deviantart.com">Copyright 2015 spyed</media:copyright>
            <media:description type="html" />
            <media:content url="http://spyed.deviantart.com/journal/The-Floor-is-Open-548845475" medium="document" />
            <media:text type="html">Happy Saturday! I'm hanging out at home, so I thought I'd have an open conversation. Post anything, I'll reply. It's about 11:30am, I'll be in front of this thing for two hours before I go to my god daughters 7th birthday party! Yay!&lt;br /&gt;&lt;br /&gt;If you're wondering what we're up to, check out the DeviantArt Timeline ( http://www.deviantart.com/timeline/ ) -- It might compel you to ask some questions. Or, if there's anything you've been wondering about, ask!&lt;br /&gt;&lt;br /&gt;Here's some food for thought to get you started about the overall state of DeviantArt:&lt;br /&gt;&lt;br /&gt;Our team focuses on two things that matter most to us, the first is our mission to Entertain, Inspire &amp;amp; Em</media:text>
            <description />
        </item>
        ... etc ....

but I'm getting the following error:

08-13 15:55:38.529: W/System.err(1437): org.simpleframework.xml.core.PersistenceException: Element 'title' is already used with @org.simpleframework.xml.Element(data=false, name=title, required=false, type=void) on field 'title' public java.lang.String com.example.feedreader.SimpleRss$Channel$RssItem.title at line 1

I noticed that there is a title tag in two different levels, but I'm not sure how to make the distinction in code.

Here's what I have:

@Root(name = "rss", strict = false)
public class SimpleRss implements FeedRoot {

    @Root(name = "channel")
    public static class Channel {

        @Element(name = "title", required = false)
        public String title = "";

        @Attribute(name = "href", required = false)
        @ElementList(entry = "link", inline = true, required = false)
        private List<String> links;

        @Element(name = "description", required = false)
        @Namespace(prefix = "")
        public String description = "";

        @Element(name = "pubDate", required = false)
        public String pubDate = "";

        @Element(name = "event_link", required = false)
        public String event_link = "";

        @Root(name = "item")
        public static class RssItem implements SimpleFeedItem {

            public String parent = "";
            public String feedUrl = null;
            public Date date = null;

            @Element(name = "title", required = false)
            public String title = "";

            @Element(name = "link", required = false)
            public String link = "";

            @Element(name = "event_link", required = false)
            public String event_link = "";

            @Element(name = "description", required = false)
            public String description = "";

            @Element(name = "pubDate", required = false)
            public String pubDate = "";

            @Path("enclosure")
            @Attribute(name = "url", required = false)
            public String enclosureUrl = "";

            @Path("enclosure")
            @Attribute(name = "type", required = false)
            public String enclosureType = "";

            @Override
            public String getTitle() {
                return title;
            }

            @Override
            public String getDescription() {
                return description;
            }

            @Override
            public String getLink() {
                return link;
            }

            @Override
            public String getEventLink() {
                return event_link;
            }

            @Override
            public String getAdditional() {
                return parent;
            }

            @Override
            public String getPubDate() {
                return pubDate;
            }

            @Override
            public String getFeedUrl() {
                return feedUrl;
            }

            @Override
            public void setFeedUrl(String url) {
                feedUrl = url;
            }

            @Override
            public void setDate(Date date) {
                this.date = date;
            }

            @Override
            public Date getDate() {
                return date;
            }

            @Override
            public String getPictureUrl() {
                if (DataUtils.isEmpty(enclosureType)) {
                    return null;
                } else if (SimpleFeedItem.SupportedFeedImageTypes
                        .contains(enclosureType.toLowerCase(Locale.ENGLISH))) {
                    return enclosureUrl;
                } else {
                    return null;
                }
            }

        }

        @ElementList(inline = true, required = false)
        public List<RssItem> rssItems = J.newArrayList();

    }

    @Element(name = "channel")
    public Channel channel;

    @Override
    public List<SimpleFeedItem> getItems() {
        List<SimpleFeedItem> items = J.newArrayList();

        if (channel != null && channel.rssItems != null) {
            for (RssItem item : channel.rssItems) {
                String title = channel.title;
                if (title == null) {
                    title = "";
                }
                item.parent = title.intern();
                items.add(item);
            }
        }
        return items;
    }

    @Override
    public String getTitle() {
        if (channel == null) {
            return "";
        } else {
            return channel.title;
        }
    }

}

I've tried commenting out the

@Element(name = "title", required = false)
public String title = "";

in the Channel class and I get the same error. Also if I just rename it.

If I do the same with the one in the RssItem class however, it will work but I don't get the titles for the items.

Thanks!

like image 420
zundi Avatar asked Aug 13 '15 22:08

zundi


3 Answers

This fixes the problem:

Remove this:

@Element(name = "title", required = false)

Replace with:

//inside the inner class RssItem
@Path("title")
@Text(required=false)
public String title = "";

This should be repeated for any other field that gets the exception.

like image 108
zundi Avatar answered Nov 15 '22 16:11

zundi


It appears that using

@Element(name = "title", required = false, inLine=true)
public String title = "";

will solve your problem, as shown here.

like image 24
Rossiar Avatar answered Nov 15 '22 15:11

Rossiar


There are two title elements in your XML file. The first title element is in channel tag and the other title element is in item tag. so you should specify to the parser that the paths for these titles are different. do that in the following way:

Edit this:

@Element(name = "title", required = false)
public String title = "";

Add Path Annotation:

@Element(name = "title", required = false)
@Path('rss/channel')
public String title = "";

here you specified for the title in channel tag that this is your path. the other title differs from you :)

like image 1
Nasrullah Mohseni Avatar answered Nov 15 '22 15:11

Nasrullah Mohseni