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

如何解决调用SOAP接口时出现的XmlPullParserException?

解决SOAP调用返回JSON导致的XmlPullParserException问题

你这明显是踩了个“协议不匹配”的坑:你用ksoap2按照SOAP协议发送请求,但接口实际返回的是纯JSON格式数据,而ksoap2的HttpTransportSE默认会把响应当作SOAP XML来解析,这就直接触发了XmlPullParserException——它预期看到XML标签,结果拿到的是JSON的{符号,自然直接报错崩溃。

问题根源

你的代码里,androidHttpTransportSE.call(SOAP_ACTION, envelope)这一行会自动尝试将服务器响应解析为SOAP Envelope,但服务器返回的是JSON,完全不符合SOAP规范的XML结构,所以解析过程直接失败,根本执行不到后续处理JSON的代码段。

解决方案:绕过ksoap2的自动解析,手动获取原始响应

我们需要跳过ksoap2的XML解析步骤,直接获取服务器返回的原始JSON字符串,再自行处理JSON解析。这里提供两种可行的实现方式:

方式1:修改HttpTransportSE的使用逻辑,获取原始响应

利用HttpTransportSE的底层连接能力,跳过自动解析步骤,直接读取响应流:

@Override
protected String doInBackground(String... params) {
    String result = "";
    try {
        // 构建SOAP请求体
        SoapObject request = new SoapObject(SOAP_NAMESPACE, SOAP_METHOD);
        request.addProperty("labcode", mLabCode.getText().toString());
        request.addProperty("username", mUserName.getText().toString());
        request.addProperty("pass", mPasswordView.getText().toString());
        
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.setOutputSoapObject(request);
        envelope.dotNet = true;

        HttpTransportSE androidHttpTransportSE = new HttpTransportSE(URL);
        // 发送请求但跳过自动解析(第三个参数设为false)
        androidHttpTransportSE.call(SOAP_ACTION, envelope, false);
        
        // 读取原始响应流
        InputStream inputStream = androidHttpTransportSE.getServiceConnection().getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        result = sb.toString();
        reader.close();
        inputStream.close();

        // 处理JSON(注意:根据报错日志,返回的是JSONObject而非JSONArray)
        Log.e("Test Result", result);
        try {
            JSONObject jsonObject = new JSONObject(result);
            strStatusID = jsonObject.getString("Flag");
            labCode = jsonObject.getString("LabCode");
            userName = jsonObject.getString("Username");
            Log.e("Flag", strStatusID);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

方式2:直接用原生HttpURLConnection发送SOAP请求

如果觉得ksoap2的封装限制太多,也可以用原生HttpURLConnection手动构造SOAP XML请求,再读取JSON响应:

@Override
protected String doInBackground(String... params) {
    String result = "";
    try {
        // 手动构造SOAP请求XML
        String soapRequest = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns=\"" + SOAP_NAMESPACE + "\">" +
                "<soap:Body>" +
                "<ns:" + SOAP_METHOD + ">" +
                "<ns:labcode>" + mLabCode.getText().toString() + "</ns:labcode>" +
                "<ns:username>" + mUserName.getText().toString() + "</ns:username>" +
                "<ns:pass>" + mPasswordView.getText().toString() + "</ns:pass>" +
                "</ns:" + SOAP_METHOD + ">" +
                "</soap:Body>" +
                "</soap:Envelope>";

        URL url = new URL(URL);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
        conn.setRequestProperty("SOAPAction", SOAP_ACTION);
        conn.setDoOutput(true);

        // 发送SOAP请求
        OutputStream os = conn.getOutputStream();
        os.write(soapRequest.getBytes("UTF-8"));
        os.flush();
        os.close();

        // 读取响应内容
        InputStream inputStream = conn.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        result = sb.toString();
        reader.close();
        inputStream.close();
        conn.disconnect();

        // 解析JSON
        Log.e("Test Result", result);
        try {
            JSONObject jsonObject = new JSONObject(result);
            strStatusID = jsonObject.getString("Flag");
            labCode = jsonObject.getString("LabCode");
            userName = jsonObject.getString("Username");
            Log.e("Flag", strStatusID);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

额外提醒

  • 确认JSON格式:从报错日志看,服务器返回的是{ "Flag": 1, ...}这种单个对象,不是JSON数组,所以原来代码里用JSONArray解析会触发JSONException,记得改成JSONObject。
  • 提前验证响应:建议先用Postman之类的工具发送相同的SOAP请求,确认服务器返回的确实是纯JSON,而非包裹在SOAP Envelope里的JSON内容。

内容的提问来源于stack exchange,提问作者Afsal .Kritisoft

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:18:14