【问题标题】:How can JAXB unmarshal nested xml elements into a string?JAXB 如何将嵌套的 xml 元素解组为字符串?
【发布时间】:2017-04-28 18:56:19
【问题描述】:

我正在尝试将 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;
}}

这是我的上下文

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 类中,xmlPost 将包含Report 的xml 或Status 的xml 所以我想将它捕获到一个字符串中,以便我可以尝试解组每个案例。

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

感谢所有高级帮助。

【问题讨论】:

  • 你能发布你得到的错误吗?
  • @AdamRosini 我没有收到错误,只是在我的 Request 类中 XMLPost 是一个空字符串,而我期待一个带有 xml 的字符串

标签: java xml jaxb unmarshalling


【解决方案1】:

我真正要做的是创建一个XMLPost 对象,带有可选的reportstatus 字段。然后在解组后,您可以看到填充了哪一个。

但是,要回答您最初的问题,您应该使用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));
  }

}

【讨论】:

    【解决方案2】:

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

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

    这意味着根据 XML 规范的 JAXB 期望 XML 具有简单类型元素 XMLPost 作为 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 类 然后,如果您的请求有报告元素,那么 报告字段将具有它并且状态将为空 或者当 Request 有 Status 时,status 字段将具有它,report 字段将为空。

    如果您需要您的报告和状态而不使用字符串并单独解组它们,那么这可能是更合适的方法。这取决于您以及您需要对这些元素做什么......

    就您所做的 XML Schema 而言:

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

    最后,如果您只需要一个字段来保留报告或状态对象(不是字符串),请将其定义为对象

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

    对应XSD:

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

    当然,当您处理您的请求时,您可以检查什么是 xmlPost 对象的类

    【讨论】:

      【解决方案3】:

      您可以使用自定义处理程序来实现转换,请查看此帖子。我希望它能帮助你解决你的问题:http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html

      【讨论】:

        猜你喜欢
        • 2017-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-06
        相关资源
        最近更新 更多