如何将 SOAP XML 解组为 Java 对象 [重复]

Posted

技术标签:

【中文标题】如何将 SOAP XML 解组为 Java 对象 [重复]【英文标题】:How to unmarshall SOAP XML to Java Object [duplicate] 【发布时间】:2014-11-23 17:16:24 【问题描述】:

在尝试将我的 soap XML 解组为 JAXB 对象时,出现以下错误。

我们收到错误,预期元素为无。在解组 SOAP XML 时是否应该执行任何特定操作。

javax.xml.bind.JAXBContext jaxbContext = (javax.xml.bind.JAXBContext) JAXBContext.newInstance(Class.forName(requestName));
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(SoapXmlString);          
reqInfo = unmarshaller.unmarshal(reader);

我收到以下错误:

 javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are (none)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:254)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:249)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:116)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement

这里是示例 XML

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://example.com/v2">
       <soapenv:Header/>
       <soapenv:Body>
          <v2:createSession>
             <v2:client>
                <!--Optional:-->
                <v2:name>?</v2:name>
                <!--Optional:-->
                <v2:clientId>?</v2:clientId>
                <!--Optional:-->
                <v2:requestId>?</v2:requestId>
             </v2:client>
             <!--Optional:-->
             <v2:oldSessionId>?</v2:oldSessionId>
             <!--Optional:-->
             <v2:clientIp>?</v2:clientIp>
             <!--Optional:-->
             <v2:clientIpStatus>?</v2:clientIpStatus>
             <!--Optional:-->
             <v2:superBYOBFlow>?</v2:superBYOBFlow>
             <!--Optional:-->
             <v2:FlowParams>?</v2:FlowParams>
             <!--Optional:-->
             <v2:deviceInfo>?</v2:deviceInfo>
          </v2:createSession>
       </soapenv:Body>
    </soapenv:Envelope>

请帮忙。

【问题讨论】:

'requestName' 有什么价值? 见here。 @priyesh:它是一个类名。例如:createSessionRequest 我可能会失明(可能),但我看不到重复答案的链接?!? 【参考方案1】:

我认为您没有将 SOAP 信封考虑在内...您生成的 JAXB Unmarshaller 对 Body 或 Envelope 标签一无所知,它会期望您的 createSession 成为根元素,因此“意外元素”错误。

您需要先从信封中提取内容,如果您先从内容中创建 SOAPMessage 对象,则可以使用 message.getSOAPBody().extractContentAsDocument() 来完成。

这很繁琐,这是我blog的一个工作示例

String example =
        "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header /><soapenv:Body><ns2:farm xmlns:ns2=\"http://adamish.com/example/farm\"><horse height=\"123\" name=\"glue factory\"/></ns2:farm></soapenv:Body></soapenv:Envelope>";
SOAPMessage message = MessageFactory.newInstance().createMessage(null,
        new ByteArrayInputStream(example.getBytes()));
Unmarshaller unmarshaller = JAXBContext.newInstance(Farm.class).createUnmarshaller();
Farm farm = (Farm)unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());

似乎如果您没有在架构 .xsd 文件中声明命名空间,那么您会看到您遇到的错误。

我创建了一个带有根元素 createSession 的虚拟模式,并通过添加 targetNamespace 属性并重新生成 JAXB 类,错误消失了

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     targetNamespace="http://example.com/v2"> <!-- targetNamespace essential for JAXB to work-->
    <xs:element name="createSession">  
        <xs:complexType>
            <xs:attribute name="foo" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
</xs:schema>

【讨论】:

感谢您的帮助 .. 我尝试了相同的代码,将 Farm 类替换为 CreateSessionRequest 类。但是我再次出现以下错误。 javax.xml.bind.UnmarshalException:意外元素(uri:“example.com/v2”,本地:“createSession”)。预期的元素是(无) @srinath 你能把你的 .xsd 文件贴出来,我会仔细看看。

以上是关于如何将 SOAP XML 解组为 Java 对象 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

在将 XML 文件解组为对象后,如何让 JAXB 调用方法?

使用 Jaxb API 将 XML 解组为 Java 对象时获取 NullPointerException

在 Android 中将 XML 文件解组为 Java 对象?

Java/JAXB:根据属性将 Xml 解组为特定子类

当 JSON 字段键是日期时,如何将 JSON 对象解组为 Golang 结构?

Akka HTTP:如何将 Json 格式响应解组为域对象