简体   繁体   English

JAXB如何将嵌套的xml元素解组为字符串?

[英]How can JAXB unmarshal nested xml elements into a string?

I am trying to convert xml to my Java class 我正在尝试将xml转换为我的Java类

@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. Request类中, xmlPost将包含Report xml或Status xml,因此我想将其捕获到字符串中,以便尝试解组每种情况。

The Report class comes from a 3rd party request that I have no control over. Report类来自我无法控制的第三方请求。 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 . 但是,当我尝试XMLPost Request如果XMLPost字段中有任何XML,即使我已将其指定为String ,它也会尝试XMLPost Request Why can't I stuff the xml that in XMLPost in to a String ? 为什么我不能将XMLPost中的xml XMLPostString

Thanks for all the help in advanced. 感谢您提供的所有高级帮助。

You can achieve using cusom handler to convert it, Please check this post. 您可以使用cusom handler进行转换,请检查这篇文章。 I hope it would help you to fix ur issue : http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html 我希望它能帮助您解决问题: http : //blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html

You cannot do that directly, because it does not follow XML specification. 您不能直接执行此操作,因为它不遵循XML规范。 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. 这意味着根据XML规范的JAXB期望具有简单类型元素XMLPost的XML为xs:string。 not as another XML element. 不作为另一个XML元素。 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: 因此,如果您想在其中包含另一个XML作为字符串,则必须以XML转义的形式来存储它,例如:

<Request>
    <XMLPost>&lt;Report&gt; ...xml escaped content... &lt;/Report&gt;</XMLPost>
</Request>

or as CDATA element. 或作为CDATA元素。

<Request>
    <XMLPost><![CDATA[<Report> ...xml content... </Report>]]></XMLPost>
</Request>

From other hands you can have two fields as your complex XML elements 另一方面,您可以将两个字段作为复杂的XML元素

@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. 在这种情况下,您必须具有用于报告和状态的JAXB类。然后,如果您的请求具有报告元素,则报告字段将具有该元素,并且状态将为null;或者,如果请求具有状态,则状态字段将具有该元素,而报告字段将为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: 关于XML Schema,您做了什么:

<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 最后,如果只需要一个字段来保留Report或Status对象(不是String),则将其定义为Object

@XmlElement(name="XMLPost")
private Object xmlPost;

It corresponds to XSD: 它对应于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 当然,当您处理请求时,要由您检查什么是xmlPost对象类

What I would really do is create an XMLPost object, with optional report and status fields. 我真正要做的是创建一个带有可选reportstatus字段的XMLPost对象。 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? ). 但是,要回答您的原始问题,您应该使用XmlAdapter在JAXB中,如何使用@XmlJavaTypeAdapters批注? )。 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));
  }

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM