如何正确反序列化带有XML命名空间的SOAP字符串?
带命名空间的SOAP响应反序列化解决方案
首先要修正你提供的SOAP响应XML格式错误:
- 闭合标签
<n0:ZcustomerMasterInfoResponse/>应改为</n0:ZcustomerMasterInfoResponse> - 闭合标签
</soap:Envelop />应改为</soap-env:Envelope>
以下是针对不同语言的具体实现方案,核心是严格匹配命名空间URI(前缀如soap-env、n0不影响解析,只需URI一致):
C# 实现(XmlSerializer)
1. 定义对应实体类
using System.Xml.Serialization; // SOAP信封类 [XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] public class SoapEnvelope { [XmlElement(ElementName = "Header", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] public SoapHeader Header { get; set; } [XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] public SoapBody Body { get; set; } } public class SoapHeader { } public class SoapBody { [XmlElement(ElementName = "ZcustomerMasterInfoResponse", Namespace = "urn:sap-com:document:sap:soap:functions:mc-style")] public ZcustomerMasterInfoResponse Response { get; set; } } [XmlRoot(ElementName = "ZcustomerMasterInfoResponse", Namespace = "urn:sap-com:document:sap:soap:functions:mc-style")] public class ZcustomerMasterInfoResponse { [XmlElement(ElementName = "EOutput")] public EOutput EOutput { get; set; } } // 根据实际子标签扩展EOutput类 public class EOutput { // 示例:如果有<CustomerId>标签,添加对应属性 // public string CustomerId { get; set; } }
2. 安全反序列化代码
using System.IO; using System.Xml; using System.Xml.Serialization; var soapResponseXml = "你的SOAP响应XML字符串"; // 配置安全解析规则,防止XXE攻击 var settings = new XmlReaderSettings(); settings.DtdProcessing = DtdProcessing.Prohibit; settings.XmlResolver = null; using (var reader = XmlReader.Create(new StringReader(soapResponseXml), settings)) { var serializer = new XmlSerializer(typeof(SoapEnvelope)); var envelope = (SoapEnvelope)serializer.Deserialize(reader); // 读取目标数据 var customerOutput = envelope.Body.Response.EOutput; }
Java 实现(JAXB)
1. 定义对应实体类
import jakarta.xml.bind.annotation.*; @XmlRootElement(namespace = "http://schemas.xmlsoap.org/soap/envelope/", name = "Envelope") @XmlAccessorType(XmlAccessType.FIELD) public class SoapEnvelope { @XmlElement(namespace = "http://schemas.xmlsoap.org/soap/envelope/") private SoapHeader Header; @XmlElement(namespace = "http://schemas.xmlsoap.org/soap/envelope/") private SoapBody Body; // Getters and Setters public SoapHeader getHeader() { return Header; } public void setHeader(SoapHeader header) { Header = header; } public SoapBody getBody() { return Body; } public void setBody(SoapBody body) { Body = body; } } @XmlAccessorType(XmlAccessType.FIELD) public class SoapHeader { } @XmlAccessorType(XmlAccessType.FIELD) public class SoapBody { @XmlElement(namespace = "urn:sap-com:document:sap:soap:functions:mc-style", name = "ZcustomerMasterInfoResponse") private ZcustomerMasterInfoResponse response; // Getters and Setters public ZcustomerMasterInfoResponse getResponse() { return response; } public void setResponse(ZcustomerMasterInfoResponse response) { this.response = response; } } @XmlRootElement(namespace = "urn:sap-com:document:sap:soap:functions:mc-style", name = "ZcustomerMasterInfoResponse") @XmlAccessorType(XmlAccessType.FIELD) public class ZcustomerMasterInfoResponse { @XmlElement(name = "EOutput") private EOutput eOutput; // Getters and Setters public EOutput getEOutput() { return eOutput; } public void setEOutput(EOutput eOutput) { this.eOutput = eOutput; } } // 根据实际子标签扩展EOutput类 @XmlAccessorType(XmlAccessType.FIELD) public class EOutput { // 示例:添加对应子标签的属性 // private String CustomerId; }
2. 安全反序列化代码
import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.Unmarshaller; import org.xml.sax.XMLReader; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.XMLConstants; import java.io.StringReader; String soapResponseXml = "你的SOAP响应XML字符串"; // 配置安全解析,禁用外部实体防止XXE SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); XMLReader xmlReader = spf.newSAXParser().getXMLReader(); JAXBContext context = JAXBContext.newInstance(SoapEnvelope.class); Unmarshaller unmarshaller = context.createUnmarshaller(); unmarshaller.setProperty("org.xml.sax.XMLReader", xmlReader); SoapEnvelope envelope = (SoapEnvelope) unmarshaller.unmarshal(new StringReader(soapResponseXml)); ZcustomerMasterInfoResponse response = envelope.getBody().getResponse(); EOutput output = response.getEOutput();
通用注意事项
- 优先通过WSDL自动生成实体类,避免手动编写注解时的命名空间匹配错误
- 必须确保XML格式合法,闭合标签、命名空间声明无错误
- 所有解析操作必须开启安全配置,禁用DTD和外部实体引入,防止XXE注入攻击
内容的提问来源于stack exchange,提问作者pilotguy
相关产品推荐
相关产品推荐

