杰瑞科技汇

Java如何高效解析SOAP XML?

Java 解析 SOAP XML 的方法

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

Java如何高效解析SOAP XML?-图1
(图片来源网络,侵删)

使用标准 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错误
        }
    }
}

最佳实践建议

  1. 对于简单解析:如果只需要提取少量数据,SAX 解析更高效
  2. 对于复杂结构:JAXB 提供了更好的类型安全性和可维护性
  3. 性能要求高:考虑使用 StAX (如 Woodstox) 解析器
  4. 与 Web 服务集成:使用 Spring Web Services 或 Apache CXF 等框架

选择哪种方法取决于你的具体需求、性能要求以及项目上下文。

Java如何高效解析SOAP XML?-图2
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇