我正在使用JAXB来解析SOAP响应中的xml元素。我已经为xml元素定义了POJO类。我已经测试了没有命名空间的pojo类,并且前缀工作正常。但是当我尝试使用命名空间解析并且前缀面向以下异常时。要求解析来自SOAPMessage对象的输入
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are <{}Envelope>
尝试通过在package-info.java中为包创建@XMLSchema来修复,并将此文件放在包文件夹中。任何人都可以指导我继续前进吗?
Referred这个帖子但没有帮助我。
已编辑:XMLSchema
@javax.xml.bind.annotation.XmlSchema (
xmlns = { @javax.xml.bind.annotation.XmlNs(prefix = "env",
namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
@javax.xml.bind.annotation.XmlNs(prefix="ns3", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
提前致谢
答案 0 :(得分:17)
这可以在不使用标准SOAPMessage类修改生成的JAXB代码的情况下完成。我写了关于这个here和here
的文章它有点繁琐,但工作正常。
Farm farm = new Farm();
farm.getHorse().add(new Horse());
farm.getHorse().get(0).setName("glue factory");
farm.getHorse().get(0).setHeight(BigInteger.valueOf(123));
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Marshaller marshaller = JAXBContext.newInstance(Farm.class).createMarshaller();
marshaller.marshal(farm, document);
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
soapMessage.getSOAPBody().addDocument(document);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
soapMessage.writeTo(outputStream);
String output = new String(outputStream.toByteArray());
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());
答案 1 :(得分:13)
以下是处理使用cae的方法:
Envelope
元素<强>包信息强>
通常,您将使用@XmlSchema
,如下所示。像我所做的那样使用namespace
和elementFormDefault
属性意味着除非另有映射,否则映射到XML元素的所有数据都属于http://www.xxxx.com/ncp/oomr/dto/
命名空间。 xmlns
中指定的信息用于生成XML模式,一些JAXB实现使用它来确定编组时命名空间的首选前缀(请参阅:http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html)。
@XmlSchema (
namespace="http://www.xxxx.com/ncp/oomr/dto/",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns = {
@XmlNs(prefix = "env", namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
@XmlNs(prefix="whatever", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
import javax.xml.bind.annotation.*;
<强>封套强>
如果在com.one.two
范围内需要映射到http://www.xxxx.com/ncp/oomr/dto/
以外的命名空间中的元素,则需要在@XmlRootElement
和@XmlElement
注释中指定它。
package com.one.two;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Envelope", namespace="http://schemas.xmlsoap.org/soap/envelope/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Envelope {
@XmlElement(name="Body", namespace="http://schemas.xmlsoap.org/soap/envelope/")
private Body body;
}
了解更多信息
您可以使用StAX解析器来解析消息并前进到有效负载部分并从那里解组:
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class UnmarshalDemo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("src/blog/stax/middle/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while(!xsr.getLocalName().equals("return")) {
xsr.nextTag();
}
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Customer> jb = unmarshaller.unmarshal(xsr, Customer.class);
xsr.close();
}
}
了解更多信息
答案 2 :(得分:2)
只是想添加到现有的答案 - 如果XML文档不是名称空间感知的,则解组时可能会收到错误:javax.xml.bind.UnmarshalException:unexpected element(uri:“http://some.url”; ,local:“someOperation”)
如果是这种情况,您可以在unmarshaller上使用不同的方法:
Unmarshaller unmarshaller = JAXBContext.newInstance(YourObject.class).createUnmarshaller();
JAXBElement<YourObject> element = unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument(), YourObject.class);
YourObject yo = element.getValue();