You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中SimpleXML反序列化Retrofit2的SOAP XML响应遇xsi/xmlns问题

嘿,我来帮你搞定这个Retrofit2处理SOAP XML响应的头疼问题!核心就是xsi实例和xmlns命名空间的处理,咱们一步步拆解解决它。

解决Retrofit2 SOAP XML反序列化问题

1. 先揪出问题根源

Retrofit默认用的是Gson这类JSON解析器,完全不兼容XML,更别说处理SOAP里的xmlns命名空间和xsi实例属性了。所以第一步必须换个XML专用的转换器,SimpleXmlConverter是Android/Java项目里最靠谱的选择。

2. 第一步:添加XML解析依赖

先在你的build.gradle(Java项目用pom.xml)里加上依赖:

// Retrofit2的SimpleXml转换器,版本和你的Retrofit版本保持一致
implementation 'com.squareup.retrofit2:converter-simplexml:2.9.0'

如果是Android项目,可能需要在AndroidManifest.xml里加一行tools:replace="android:appComponentFactory"来避免依赖冲突,先加依赖再说。

3. 给模型类加上命名空间和xsi处理注解

你的三个模型类(UsStatesResponseBody、UsStatesCPResponse、UsStatesResponseReturn)必须用SimpleXml的注解明确标注命名空间,还要处理xsi:开头的属性。我给你写个示例:

UsStatesResponseBody.class

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.Root;

@Root(name = "Envelope", strict = false) // strict=false可以忽略XML里没定义的额外元素
@Namespace(prefix = "soapenv", reference = "http://schemas.xmlsoap.org/soap/envelope/")
public class UsStatesResponseBody {
    @Element(name = "Body")
    @Namespace(prefix = "soapenv", reference = "http://schemas.xmlsoap.org/soap/envelope/")
    private UsStatesCPResponse body;

    // 别忘了加Getters和Setters
}

UsStatesCPResponse.class

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Namespace;

// 把这里的reference换成你SOAP响应里实际的命名空间URL
@Namespace(prefix = "web", reference = "http://your-target-namespace.com/")
public class UsStatesCPResponse {
    @Element(name = "getUsStatesResponse")
    private UsStatesResponseReturn responseReturn;

    // Getters和Setters
}

UsStatesResponseReturn.class

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Attribute;

public class UsStatesResponseReturn {
    // 处理xsi:type属性,required=false表示这个属性可能不存在
    @Attribute(name = "xsi:type", required = false)
    private String xsiType;

    @Element(name = "stateCode")
    private String stateCode;

    @Element(name = "stateName")
    private String stateName;

    // 其他字段和对应的Getters/Setters
}

💡 关键提醒:

  • 命名空间的URL必须和响应里的完全一致,包括大小写和结尾的斜杠
  • @Root(strict = false)能避免因为XML里有额外元素导致解析失败
  • 对于xsi:开头的属性,直接用@Attribute(name = "xsi:type")标注即可,SimpleXml会自动处理

4. 重新配置Retrofit实例,换成XML转换器

原来的Retrofit可能用的是GsonConverterFactory,现在必须换成SimpleXmlConverterFactory:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://your-soap-service-base-url.com/")
    .addConverterFactory(SimpleXmlConverterFactory.create()) // 替换成XML转换器
    .build();

如果你的XML里有CDATA内容,还需要额外配置:

// 配置支持CDATA的序列化器
Serializer serializer = new Persister(new AnnotationStrategy());
SimpleXmlConverterFactory factory = SimpleXmlConverterFactory.create(serializer);

// 用这个factory创建Retrofit
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://your-soap-service-base-url.com/")
    .addConverterFactory(factory)
    .build();

5. 检查你的Retrofit接口定义

确保接口正确配置了SOAP请求的头部和请求体:

public interface SoapService {
    @POST("/your-soap-endpoint-path")
    @Headers({
        "Content-Type: text/xml; charset=utf-8",
        // 替换成你服务实际要求的SOAPAction,有些需要加引号,有些不需要
        "SOAPAction: \"http://your-target-namespace.com/getUsStates\""
    })
    Call<UsStatesResponseBody> getUsStates(@Body RequestBody soapRequest);
}

6. 常见坑点排查

  • 命名空间的URL一定要和响应里的完全匹配,别漏了斜杠或者大小写错误
  • 如果响应里有默认命名空间(没有前缀),直接用@Namespace(reference = "http://...")不要指定prefix
  • 如果xsi:type是复杂类型,可能需要自定义转换器或者用@ElementUnion处理不同类型的返回
  • 模型类的字段名要和XML标签名完全一致,包括大小写

内容的提问来源于stack exchange,提问作者Mahdi Azadbar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:37:36