使用Retrofit 2将根单个元素添加到xml

时间:2016-11-09 06:34:43

标签: android xml retrofit2 simple-xml-converter

我在xml中有一个服务器响应,格式不正确且没有根元素:

<option value="stationAValue">stationADescription</option>
<option value="stationBValue">stationBDescription</option>

我试图像这样使用SimpleXmlConverterFactory

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(Params.BASE_URL)
    .client(okHttpClient)
    .addConverterFactory(SimpleXmlConverterFactory.create())
    .build();

这是我的代表一行的类:

public class Station {
    @Element(name = "option")
    private String mName;

   @Attribute(required = false)
   private String value;
}

但当然不能在没有根元素的情况下解析它, 有没有办法在SimpleXmlConverterFactory尝试解析响应之前操纵响应,并添加根元素?

或许是另一种解决方案?

2 个答案:

答案 0 :(得分:3)

使用Retrofit / OkHttp,您有2个拦截这些请求的选项:

  • 使用带有OkHttp的拦截器并直接修改响应/请求
  • 包装解析器并在传递响应之前修改响应

两者都有点装饰模式。

使用拦截器

直接将响应修改为http堆栈的一部分:

public class XmlInterceptor implements Interceptor {
  @Override
  public Response intercept(Chain chain) throws IOException {
    Response response = chain.proceed(chain.request());
    ResponseBody body = response.body();
    String wrappedBody = "<root>" + body.string() + "</root>";
    return response.newBuilder()
            .body(ResponseBody.create(body.contentType(), wrappedBody))
            .build();
  }
}

只需将拦截器添加到OkHttp

即可
new OkHttpClient.Builder()
    .addInterceptor(new XmlInterceptor())
    .build();

使用包装解析器

包装您要使用的解析器,然后再次修改响应。这里的好处是,您可以为包装添加自定义注释。例如传入根元素的名称。

public class XmlParser extends Converter.Factory {

  private Converter.Factory factory = SimpleXmlConverterFactory.create();

  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
    // here you can actually look at the annotations, type, etc.
    return new WrappedResponseBodyConverter(factory.responseBodyConverter(type, annotations, retrofit));
  }

  private class WrappedResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private Converter<ResponseBody, T> responseBodyConverter;

    public WrappedResponseBodyConverter(Converter<ResponseBody, T> responseBodyConverter) {
      this.responseBodyConverter = responseBodyConverter;
    }

    @Override
    public T convert(ResponseBody value) throws IOException {
      String body = "<root>" + value.string() + "</root>";
      ResponseBody wrapped = ResponseBody.create(value.contentType(), body);
      return responseBodyConverter.convert(value);
    }
  }
}

然后使用这个。

new Retrofit.Builder()
    .addConverterFactory(new XmlParser())
    .build();

选择您喜欢的任何一种,因为没有正确或错误的imho。

代码未经过测试。这只是一个例子。

答案 1 :(得分:-1)

I have done something almost similar to your current ptoblem. Once you receive the xml response in java, you can use + operation to include you root element, like so :

String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<root>" + response + "</root>";

here, response is the xml response you get you get in String format. Note that you can also manipulate the xml respose to suit your needs by treating it as a string, so you can concat any additional data into your response and you can also split the response at different parts to suit the format that you require. Hope this will assist.