SOAP (Simple Object Access Protocol) 是一种基于XML的协议,用于在Web服务之间交换结构化信息。SOAP消息是XML格式的,包含以下几个主要部分:
DOM (Document Object Model) 解析器将整个XML文档加载到内存中,形成树状结构。
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
public class SoapDomParser {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("soap.xml");
NodeList bodyElements = document.getElementsByTagNameNS(
"http://schemas.xmlsoap.org/soap/envelope/", "Body");
// 进一步处理Body内容
}
}
SAX (Simple API for XML) 是事件驱动的解析方式,适合大文件。
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class SoapSaxParser {
public static void main(String[] args) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
boolean inBody = false;
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("soap:Body")) {
inBody = true;
}
}
public void characters(char ch[], int start, int length) throws SAXException {
if (inBody) {
System.out.println(new String(ch, start, length));
}
}
public void endElement(String uri, String localName,
String qName) throws SAXException {
if (qName.equalsIgnoreCase("soap:Body")) {
inBody = false;
}
}
};
saxParser.parse("soap.xml", handler);
}
}
适合将XML映射到Java对象。
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
public class SoapJaxbParser {
public static void main(String[] args) throws Exception {
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage(null,
new FileInputStream("soap.xml"));
JAXBContext jc = JAXBContext.newInstance(Response.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Response response = (Response) unmarshaller.unmarshal(
message.getSOAPBody().extractContentAsDocument());
}
}
import xml.etree.ElementTree as ET
def parse_soap(xml_string):
# 注册命名空间
namespaces = {
'soap': 'http://schemas.xmlsoap.org/soap/envelope/',
'm': 'http://www.example.org/stock'
}
root = ET.fromstring(xml_string)
# 获取Body内容
body = root.find('soap:Body', namespaces)
# 进一步处理Body中的具体内容
stock_price = body.find('m:GetStockPriceResponse/m:Price', namespaces)
return stock_price.text
问题:无法正确找到元素,因为忽略了命名空间。
解决:在查找元素时始终包含命名空间。
// 正确方式
document.getElementsByTagNameNS("http://schemas.xmlsoap.org/soap/envelope/", "Body");
// 错误方式
document.getElementsByTagName("Body");
问题:使用DOM解析大文件导致内存不足。
解决:改用SAX或StAX解析器。
问题:XML文件编码与解析器预期不符。
解决:确保XML声明中包含正确的编码,如<?xml version="1.0" encoding="UTF-8"?>
。
问题:未正确处理SOAP错误。
解决:检查是否存在Fault元素并提取错误信息。
NodeList faultNodes = document.getElementsByTagNameNS(
"http://schemas.xmlsoap.org/soap/envelope/", "Fault");
if (faultNodes.getLength() > 0) {
Element fault = (Element) faultNodes.item(0);
String faultCode = fault.getElementsByTagName("faultcode").item(0).getTextContent();
String faultString = fault.getElementsByTagName("faultstring").item(0).getTextContent();
System.err.println("SOAP Fault: " + faultCode + " - " + faultString);
}
优势:
局限:
选择解析方法时应考虑性能需求、开发便利性和项目规模。对于简单项目,DOM可能足够;对于大文件或高性能需求,SAX或StAX更合适;对于对象映射场景,JAXB是理想选择。
没有搜到相关的文章