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

如何在R和Python中解析XML MTOM格式的SOAP响应

MTOM格式SOAP响应解析方案(Python+R)

核心逻辑

  • 收到的application/xop+xml类型响应属于MTOM封装的MIME多部分消息,需先拆分多部分内容提取SOAP XML片段,无法直接用常规XML库解析
  • SOAP报文体中的业务数据为HTML转义后的XML字符串,需完成反转义后才能解析内层业务字段

Python 实现

方案1:内置库手动解析(无需额外SOAP客户端)

依赖Python标准库即可完成解析,无需安装第三方SOAP框架:

import html
import xml.etree.ElementTree as ET
from email import policy
from email.parser import BytesParser

# 此处替换为你实际拿到的响应原始字节内容,若用requests发请求则为response.content
response_content = b'你的原始MTOM响应字节内容'

# 1. 解析MIME多部分内容,提取SOAP XML片段
msg = BytesParser(policy=policy.default).parsebytes(response_content)
soap_xml = None
for part in msg.walk():
    if part.get_content_type() == 'application/xop+xml':
        soap_xml = part.get_content()
        break

# 2. 解析SOAP信封,提取转义的业务XML
ns = {
    's': 'http://www.w3.org/2003/05/soap-envelope',
    'bir': 'http://CIS/BIR/PUBL/2014/07'
}
soap_root = ET.fromstring(soap_xml)
encoded_biz_xml = soap_root.find('./s:Body/bir:DaneSzukajPodmiotyResponse/bir:DaneSzukajPodmiotyResult', ns).text

# 3. 反转义后解析业务字段
biz_xml = html.unescape(encoded_biz_xml)
biz_root = ET.fromstring(biz_xml)
dane_node = biz_root.find('./dane')

# 字段提取示例
regon = dane_node.find('Regon').text
nip = dane_node.find('Nip').text
nazwa = dane_node.find('Nazwa').text
print(f"Regon编码: {regon}, NIP税号: {nip}, 公司名称: {nazwa}")

方案2:zeep SOAP客户端自动处理(推荐)

如果是主动发起SOAP请求,直接用支持MTOM的zeep框架,无需手动解析:

  1. 安装依赖:pip install zeep
  2. 调用示例:
from zeep import Client
from zeep.transports import Transport

# 开启MTOM支持
transport = Transport(mtom=True)
# 替换为实际的WSDL地址
client = Client('https://你的服务地址?wsdl', transport=transport)
# 直接调用接口方法,自动处理MTOM封装与解析
resp = client.service.DaneSzukajPodmioty(请求参数名=参数值)
# 直接读取结构化返回值
print(resp.DaneSzukajPodmiotyResult.dane.Regon)

R 实现

  1. 先安装依赖包:install.packages(c("httr", "xml2"))
  2. 解析代码:
library(httr)
library(xml2)

# 此处resp为httr发送SOAP请求返回的响应对象,示例:resp <- POST("接口地址", body = 构造的SOAP请求体, content_type("application/soap+xml"))
resp <- 你的请求响应对象

# 1. 拆分MTOM多部分内容,提取SOAP XML
content_type <- headers(resp)$`Content-Type`
boundary <- gsub('.*boundary="?([^";]+)"?.*', '\\1', content_type)
resp_raw <- content(resp, as = "raw")
parts <- strsplit(rawToChar(resp_raw), paste0("--", boundary))[[1]]
parts <- parts[parts != "" & parts != "--\r\n"]

soap_xml <- NULL
for (part in parts) {
  if (grepl("Content-Type: application/xop\\+xml", part)) {
    # 拆分头部和内容
    split_part <- strsplit(part, "\r\n\r\n")[[1]]
    soap_xml <- split_part[length(split_part)]
    break
  }
}

# 2. 解析SOAP信封提取转义XML
ns <- c(
  s = "http://www.w3.org/2003/05/soap-envelope",
  bir = "http://CIS/BIR/PUBL/2014/07"
)
soap_root <- read_xml(soap_xml)
encoded_biz_xml <- xml_text(xml_find_first(soap_root, "//s:Body/bir:DaneSzukajPodmiotyResponse/bir:DaneSzukajPodmiotyResult", ns))

# 3. 反转义解析业务字段
biz_root <- read_xml(xml_unescape(encoded_biz_xml))
regon <- xml_text(xml_find_first(biz_root, "//dane/Regon"))
nazwa <- xml_text(xml_find_first(biz_root, "//dane/Nazwa"))
print(paste0("Regon编码: ", regon, " 公司名称: ", nazwa))

内容的提问来源于stack exchange,提问作者khasis lampard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 19:54:04