J'utilise Retrofit 2.1.0 et Retrofit SimpleXML Converter 2.1.0 . J'ai ajouté simplexmlconverter pour adapter l'instance à la méthode addConverterFactory.
XML est ci-dessous
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:iTunes="http://www.iTunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<title>title</title>
<description></description>
<language>en-us</language>
<item>
<title>text</title>
<link>text</link>
<description>text</description>
<Enclosure url="text" length="2043520" type="image/jpeg" />
<guid isPermaLink="false">text</guid>
<pubDate>Fri, 17 Jun 2016 11:43 EDT</pubDate>
<source url="text">text</source>
</item>
<item>
<title>text</title>
<link>text</link>
<description>text</description>
<Enclosure url="text" length="1735257" type="image/jpeg" />
<guid isPermaLink="false">text</guid>
<pubDate>Thu, 16 Jun 2016 10:17 EDT</pubDate>
<source url="text"></source>
</item>
<item>
<title>text</title>
<link>text</link>
<description>text</description>
<Enclosure url="text" length="3763157" type="image/jpeg" />
<guid isPermaLink="false">text</guid>
<pubDate>Wed, 15 Jun 2016 10:02 EDT</pubDate>
<source url="text">text</source>
</item>
</channel>
</rss>
Code pertinent pour mon client api de modification: RetrofitAPIClient
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
apiService = retrofit.create(MyService.class);
ArticleResponse.Java
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import Java.util.List;
@Root(name = "rss")
public class ArticleResponse {
@Element(name = "channel")
public Channel channel;
public class Channel {
@ElementList
public List<Article> articles;
}
}
Article.Java
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Text;
@Element(name = "item")
public class Article {
@Element(name = "title")
private String title;
@Element(name = "link")
private String link;
@Element(name = "description")
private String description;
@Element(name = "Enclosure")
private Enclosure enclosure;
@Element(name = "guid")
private String guid;
@Element(name = "pubDate")
private String pubDate;
@Element(name = "source")
private Source source;
public class Enclosure {
@Attribute(name = "url")
private String url;
@Attribute(name = "length")
private long length;
@Attribute(name = "type")
private String type;
}
public class Source {
@Attribute(name = "url")
private String url;
@Text
private String text;
}
}
L'erreur est:
06-18 20:31:22.894 W/System.err: Java.lang.RuntimeException: org.simpleframework.xml.core.AttributeException: Attribute 'version' does not have a match in class [my-package].webservice.response.ArticleResponse at line 1
06-18 20:31:22.894 W/System.err: at retrofit2.converter.simplexml.SimpleXmlResponseBodyConverter.convert(SimpleXmlResponseBodyConverter.Java:44)
06-18 20:31:22.894 W/System.err: at retrofit2.converter.simplexml.SimpleXmlResponseBodyConverter.convert(SimpleXmlResponseBodyConverter.Java:23)
06-18 20:31:22.894 W/System.err: at retrofit2.ServiceMethod.toResponse(ServiceMethod.Java:116)
06-18 20:31:22.894 W/System.err: at retrofit2.OkHttpCall.parseResponse(OkHttpCall.Java:211)
06-18 20:31:22.894 W/System.err: at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.Java:106)
06-18 20:31:22.894 W/System.err: at okhttp3.RealCall$AsyncCall.execute(RealCall.Java:133)
06-18 20:31:22.894 W/System.err: at okhttp3.internal.NamedRunnable.run(NamedRunnable.Java:32)
06-18 20:31:22.894 W/System.err: at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1112)
06-18 20:31:22.894 W/System.err: at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:587)
06-18 20:31:22.894 W/System.err: at Java.lang.Thread.run(Thread.Java:818)
06-18 20:31:22.894 W/System.err: Caused by: org.simpleframework.xml.core.AttributeException: Attribute 'version' does not have a match in class [my-package].webservice.response.ArticleResponse at line 1
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Composite.readAttribute(Composite.Java:494)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Composite.readAttributes(Composite.Java:413)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Composite.access$300(Composite.Java:59)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Composite$Builder.read(Composite.Java:1382)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Composite.read(Composite.Java:201)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Composite.read(Composite.Java:148)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Traverser.read(Traverser.Java:92)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Persister.read(Persister.Java:625)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Persister.read(Persister.Java:606)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Persister.read(Persister.Java:584)
06-18 20:31:22.895 W/System.err: at org.simpleframework.xml.core.Persister.read(Persister.Java:543)
06-18 20:31:22.895 W/System.err: at retrofit2.converter.simplexml.SimpleXmlResponseBodyConverter.convert(SimpleXmlResponseBodyConverter.Java:36)
06-18 20:31:22.895 W/System.err: ... 9 more
Essayez avec strict = false
:
@Root(name = "rss", strict = false)
public class ArticleResponse {
@Element(name = "channel")
public Channel channel;
public class Channel {
@ElementList
public List<Article> articles;
}
}
Face à un même problème. La solution consiste à rendre la classe interne statique (ou simplement à créer une nouvelle classe Java unique). Ajoutez également une annotation "racine" pour le nœud "canal".
@Root(name = "rss", strict = false)
public class ArticleResponse {
@Element(name = "channel")
private Channel channel;
@Root(name = "channel", strict = false)
static class Channel {
@ElementList(inline = true, name="item")
private List<Article> articles;
}
}
Idem avec les nœuds "Enclosure" et "source" - créez un nouveau fichier ou créez une classe interne statique.
public class Enclosure {
@Attribute(name = "url")
private String url;
@Attribute(name = "length")
private long length;
@Attribute(name = "type")
private String type;
}
Vous voyez cela parce que l'annotation de l'attribut "default" dans votre document XML est manquante.
Le comportement par défaut de SimpleXML est de définir (strict = true), ce qui signifie que vous devez annoter TOUS les éléments et attributs de votre document. Dans le cas contraire, il lève l'exception d'exécution que vous voyez.
Donc, pour l'exemple XML ci-dessous:
<response xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XML-Schema-instance" version="1.2">
<sample_string>Brady</sample_string>
<sample_integer>12</sample_integer>
</response>
Vous devez soit utiliser l'indicateur (strict = false) pour ignorer l'attribut "version":
@Root(strict = false)
public class Response {
@Element(name = "sample_string")
private String sampleString;
@Element(name = "sample_integer")
private Integer sampleInteger;
public String getSampleString() {
return sampleString;
}
public Integer getSampleInteger() {
return sampleInteger;
}
}
OU, annotez l'attribut "version" dans votre classe:
@Root
public class Response {
@Attribute(name = "version")
private String version;
@Element(name = "sample_string")
private String sampleString;
@Element(name = "sample_integer")
private Integer sampleInteger;
public String getVersion() {
return version;
}
public String getSampleString() {
return sampleString;
}
public Integer getSampleInteger() {
return sampleInteger;
}
}