I am trying to convert xml to my Java class
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Request")
public class Request {
@XmlElement(name="UserName")
private String username;
@XmlElement(name="Password")
private String password;
@XmlElement(name="XMLPost")
private String xmlPost;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getXmlPost() {
return xmlPost;
}
public void setXmlPost(String xmlPost) {
this.xmlPost = xmlPost;
}}
Here is my context
JAXBContext jc = JAXVContext.newInstance(Request.class, Report.class, Status.class);
StringReader reader = new StringReader(xml);
Unmarshaller unmarshaller = jc.createUnmarshaller();
And here is how I use them together
Request request = unmarshaller.unmarshal(reader);
In the Request
class the xmlPost
will contain either xml of Report
or xml of Status
So I would like to capture it into a string so that I can try to unmarshal each case.
The Report
class comes from a 3rd party request that I have no control over. However when I attempt to unmarshal the Request
if there is any XML in XMLPost
field it tries to unmarshal it as well, even though I have specified that it should just be a String
. Why can't I stuff the xml that in XMLPost
in to a String
?
Thanks for all the help in advanced.
You can achieve using cusom handler to convert it, Please check this post. I hope it would help you to fix ur issue : http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html
You cannot do that directly, because it does not follow XML specification. When you define:
@XmlElement(name="XMLPost")
private String xmlPost;
it means that JAXB according to XML specification expects XML with simple type element XMLPost as xs:string. not as another XML element. To have a value in it your Request must look like:
<Request>
<XMLPost>some string in it</XMLPost>
</Request>
So, if you'd like to have another XML in it as a String you must have it either in XML escaped form like:
<Request>
<XMLPost><Report> ...xml escaped content... </Report></XMLPost>
</Request>
or as CDATA element.
<Request>
<XMLPost><![CDATA[<Report> ...xml content... </Report>]]></XMLPost>
</Request>
From other hands you can have two fields as your complex XML elements
@XmlElement(name="Report")
private Report report;
@XmlElement(name="Status")
private Status status;
In that case you have to have JAXB classes for Report and Status Then if your Request has Report element then report field will have it and status will be null or when Request has Status then status field will have it and report field will be null.
Maybe it is more appropriate approach if you need your Report and Status without taking a String and unmarshaling them separately. It is up to you and what you need to do with those elements...
In terms of XML Schema what you did:
<xs:element name="Request">
<xs:complexType>
<xs:sequence>
<xs:element name="XMLPost" type="xs:string">
</xs:sequence>
</xs:complexType>
</xs:element>
for the second approach it will look like:
<xs:element name="Request">
<xs:complexType>
<xs:sequence>
<xs:element name="Report" minOccurs="0">
<xs:complexType>
<xs:sequence>
<!-- ... Report type definition ... -->
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Status" minOccurs="0">
<xs:complexType>
<xs:sequence>
<!-- ... Status type definition ... -->
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
And finally if you need only one field to keep either Report or Status object (not String) define it as Object
@XmlElement(name="XMLPost")
private Object xmlPost;
It corresponds to XSD:
<element name="XMLPost" type="xs:anyType" />
Of course when you process your request it is up to you to check what is a Class of xmlPost object
What I would really do is create an XMLPost
object, with optional report
and status
fields. Then after unmarshalling, you can see which one is populated.
However to answer your original question, you should use an XmlAdapter
( In JAXB, how to use @XmlJavaTypeAdapters annotation? ). Here is an example of what the adapter might look like:
public class XmlPostStringAdapter extends XmlAdapter<XMLPost, String> {
@Override
public String unmarshal(XMLPost xmlPost) throws Exception {
StringWriter sw = new StringWriter();
JAXBContext jaxbContext = JAXBContext.newInstance(XmlPost.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.marshal(xmlPost, sw);
return sw.toString();
}
@Override
public XMLPost marshal(String xmlPost) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(XMLPost.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
return (XMLPost) jaxbUnmarshaller.unmarshal(new StringReader(xmlPost));
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.