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

Add root single element to xml using Retrofit 2

我在 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();

这是我的 class 代表一行:

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

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

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

或者其他解决方案?

我已经做了一些与你目前的问题几乎相似的事情。在 java 中收到 xml 响应后,您可以使用 + 操作来包含您的根元素,如下所示:

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

此处,response 是您获得的 xml 字符串格式的响应。请注意,您还可以通过将 xml 响应视为字符串来操纵它以满足您的需要,因此您可以将任何其他数据连接到您的响应中,您还可以将响应拆分为不同的部分以适合您的格式要求。希望这会有所帮助。

使用 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();

选择你喜欢的,没有对错之分恕我直言。


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