web-dev-qa-db-ja.com

Android Retrofit 2 Simple XML Converter

Retrofit 2.1.とRetrofit SimpleXML Converter 2.1.を使用しています。 addConverterFactoryメソッドを使用して、simplexmlconverterをレトロフィットインスタンスに追加しました。

XMLは以下です

<?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>

私の改造APIクライアント関連コード: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;
    }
}

エラーは:

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
10
okarakose

strict = falseでお試しください:

@Root(name = "rss", strict = false)
public class ArticleResponse {

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

    public class Channel {

        @ElementList
        public List<Article> articles;
    }
}
4
KERiii

これが表示されるのは、XMLドキュメントの「デフォルト」属性のアノテーションが欠落しているためです。

SimpleXMLのデフォルトの動作は設定(strict = true)です。つまり、ドキュメント内のすべての要素と属性に注釈を付ける必要があります。そうしないと、表示されているランタイム例外がスローされます。

したがって、以下のサンプルXMLの場合:

<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>

「version」属性を無視するには、(strict = false)フラグを使用する必要があります。

@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;
    }
}

または、クラスの「バージョン」属性に注釈を付けます。

@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;
    }
}
3
FrostRocket

同じ問題に直面しました。解決策は、内部クラスを静的にすることです(または単に単一のJavaクラスを作成します)。また、「チャネル」ノードに「ルート」アノテーションを追加します。

@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;
  }

}

「エンクロージャー」ノードおよび「ソース」ノードと同じ-新しいファイルを作成するか、静的内部クラスを作成します。

public class Enclosure {

    @Attribute(name = "url")
    private String url;

    @Attribute(name = "length")
    private long length;

    @Attribute(name = "type")
    private String type;
}
2
user5257758