Java 解析 SOAP XML 的方法
在 Java 中解析 SOAP XML 有多种方法,以下是几种常用的技术方案:

使用标准 Java API (DOM/SAX)
DOM 解析方式
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class SoapDomParser {
public static void parseSoapResponse(String soapResponse) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(soapResponse)));
// 获取SOAP Body
NodeList bodyList = document.getElementsByTagName("soap:Body");
Element body = (Element) bodyList.item(0);
// 获取响应数据
NodeList responseList = body.getElementsByTagName("ns2:Response");
Element response = (Element) responseList.item(0);
// 提取具体数据
String result = response.getElementsByTagName("ns2:Result").item(0).getTextContent();
System.out.println("Result: " + result);
}
}
SAX 解析方式
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SoapSaxParser extends DefaultHandler {
private boolean inBody = false;
private boolean inResult = false;
private StringBuilder currentValue = new StringBuilder();
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if ("soap:Body".equals(qName)) {
inBody = true;
} else if (inBody && "ns2:Result".equals(qName)) {
inResult = true;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (inResult) {
currentValue.append(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("soap:Body".equals(qName)) {
inBody = false;
} else if (inResult && "ns2:Result".equals(qName)) {
inResult = false;
System.out.println("Result: " + currentValue.toString());
currentValue.setLength(0);
}
}
}
使用 JAXB (Java Architecture for XML Binding)
JAXB 可以将 XML 映射到 Java 对象,特别适合处理结构化的 SOAP 响应。
定义 Java 类
import javax.xml.bind.annotation.*;
@XmlRootElement(name = "Envelope", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
@XmlAccessorType(XmlAccessType.FIELD)
public class SoapEnvelope {
@XmlElement(name = "Body", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
private SoapBody body;
// getters and setters
}
@XmlAccessorType(XmlAccessType.FIELD)
public class SoapBody {
@XmlElement(name = "Response", namespace = "http://example.com/namespace")
private SoapResponse response;
// getters and setters
}
@XmlAccessorType(XmlAccessType.FIELD)
public class SoapResponse {
@XmlElement(name = "Result")
private String result;
// getters and setters
}
解析代码
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class SoapJaxbParser {
public static SoapEnvelope parseSoapResponse(String soapResponse) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(SoapEnvelope.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return (SoapEnvelope) unmarshaller.unmarshal(new StringReader(soapResponse));
}
}
使用第三方库
1 Apache Axis2
import org.apache.axis2.databinding.ADBException;
import org.apache.axis2.databinding.utils.BeanUtil;
public class SoapAxis2Parser {
public static void parseWithAxis2(String soapResponse) throws ADBException {
// 假设你已经定义了相应的Java类
Object response = BeanUtil.deserialize(soapResponse, SoapResponse.class);
System.out.println(response);
}
}
2 Woodstox
import com.ctc.wstx.api.WstxInputProperties;
import com.ctc.wstx.stax.WstxInputFactory;
import org.codehaus.stax2.XMLStreamReader2;
public class SoapWoodstoxParser {
public static void parseWithWoodstox(String soapResponse) throws Exception {
WstxInputFactory factory = new WstxInputFactory();
factory.setProperty(WstxInputProperties.P_MAX_ATTRIBUTE_COUNT, 1000);
XMLStreamReader2 reader = (XMLStreamReader2) factory.createStreamReader(new StringReader(soapResponse));
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
if ("Result".equals(reader.getLocalName())) {
String result = reader.getElementText();
System.out.println("Result: " + result);
}
}
}
}
}
使用 Spring Web Services
如果你正在使用 Spring 框架,可以结合 Spring Web Services 处理 SOAP 消息:
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.client.SoapFaultClientException;
public class SoapSpringClient {
private WebServiceTemplate webServiceTemplate;
public void sendAndReceiveSoapMessage(String request) {
try {
Object response = webServiceTemplate.marshalSendAndReceive(request);
// 处理响应
} catch (SoapFaultClientException e) {
// 处理SOAP错误
}
}
}
最佳实践建议
- 对于简单解析:如果只需要提取少量数据,SAX 解析更高效
- 对于复杂结构:JAXB 提供了更好的类型安全性和可维护性
- 性能要求高:考虑使用 StAX (如 Woodstox) 解析器
- 与 Web 服务集成:使用 Spring Web Services 或 Apache CXF 等框架
选择哪种方法取决于你的具体需求、性能要求以及项目上下文。

