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

如何在Retrofit+SimpleXmlConverter中解析不同结构的XML响应?

这个问题我之前也碰到过,API返回不同根节点的XML确实会让SimpleXmlConverter直接抛出结构不匹配的异常,给你两种实用的解决方案:

方案一:创建通用包装模型类,包含成功和错误响应

这种方式最直观,我们定义一个能同时容纳Success和Error节点的通用模型,关闭严格解析模式来兼容不同的根节点:

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

@Root(name = "Response", strict = false)
public class GeneralResponse {
    // 标记为非必填,因为只会返回其中一个节点
    @Element(name = "Success", required = false)
    private SuccessModel success;
    
    @Element(name = "Error", required = false)
    private ErrorModel error;

    // 判断是否为成功响应
    public boolean isSuccess() {
        return success != null;
    }

    // Getter方法
    public SuccessModel getSuccess() {
        return success;
    }

    public ErrorModel getError() {
        return error;
    }

    // 内部类定义成功响应模型
    @Root(name = "Success")
    public static class SuccessModel {
        @Element
        private String id;

        public String getId() {
            return id;
        }
    }

    // 内部类定义错误响应模型
    @Root(name = "Error")
    public static class ErrorModel {
        @Element
        private String message;

        public String getMessage() {
            return message;
        }
    }
}

使用时,Retrofit接口返回Call<GeneralResponse>,在回调里判断响应类型即可:

call.enqueue(new Callback<GeneralResponse>() {
    @Override
    public void onResponse(Call<GeneralResponse> call, Response<GeneralResponse> response) {
        if (response.isSuccessful()) {
            GeneralResponse resp = response.body();
            if (resp.isSuccess()) {
                // 处理成功逻辑,获取id
                String id = resp.getSuccess().getId();
            } else {
                // 处理错误逻辑,展示错误信息
                String errorMsg = resp.getError().getMessage();
            }
        } else {
            // 处理HTTP错误(如404、500等),可解析errorBody获取详细信息
            try {
                String errorXml = response.errorBody().string();
                // 用同样的GeneralResponse解析errorXml
                GeneralResponse errorResp = new Persister().read(GeneralResponse.class, errorXml);
                String errorMsg = errorResp.getError().getMessage();
            } catch (IOException | Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onFailure(Call<GeneralResponse> call, Throwable t) {
        // 处理网络失败等异常
    }
});
方案二:利用@Root的alternate属性实现多根节点解析

这种方式更偏向面向对象,通过抽象父类+子类的方式,让SimpleXml支持解析多个根节点:

首先定义抽象父类和两个响应子类:

import org.simpleframework.xml.Root;

@Root(alternate = {SuccessResponse.class, ErrorResponse.class})
public abstract class BaseResponse {
}
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root(name = "Success")
public class SuccessResponse extends BaseResponse {
    @Element
    private String id;

    public String getId() {
        return id;
    }
}
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root(name = "Error")
public class ErrorResponse extends BaseResponse {
    @Element
    private String message;

    public String getMessage() {
        return message;
    }
}

然后Retrofit接口返回Call<BaseResponse>,在回调里通过instanceof判断具体类型:

call.enqueue(new Callback<BaseResponse>() {
    @Override
    public void onResponse(Call<BaseResponse> call, Response<BaseResponse> response) {
        if (response.isSuccessful()) {
            BaseResponse resp = response.body();
            if (resp instanceof SuccessResponse) {
                String id = ((SuccessResponse) resp).getId();
                // 处理成功逻辑
            } else if (resp instanceof ErrorResponse) {
                String errorMsg = ((ErrorResponse) resp).getMessage();
                // 处理错误逻辑
            }
        } else {
            // 同样处理HTTP错误,解析errorBody
            try {
                String errorXml = response.errorBody().string();
                BaseResponse errorResp = new Persister().read(BaseResponse.class, errorXml);
                if (errorResp instanceof ErrorResponse) {
                    String errorMsg = ((ErrorResponse) errorResp).getMessage();
                }
            } catch (IOException | Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onFailure(Call<BaseResponse> call, Throwable t) {
        // 处理网络异常
    }
});
额外配置提醒

确保你的Retrofit已经正确配置了SimpleXmlConverterFactory,若需要宽松解析(比如忽略未知元素),可以用createNonStrict():

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("你的API基础地址")
        .addConverterFactory(SimpleXmlConverterFactory.createNonStrict())
        .build();

内容的提问来源于stack exchange,提问作者andro-girl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:58:17