Search code examples
javaandroidxmlrssretrofit

How to parse RSS xml feed using Retrofit lib


I am trying to parse an XML feed with Retrofit API but I was blocked, I don't know how to access those attributes I think the problem is the Root RSS!

This is the feed : http://www.ka-news.de/storage/rss/rss/karlsruhe.xml

The main activity is where I will pass the data (list of items) to the adapter.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub      
    View rootView = inflater.inflate(R.layout.fragment_main, container, false);

    RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint("http://www.ka-news.de")
            .setConverter(new SimpleXmlConverter())
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .build();

    api apiService = restAdapter.create(api.class);
    Rss rss = apiService.getRss();
    List<Item> items = rss.getChannel().getItemList();
    // Obtener el Recycler
    recycler = (RecyclerView) rootView.findViewById(R.id.reciclador);
    recycler.setHasFixedSize(true);

    // Usar un administrador para LinearLayout
    lManager = new LinearLayoutManager(getContext());
    recycler.setLayoutManager(lManager);

    // Crear un nuevo adaptador
    adapter = new AnimeAdapter(items);
    recycler.setAdapter(adapter);


    rootView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT ));       
    return rootView;        
}

api interface :

public interface api {
@GET("/storage/rss/rss/karlsruhe.xml")
public Rss getRss();
}

I have created three entities :

Channel :

@Root(strict = false)
public class Channel {
    @ElementList(name = "item", required = true, inline = true)
    public List<Item> itemList;

public List<Item> getItemList() {
    return itemList;
}

public void setItemList(List<Item> itemList) {
    this.itemList = itemList;
}

}

Item:

@Root(name = "item", strict = false)
public  class Item {
@Element(name = "title", required = true)
String title;
@Element(name = "link", required = true)
String link;
@Element(name = "description", required = true)
String description;
@Element(name = "pubDate", required = false)
String pubDate;


public String getTitle() {
    return title;
}

public void setTitle(String title) {
    this.title = title;
}

public String getLink() {
    return link;
}

public void setLink(String link) {
    this.link = link;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public String getPubDate() {
    return pubDate;
}

public void setPubDate(String pubDate) {
    this.pubDate = pubDate;
}

@Override
public String toString() {
    return "Item{" +
            "title='" + title + '\'' +
            ", link='" + link + '\'' +
            ", description='" + description + '\'' +
            ", pubDate='" + pubDate + '\'' +
            '}';
}

}

Rss:

@Root
public class Rss {

@Attribute
String version;

@Element
Channel channel;


public Channel getChannel() {
    return channel;
}

public String getVersion() {
    return version;
}

public void setVersion(String version) {
    this.version = version;
}

public void setChannel(Channel channel) {
    this.channel = channel;
}

@Override
public String toString() {
    return "RSS{" +
            "version='" + version + '\'' +
            ", channel=" + channel +
            '}';
}

}

the problem showing in log is :

FATAL EXCEPTION: main
retrofit.RetrofitError
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:394)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
at $Proxy1.getRss(Native Method)
at br.liveo.ndrawer.ui.fragment.MainFragment.onCreateView(MainFragment.java:109)

this line :

Rss rss = apiService.getRss();

Solution

  • I have find the solution inspired from those post in stackoverflow.com: First link and Second link

    have already create new api and entities :

    The api interface :

    public interface RssAdapter{
    @GET("/storage/rss/rss/karlsruhe.xml")
    void getItems(Callback<Feed> callback);
    }
    

    Feed class :

    @Root(name = "rss", strict = false)
    public class Feed implements Serializable {
    @Element(name = "channel")
    private Channel mChannel;
    
    public Channel getmChannel() {
        return mChannel;
    }
    
    public Feed() {
    }
    
    public Feed(Channel mChannel) {
        this.mChannel = mChannel;
    }
    }
    

    and channel class:

    @Root(name = "channel", strict = false)
    public class Channel implements Serializable {
    @ElementList(inline = true, name="item")
    private List<FeedItem> mFeedItems;
    
    public List<FeedItem> getFeedItems() {
        return mFeedItems;
    }
    
    public Channel() {
    }
    
    public Channel(List<FeedItem> mFeedItems) {
        this.mFeedItems = mFeedItems;
    }
    }
    

    and the last one it's item:

    @Root(name = "item", strict = false)
    public class FeedItem implements Serializable {
    @Element(name = "pubDate")
    private String mpubDate;
    @Element(name = "title")
    private String mtitle;
    @Element(name = "link")
    private String mlink;
    @Element(name = "description")
    private String mdescription;
    
    public FeedItem() {
            }
    
    public FeedItem(String mdescription, String mlink, String mtitle, String mpubDate) {
        this.mdescription = mdescription;
        this.mlink = mlink;
        this.mtitle = mtitle;
        this.mpubDate = mpubDate;
    }
    
    public String getMpubDate() {
        return mpubDate;
    }
    
    public void setMpubDate(String mpubDate) {
        this.mpubDate = mpubDate;
    }
    
    public String getMtitle() {
        return mtitle;
    }
    
    public void setMtitle(String mtitle) {
        this.mtitle = mtitle;
    }
    
    public String getMlink() {
        return mlink;
    }
    
    public void setMlink(String mlink) {
        this.mlink = mlink;
    }
    
    public String getMdescription() {
        return mdescription;
    }
    
    public void setMdescription(String mdescription) {
        this.mdescription = mdescription;
    }
    }
    

    of course in my main activity i will put that :

    RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("http://www.ka-news.de")
                .setConverter(new SimpleXmlConverter())
                .build();
    
        RssAdapter rssAdapter = restAdapter.create(RssAdapter.class);
        rssAdapter.getItems(new Callback<Feed>() {
            @Override
            public void success(Feed newsitems, Response response) {
                Toast.makeText(getContext(), "oki", Toast.LENGTH_LONG).show();
    
    
                List<FeedItem> mItems = new ArrayList<>();
    
                mItems = newsitems.getmChannel().getFeedItems();
                // Crear un nuevo adaptador
                adapter = new AnimeAdapter(mItems);
                recycler.setAdapter(adapter);
    
            }
    
            @Override
            public void failure(RetrofitError error) {
                System.out.println(error);
    
                Toast.makeText(getContext(), "Error" + error.getMessage(),           Toast.LENGTH_LONG).show();
    
    
            }
        });
    

    and the items getting from the parsing using the retrofit api i will set on the adapter constructor to show that in the listview or RecyclerView.

    Good Luck