使用 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();
选择你喜欢的,没有对错之分恕我直言。
代码未经测试。这只是一个例子。
我在 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();
选择你喜欢的,没有对错之分恕我直言。
代码未经测试。这只是一个例子。