Java JAXB 使用命名空间和前缀解组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19395400/
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
JAXB unmarshall with namespaces and prefix
提问by gks
I am using JAXB to parse xml elements from the SOAP response. I have defined POJO classes for the xml elements. I have tested pojo classes without namespace and prefix its working fine .Though when i am trying to parse with namespaces and prefix facing the following exception.Requirement is to parse the input from SOAPMessage Object
我正在使用 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>
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are <{}Envelope>
Tried to fix by creating @XMLSchema for the package in package-info.java and located this file in package folder.Can any one guide me to move forward?
试图通过在 package-info.java 中为包创建 @XMLSchema 来修复并将此文件放在包文件夹中。有人能指导我继续前进吗?
Referredthis posts but didn help me .
引用了这篇文章,但没有帮助我。
EDITED :XMLSchema
编辑: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;
Thanks in advance
提前致谢
回答by bdoughan
Here is how you can handle your use cae:
以下是您可以如何处理您的使用 cae:
If You Need to Map the Envelope
Element
如果您需要映射Envelope
元素
package-info
包信息
Typically you would use the @XmlSchema
as follows. Using the namespace
and elementFormDefault
properties like I've done means that all data mapped to XML elements unless otherwise mapped will belong to the http://www.xxxx.com/ncp/oomr/dto/
namespace. The information specified in xmlns
is for XML schema generation altough some JAXB implementations use this to determine the preferred prefix for a namespace when marshalling (see: http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html).
通常你会使用@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.*;
Envelope
信封
If within the com.one.two
you need to map to elements from a namespace other than http://www.xxxx.com/ncp/oomr/dto/
then you need to specify it in the @XmlRootElement
and @XmlElement
annotations.
如果com.one.two
您需要映射到来自命名空间以外的元素,http://www.xxxx.com/ncp/oomr/dto/
那么您需要在@XmlRootElement
and@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;
}
For More Information
想要查询更多的信息
If You Just Want to Map the Body
如果你只是想映射身体
You can use a StAX parser to parse the message and advance to the payload portion and unmarshal from there:
您可以使用 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();
}
}
For More Information
想要查询更多的信息
回答by Adam
This can be done without modifying the generated JAXB code using standard SOAPMessage class. I wrote about this hereand here
这可以在不使用标准 SOAPMessage 类修改生成的 JAXB 代码的情况下完成。我在这里和这里写过这个
It's a little fiddly but works correctly.
这有点繁琐,但工作正常。
Marshalling
编组
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());
Unmarshalling
解组
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());
回答by ptdunlap
Just wanted to add onto the existing answers -- while unmarshalling if the XML document is not namespace aware you might receive an error: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://some.url";, local:"someOperation")
只是想添加到现有的答案 - 如果 XML 文档不知道命名空间,则在解组时您可能会收到错误:javax.xml.bind.UnmarshalException:意外元素(uri:“ http://some.url” ;,本地:“someOperation”)
If this is the case you can simply use a different method on the unmarshaller:
如果是这种情况,您可以简单地在解组器上使用不同的方法:
Unmarshaller unmarshaller = JAXBContext.newInstance(YourObject.class).createUnmarshaller();
JAXBElement<YourObject> element = unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument(), YourObject.class);
YourObject yo = element.getValue();