用 Java 解析 SOAP 响应
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19975796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Parsing SOAP Response in Java
提问by Ben
I do not succeed in parsing a SOAP Response in Java (using Bonita Open Solution BPM). I have the following SOAP response (searching for a document in the IBM Content Manager; the SOAP Response returns 1 matching document)
我没有成功解析 Java 中的 SOAP 响应(使用 Bonita Open Solution BPM)。我有以下 SOAP 响应(在 IBM Content Manager 中搜索文档;SOAP 响应返回 1 个匹配的文档)
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:RunQueryReply xmlns="http://www.ibm.com/xmlns/db2/cm/beans/1.0/schema" xmlns:ns1="http://www.ibm.com/xmlns/db2/cm/beans/1.0/schema">
<ns1:RequestStatus success="true"></ns1:RequestStatus>
<ns1:ResultSet count="1">
<ns1:Item URI="http://xxxx/CMBSpecificWebService/CMBGetPIDUrl?pid=96 3 ICM8 ICMNLSDB16 ICCSPArchivSuche59 26 A1001001A12D18B30015E9357518 A12D18B30015E935751 14 1087&server=ICMNLSDB&dsType=ICM">
<ns1:ItemXML>
<ICCSPArchivSuche ICCCreatedBy="EBUSINESS\iccadmin" ICCCreatedDate="2012-04-18T10:51:26.000000" ICCFileName="Golem_Artikel.txt" ICCFolderPath="" ICCLastModifiedDate="2012-04-18T10:51:28.000000" ICCLibrary="Dokumente" ICCModifiedBy="EBUSINESS\iccadmin" ICCSharePointGUID="c43f9c93-a228-43f9-8232-06bdea4695d1" ICCSharePointVersion="1.0 " ICCSite="Archiv Suche" cm:PID="96 3 ICM8 ICMNLSDB16 ICCSPArchivSuche59 26 A1001001A12D18B30015E9357518 A12D18B30015E935751 14 1087" xmlns:cm="http://www.ibm.com/xmlns/db2/cm/api/1.0/schema">
<cm:properties type="document">
<cm:lastChangeUserid value="ICCCMADMIN"/>
<cm:lastChangeTime value="2012-04-18T11:00:15.914"/>
<cm:createUserid value="ICCCMADMIN"/>
<cm:createTime value="2012-04-18T11:00:15.914"/>
<cm:semanticType value="1"/>
<cm:ACL name="DocRouteACL"/>
<cm:lastOperation name="RETRIEVE" value="SUCCESS"/>
</cm:properties>
<cm:resourceObject CCSID="0" MIMEType="text/plain" RMName="rmdb" SMSCollName="CBR.CLLCT001" externalObjectName=" " originalFileName="" resourceFlag="2" resourceName=" " size="702" textSearchable="true" xsi:type="cm:TextObjectType">
<cm:URL value="http://cmwin01.ebusiness.local:9080/icmrm/ICMResourceManager/A1001001A12D18B30015E93575.txt?order=retrieve&item-id=A1001001A12D18B30015E93575&version=1&collection=CBR.CLLCT001&libname=icmnlsdb&update-date=2012-04-18+11%3A00%3A15.001593&token=A4E6.IcQyRE6_QbBPESDGxK2;&content-length=0"/>
</cm:resourceObject>
</ICCSPArchivSuche>
</ns1:ItemXML>
</ns1:Item>
</ns1:ResultSet>
</ns1:RunQueryReply>
</soapenv:Body>
</soapenv:Envelope>
I would like to get the filename (ICCFileName="Golem_Artikel.txt") and the url to this file ( <cm:URL value="http://cmwin01.ebusiness.local:9080/icmrm/ICMResourceManager/A10...) in string Variables using Java. I read several articles on how to do this (Can't process SOAP response, How to do the Parsing of SOAP Response) but without success. Here is what I tried:
我想获取文件名(ICCFileName="Golem_Artikel.txt")和该文件的网址( < cm:URL value="http://cmwin01.ebusiness.local:9080/icmrm/ICMResourceManager/A10... ) 在使用 Java 的字符串变量中。我阅读了几篇关于如何执行此操作的文章(无法处理 SOAP 响应,如何进行 SOAP 响应的解析)但没有成功。这是我尝试过的:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
// Clean response xml document
responseDocumentBody.normalizeDocument();
// Get result node
NodeList resultList = responseDocumentBody.getElementsByTagName("ICCSPArchivSuche");
Element resultElement = (Element) resultList.item(0);
String XMLData = resultElement.getTextContent();
// Check for empty result
if ("Data Not Found".equalsIgnoreCase(XMLData))
return null;
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource inputSource = new InputSource();
inputSource.setCharacterStream(new StringReader(XMLData));
Document doc = documentBuilder.parse(inputSource);
Node node = doc.getDocumentElement();
String result = doc.getNodeType();
return result;
From Bonita, I only get responseDocumentBody or responseDocumentEnvelope (org.w3c.dom.Document) as webservice response. Therefore, I need to navigate from the SOAP Body to my variables. I would be pleased if someone could help.
从 Bonita,我只得到 responseDocumentBody 或 responseDocumentEnvelope (org.w3c.dom.Document) 作为网络服务响应。因此,我需要从 SOAP Body 导航到我的变量。如果有人可以提供帮助,我会很高兴。
Best regards
此致
采纳答案by forty-two
If you do a lot of work with this, I would definitively recommend using JAXB as MGoron suggests. If this is a one shot excersize, XPATH could also work well.
如果您为此做了很多工作,我绝对建议您按照 MGoron 的建议使用 JAXB。如果这是一次性运动,XPATH 也可以很好地工作。
/*
* Must use a namespace aware factory
*/
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(...);
/*
* Create an XPath object
*/
XPath p = XPathFactory.newInstance().newXPath();
/*
* Must use a namespace context
*/
p.setNamespaceContext(new NamespaceContext() {
public Iterator getPrefixes(String namespaceURI) {
return null;
}
public String getPrefix(String namespaceURI) {
return null;
}
public String getNamespaceURI(String prefix) {
if (prefix.equals("ns1"))
return "http://www.ibm.com/xmlns/db2/cm/beans/1.0/schema";
if (prefix.equals("cm"))
return "http://www.ibm.com/xmlns/db2/cm/api/1.0/schema";
return null;
}
});
/*
* Find the ICCSFileName attribute
*/
Node iccsFileName = (Node) p.evaluate("//ns1:ICCSPArchivSuche/@ICCFileName", doc, XPathConstants.NODE);
System.out.println(iccsFileName.getNodeValue());
/*
* Find the URL
*/
Node url = (Node) p.evaluate("//ns1:ICCSPArchivSuche/cm:resourceObject/cm:URL/@value", doc, XPathConstants.NODE);
System.out.println(url.getNodeValue());
回答by MGorgon
- get RunQueryReply schema
- map xsd to java classes using jax-b
- unmarshall response string to jax-b class object
- 获取 RunQueryReply 架构
- 使用 jax-b 将 xsd 映射到 java 类
- 将响应字符串解组到 jax-b 类对象
回答by vtd-xml-author
Below is the code to do this in VTD-XML, it basically consists of 2 XPath queries, each returning one result... however the code is robust as it doesn't assume those queries will return non-empty result...
下面是在VTD-XML 中执行此操作的代码,它基本上由 2 个 XPath 查询组成,每个查询返回一个结果……但是代码很健壮,因为它不假设这些查询将返回非空结果……
import com.ximpleware.*;
public class parseSOAP {
public static void main(String[] s) throws VTDException, Exception{
VTDGen vg = new VTDGen();
vg.selectLcDepth(5);// soap has deep nesting so set to 5 to speed up navigation
if (!vg.parseFile("d:\xml\soap2.xml", true))
return;
VTDNav vn = vg.getNav();
AutoPilot ap =new AutoPilot(vn);
//declare name space for xpath
ap.declareXPathNameSpace("ns", "http://www.ibm.com/xmlns/db2/cm/beans/1.0/schema");
ap.declareXPathNameSpace("ns1", "http://www.ibm.com/xmlns/db2/cm/beans/1.0/schema");
ap.declareXPathNameSpace("cm", "http://www.ibm.com/xmlns/db2/cm/api/1.0/schema");
ap.declareXPathNameSpace("soapenv", "http://www.w3.org/2003/05/soap-envelope");
ap.selectXPath("/soapenv:Envelope/soapenv:Body/ns1:RunQueryReply/ns1:ResultSet/ns1:Item/ns1:ItemXML//ICCSPArchivSuche/@ICCFileName");
int i=0;
if ((i=ap.evalXPath())!=-1){
System.out.println("file name ==>"+vn.toString(i+1));
}
ap.selectXPath("/soapenv:Envelope/soapenv:Body/ns1:RunQueryReply/ns1:ResultSet/ns1:Item/ns1:ItemXML//ICCSPArchivSuche/cm:resourceObject/cm:URL/@value");
if ((i=ap.evalXPath())!=-1){
System.out.println("file name ==>"+vn.toString(i+1));
}
}
}