Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Volley adapter for making XML Requests. It uses Simple-XML for serializing XML to Objects (http://simple.sourceforge.net/). Code is based of GsonRequest. Hope someone finds it useful.
import java.io.UnsupportedEncodingException;
import java.util.Map;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
/**
* Simple Volley Class for doing XML HTTP Requests which are parsed
* into Java objects by Simple @see {{@link http://simple.sourceforge.net/}
*/
public class SimpleXmlRequest<T> extends Request<T> {
private static final Serializer serializer = new Persister();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Listener<T> listener;
/**
* Make HTTP request and return a parsed object from Response
* Invokes the other constructor.
*
* @see SimpleXmlRequest#SimpleXmlRequest(int, String, Class, Map, Listener, ErrorListener)
*/
public SimpleXmlRequest(int method, String url, Class<T> clazz,
Listener<T> listener, ErrorListener errorListener) {
this(method, url, clazz, null, listener, errorListener);
}
/**
* Make HTTP request and return a parsed object from XML Response
*
* @param url URL of the request to make
* @param clazz Relevant class object
* @param headers Map of request headers
* @param listener
* @param errorListener
*
*/
public SimpleXmlRequest(int method, String url, Class<T> clazz, Map<String, String> headers,
Listener<T> listener, ErrorListener errorListener) {
super(method, url, errorListener);
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
@Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response)
{
try {
String data = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(serializer.read(clazz, data),
HttpHeaderParser.parseCacheHeaders(response));
}
catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
catch (Exception e) {
return Response.error(new VolleyError(e.getMessage()));
}
}
}
@itsalif

This comment has been minimized.

Copy link
Owner Author

commented Aug 4, 2013

Briefly, how to use:

Suppose, you have the XML Response:
http://www.w3schools.com/xml/note.xml

And a corresponding POJO Class (Note.java):

Then, simply use it as follows:

SimpleXmlRequest<Note> simpleRequest = new SimpleXmlRequest<Note>(Request.Method.GET, url, Note.class,  
    new Response.Listener<Note>() 
    {
        @Override
        public void onResponse(Note response) {
            // response Object

        }
    }, 
    new Response.ErrorListener() 
    {
         @Override
         public void onErrorResponse(VolleyError error) {                                
            // error Object
       }
    }
);  
@kingargyle

This comment has been minimized.

Copy link

commented Jan 30, 2014

Just wanted to drop a note and say this works very well. Much quicker than using StringRequest. Using this in Serenity for Android now.

@itsalif

This comment has been minimized.

Copy link
Owner Author

commented Feb 11, 2014

Thanks for your note. I assume Serenity for Android as in the Media App (https://play.google.com/store/apps/details?id=us.nineworlds.serenity)

Thats awesome!

@rdjondo

This comment has been minimized.

Copy link

commented Mar 11, 2014

I tried your method on an XML containing international characters (non english). That reveals that the encoding of the xml (utf-8) might differ from the http response itself.
A solution that seems to work, at least in my case, is to pass into the serializer (Persister object) a ByteArrayInputStream instead of a String.
This seems to work better in handling international characters.
Thanks

@nitrico

This comment has been minimized.

Copy link

commented Apr 2, 2014

Thanks for the class!

@pumathecapoeirist what I did for dealing with international chararacters was

 //String data = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
 String data = new String(response.data,"UTF-8");

on parseNetworkResponse method

@itsalif

This comment has been minimized.

Copy link
Owner Author

commented Apr 25, 2014

Thanks @nitrico for the solution.

@whowazit

This comment has been minimized.

Copy link

commented May 10, 2014

(method, url, clazz, listener, errorListener) .. i tried to use this but i don't know what to put in "clazz" .. pls tell me ..tha nk you

@itsalif

This comment has been minimized.

Copy link
Owner Author

commented May 10, 2014

@whowazit

In class, you need to put the POJO's class name (the class name of the Generic you are going to use). See my first comment (Briefly how to use..).

If you have a POJO Note.java - http://www.w3schools.com/xml/note.xml. Then, call the constructor like this:

SimpleXmlRequest<Note> simpleRequest = new SimpleXmlRequest<Note>(Request.Method.GET, url, 
             Note.class, ... ..)
@ssadan

This comment has been minimized.

Copy link

commented May 15, 2014

can you create pojo for kxml

@itsalif

This comment has been minimized.

Copy link
Owner Author

commented May 20, 2014

I am not sure as I have not used kxml, but there should be serializers for kxmls.

@vibin

This comment has been minimized.

Copy link

commented Jun 6, 2014

I'm not entirely clear about the POJO parameter in the constructor new SimpleXmlRequest<Note>(Request.Method.GET, url, Note.class...)

I created a java class called Note and it's empty right now. What should I put in it?

@itsalif

This comment has been minimized.

Copy link
Owner Author

commented Jun 6, 2014

Hello @vibinr,

The POJO is simply a class whose attributes & methods would map to the XML structure. Have a look at some of the examples here:
http://simple.sourceforge.net/download/stream/doc/examples/examples.php

@vibin

This comment has been minimized.

Copy link

commented Jun 7, 2014

I'll take a look, thank you!

@vibin

This comment has been minimized.

Copy link

commented Jun 7, 2014

I'm trying to create a POJO for this XML - http://www1.billboard.com/rss/charts/hot-100

The only data I want is <title>, <link>, <description> - inside each item

The file looks like this now and obviously doesn't work yet, can you guide me a bit please?

@Root(name="rss") //root of the xml file
public class Note {
    @ElementList(name="channel")
    private List channel;

    @Root(name="item")
    public class item{
        @ElementUnion({
                @Element(name = "title", type = String.class),
                @Element(name = "link", type = String.class),
                @Element(name = "description", type = String.class)
        })
        private Object value;
    }
}
@gvsharma

This comment has been minimized.

Copy link

commented Sep 10, 2014

thats awesome..

@matzrm

This comment has been minimized.

Copy link

commented Sep 10, 2014

Hi,

thank you for share with us your code.
I have some problems to build my POJO class. Can you share your own?

Thank you.
Mattia

@rdiaz82

This comment has been minimized.

Copy link

commented Oct 27, 2014

Hi!!

This is a very nice piece of code, it works perfect!!. I just added a simple modification to support allow to add parameters to the request:

public class SimpleXmlRequest extends Request {

private static final Serializer serializer = new Persister();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Listener<T> listener;
private final Map<String, String> parameters;


/**
 * Make HTTP request and return a parsed object from Response
 * Invokes the other constructor.
 *
 * @see SimpleXmlRequest#SimpleXmlRequest(int, String, Class, Map, Listener, ErrorListener)
 */
public SimpleXmlRequest(int method, String url, Class<T> clazz,Map<String, String> parameters,
                        Listener<T> listener,ErrorListener errorListener) {
    this(method, url, clazz, null, parameters, listener, errorListener);
}


/**
 * Make HTTP request and return a parsed object from XML Response
 *
 * @param url           URL of the request to make
 * @param clazz         Relevant class object
 * @param headers       Map of request headers
 * @param listener
 * @param errorListener
 */
public SimpleXmlRequest(int method, String url, Class<T> clazz, Map<String, String> headers,
                        Map<String, String> parameters,Listener<T> listener, ErrorListener errorListener) {
    super(method, url, errorListener);
    this.clazz = clazz;
    this.headers = headers;
    this.listener = listener;
    this.parameters = parameters;

}


@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    return headers != null ? headers : super.getHeaders();
}

@Override
protected Map<String, String> getParams() throws AuthFailureError {
    return this.parameters != null ? parameters : super.getParams();
}

@Override
protected void deliverResponse(T response) {
    listener.onResponse(response);
}


@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
    try {

        String data = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        Utils.log(data);
        return Response.success(serializer.read(clazz, data),
                HttpHeaderParser.parseCacheHeaders(response));
    } catch (UnsupportedEncodingException e) {
        return Response.error(new ParseError(e));
    } catch (Exception e) {
        return Response.error(new VolleyError(e.getMessage()));
    }
}

}

@Motoharujap

This comment has been minimized.

Copy link

commented Nov 8, 2014

Thank you for wonderful class! I'm trying to use this actually. Could you please clarify one thing? What the Response exactly is? How does it look like? The thing is, when I used SAX parser I was able to get a list of (as it is for your example) Note objects, so I could use a loop to get items from it. But now I have only that request, and Im not able to get anything from it cause I don't exactly know what does it look like, so could you please help me?

@fparkar

This comment has been minimized.

Copy link

commented Dec 24, 2014

Could you please share Note.java? I am having hard time to create needed Note.java file.

I made simple with getter and setter, but still it don't works

For link http://api.androidhive.info/music/music.xml, I have my java file as below.

@Root(name = "music")
public class XMLMovie {

@ElementList(inline = true, data = false, empty = true, entry = "", name = "", required = false, type = void.class)
ArrayList<song> mSong;

public ArrayList<song> getmSong() {
    return mSong;
}

public void setmSong(ArrayList<song> mSong) {
    this.mSong = mSong;
}

@Root(name = "song")
public static class song {
    @Element(data = false, name = "", required = false, type = String.class)
    String title;
    @Element(data = false, name = "", required = false, type = String.class)
    String artist;
    @Element(data = false, name = "", required = false, type = String.class)
    String duration;
    @Element(data = false, name = "", required = false, type = String.class)
    String thumb_url;

    public String getTitle() {
        return title;
    }

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

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getDuration() {
        return duration;
    }

    public void setDuration(String duration) {
        this.duration = duration;
    }

    public String getThumb_url() {
        return thumb_url;
    }

    public void setThumb_url(String thumb_url) {
        this.thumb_url = thumb_url;
    }
}
}
@allanfallas

This comment has been minimized.

Copy link

commented Mar 10, 2015

A POJO class who works with this XML:
http://www.w3schools.com/xml/note.xml

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
@root(name="note",strict = false)
public class Usuario {

@Element(name = "to", required = false)
private String to;
@Element(name = "from", required = false)
private String from;
@Element(name = "heading", required = false)
private String heading;
@Element(name = "body", required = false)
private String body;

public String getTo(){
    return to;
}

public String getFrom() {
    return from;
}

public String getHeading() {
    return heading;
}

public String getBody() {
    return body;
}

}

If you need to work with a list, then read this:
http://stackoverflow.com/questions/18317273/deserializing-with-simplexml

@ArcturusArc

This comment has been minimized.

Copy link

commented Mar 24, 2015

Hello guys, I want to handle this xml file

<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0"> 

    <channel>
        <title>...</title>
        <atom:link href="..." rel="self" type="application/rss+xml"/>
        <link>...</link>
        <description>...</description>
        <lastBuildDate>Mon, 23 Mar 2015 14:17:24 +0000</lastBuildDate>
        <language>en-US</language>
        <sy:updatePeriod>hourly</sy:updatePeriod>
        <sy:updateFrequency>1</sy:updateFrequency>
        <generator>...</generator>
            <item>
                <title>...</title>
                <link>...</link>
                <comments>...</comments>
                <pubDate>...</pubDate>
                <dc:creator><![CDATA[ ... ]]></dc:creator>
                <category><![CDATA[ ... ]]></category>
                <category><![CDATA[ ... ]]></category>
                <category><![CDATA[ ... ]]></category>
                <category><![CDATA[ ... ]]></category>
                <category><![CDATA[ ... ]]></category>
                <guid isPermaLink="false">...</guid>
                <description><![CDATA[<img width="740" height="493" src="HTTP://...jpg"             class="attachment- wp-post-image" alt="DSC" style="float:left; margin:0 15px 15px 0;" /> ... ]]>
                </description>
                <content:encoded>
                <![CDATA[<img width="740" height="493" src="http://...jpg" class="attachment- wp-post-image" alt="DSC" style="float:left; margin:0 15px 15px 0;" /> bla bla...
]]>
                </content:encoded>
                <wfw:commentRss>...</wfw:commentRss>
                <slash:comments>0</slash:comments>
            </item>
            <item>
            ....
            </item>
</rss>

I want to get the<title> from the <item>and the src="..." from the <description> please tell me how to do that with your class. And how it has to be the POJO class?
I tried what allanfallas said but no success.
Can someone help me?

@ArcturusArc

This comment has been minimized.

Copy link

commented Apr 1, 2015

Hi,
I when I am running my app I am getting this

I/dalvikvm﹕ Could not find method javax.xml.stream.XMLInputFactory.newInstance, referenced from method org.simpleframework.xml.stream.StreamProvider.<init>
W/dalvikvm﹕ VFY: unable to resolve static method 14456: Ljavax/xml/stream/XMLInputFactory;.newInstance ()Ljavax/xml/stream/XMLInputFactory; 
W/dalvikvm﹕ VFY: unable to find class referenced in signature (Ljavax/xml/stream/XMLEventReader;)
W/dalvikvm﹕ VFY: unable to find class referenced in signature (Ljavax/xml/stream/XMLEventReader;)
I/dalvikvm﹕ Could not find method javax.xml.stream.XMLInputFactory.createXMLEventReader, referenced from method org.simpleframework.xml.stream.StreamProvider.provide
VFY: unable to resolve virtual method 14453: Ljavax/xml/stream/XMLInputFactory;.createXMLEventReader (Ljava/io/InputStream;)Ljavax/xml/stream/XMLEventReader;
Could not find method javax.xml.stream.XMLInputFactory.createXMLEventReader, referenced from method org.simpleframework.xml.stream.StreamProvider.provide
VFY: unable to resolve virtual method 14454: Ljavax/xml/stream/XMLInputFactory;.createXMLEventReader (Ljava/io/Reader;)Ljavax/xml/stream/XMLEventReader;

Is this because I don't use stax-1.2.0.jar , stax-api-1.0.1.jar , xpp3-1.1.3_8.jar ?

@brunocasteleiro

This comment has been minimized.

Copy link

commented Jul 2, 2015

For the ones having the same problem as @ArcturusArc (just above me), you don't really need to worry about those messages.. if you want to know why, here you have a good reading https://robertmassaioli.wordpress.com/2011/04/21/simple-xml-in-android-1-5-and-up/ .

The first time I used this SimpleXMLRequest class I was getting those messages too, and I though that they were the reason why I wasn't getting the serialized object I wanted from the request. Anyway, I was wrong, I just forgot to define some attributes in my POJO's, so please make sure your POJO's are well defined too.

A quick note to itsalif.. This class works very well, thanks for sharing!

@LadyWendy

This comment has been minimized.

Copy link

commented Jan 8, 2016

Hi,
how can I send xml data using volley?

@kapoorgautam90

This comment has been minimized.

Copy link

commented Aug 29, 2016

untitled

How to send xml request in volley as mentioned in above picture ?

@PrachiKarapurkar

This comment has been minimized.

Copy link

commented Sep 13, 2016

Hello ,
I have following response

<APIGetCitiesResponse xmlns="http://tempuri.org/">
    <APIGetCitiesResult xmlns:a="http://schemas.datacontract.org/2004/07/CRS2011AgentApi" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:CityPair>
            <a:FromCityID>1</a:FromCityID>
            <a:FromCityName>Ahmedabad</a:FromCityName>
            <a:ToCityID>10</a:ToCityID>
            <a:ToCityName>Amreli</a:ToCityName>
        </a:CityPair>
        <a:CityPair>
            <a:FromCityID>1</a:FromCityID>
            <a:FromCityName>Ahmedabad</a:FromCityName>
            <a:ToCityID>57</a:ToCityID>
            <a:ToCityName>Ankleshwar</a:ToCityName>
        </a:CityPair>
</APIGetCitiesResult>
</APIGetCitiesResponse>

How to handle it ??

@PrachiKarapurkar

This comment has been minimized.

Copy link

commented Sep 13, 2016

Can anybody help me out??.. its urgent : (

@milon87

This comment has been minimized.

Copy link

commented Feb 16, 2017

how to send POST request with XML parameter? TIA

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.