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

How can JAXB unmarshal nested xml elements into a string?

我正在尝试将 xml 转换为我的 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;
}}

这是我的上下文

JAXBContext jc = JAXVContext.newInstance(Request.class, Report.class, Status.class);
StringReader reader = new StringReader(xml);
Unmarshaller unmarshaller = jc.createUnmarshaller();

下面是我如何一起使用它们

Request request = unmarshaller.unmarshal(reader);

Request class 中,xmlPost 将包含 Report 的 xml 或 Status 的 xml 所以我想将它捕获到一个字符串中,以便我可以尝试解组每个案例。

Report class 来自我无法控制的第 3 方请求。但是,当我尝试解组 Request 时,如果 XMLPost 字段中有任何 XML,它也会尝试解组它,即使我已经指定它应该只是一个 [=21] =].为什么我不能将 XMLPost 中的 xml 填充到 String 中?

感谢所有先进的帮助。

您可以使用自定义处理程序对其进行转换,请检查此post。我希望它能帮助您解决问题:http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html

你不能直接这样做,因为它不符合 XML 规范。 当你定义:

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

这意味着根据 XML 规范的 JAXB 期望 XML 具有简单类型元素 XML 发布为 xs:string。不是另一个 XML 元素。 要在其中包含一个值,您的请求必须如下所示:

<Request>
    <XMLPost>some string in it</XMLPost>
</Request>

因此,如果您想在其中包含另一个 XML 作为字符串,您必须以 XML 转义形式包含它,例如:

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

或作为 CDATA 元素。

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

从其他人手中,您可以将两个字段作为复杂的 XML 元素

@XmlElement(name="Report")
private Report report;

@XmlElement(name="Status")
private Status status;

在那种情况下,您必须有 JAXB 类 用于报告和状态 那么如果你的请求有 Report 元素那么 报告字段将有它并且状态将为空 或者当请求有状态时,状态字段将有它并且报告字段将为空。

如果您需要 Report 和 Status 而无需使用 String 并单独解组它们,这可能是更合适的方法。这取决于您以及您需要如何处理这些元素...

就 XML 架构而言,您做了什么:

<xs:element name="Request">
   <xs:complexType>
     <xs:sequence>
         <xs:element name="XMLPost" type="xs:string">
     </xs:sequence>
   </xs:complexType>     
 </xs:element>

对于第二种方法,它看起来像:

<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>

最后,如果您只需要一个字段来保留 Report 或 Status 对象(不是 String),请将其定义为 Object

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

对应XSD:

<element name="XMLPost" type="xs:anyType" />

当然,当您处理您的请求时,您需要检查什么是 Class 的 xmlPost 对象

我真正要做的是创建一个 XMLPost 对象,其中包含可选的 reportstatus 字段。然后unmarshalling之后就可以看到populated了哪一个

但是要回答您原来的问题,您应该使用 XmlAdapter (In JAXB, how to use @XmlJavaTypeAdapters annotation?)。以下是适配器的外观示例:

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));
  }

}