JAXB绑定3级嵌套元素

时间:2019-06-13 17:35:51

标签: java xml jaxb marshalling unmarshalling

我正在尝试使用jaxb将以下xml绑定到Java

<Validation> 
...
        <Options>
             <AllowUnspecifiedParameters>
                  <Header> True </Header>
                  <Query> True </Query>
                  <Cookies> True </Cookies>
             </AllowUnspecifiedParameters>
        </Options>
</Validation> 

我看过类似的例子,例如JAXB binding nested elements 但是最深层的嵌套级别是用于列表的,@XmlElementWrapper仅用于集合,因此看起来不适合我的情况。

有人知道我该怎么做吗?真的很感激。

3 个答案:

答案 0 :(得分:1)

选项1 的一种纯JaxB方法是通过为Options元素定义适配器。适配器用于将任何xml或多或少地转换为任何对象,反之亦然(自定义封送处理)。

    @XmlJavaTypeAdapter(OptionsAdapter.class)

    public class OptionsAdapter extends extends XmlAdapter<Element, Options> {

    @Override
        public Element marshal(Options v) throws Exception {
            // put your marshaling logic here
        }

        @Override
        public Options unmarshal(Element node) throws Exception {
           // put your unmarshaling logic here
        }

    }

Then in the class holding the options element you will have:

    public class ClazzHoldingOptions {

      @XmlJavaTypeAdapter(OptionsAdapter.class)
      private Options options;

    }

选项2 EclipseLink具有通过xpath表达式映射元素的功能

     @XmlPath("AllowUnspecifiedParameters/Header/text()")
     private String  header;

https://www.eclipse.org/eclipselink/api/2.4/org/eclipse/persistence/oxm/annotations/XmlPath.html

选项3 在阅读@ df778899的代码时,我认为他的解决方案不是最佳的,但是它解决了我到目前为止尚未解决的问题。就是当您拥有如此多的属性时,您实际上并不想映射它们,或者只是简单地无法控制XML内容并且不信任它,也不想破坏更改。在其中我将映射到HashMap:

    @XmlJavaTypeAdapter(OptionsAdapter.class)

    public class OptionsAdapter extends extends XmlAdapter<Element, Options> {

    @Override
        public Element marshal(Hashmap v) throws Exception {
            // put your marshaling logic here
        }

        @Override
        public HashMap unmarshal(Element node) throws Exception {
           // put your unmarshaling logic here
        }

    }

Then in the class holding the options element you will have:

    public class ClazzHoldingOptions {

      @XmlJavaTypeAdapter(OptionsAdapter.class)
      private HashMap options;

    }

摘要。因此,让我总结一下优缺点

选项1。 +标准Aproach纯jaxB             +好,如果您拥有xml文件的架构的控制权。或者,如果预计该架构每月不会更改。             -如果架构或xml文件非常不稳定,则错误。

选项2。 +非常易于使用。无需适配器。             -如果您的架构易变,则不是最佳解决方案。             -需要特定的JaxB实现

选项3。-仅当您具有用于避免重大更改的易失性xml时,才有用。

PS:我使用@ df778899解决方案之类的唯一情况是,XML的结构是否存在极端结构性不确定性。例如,如果我知道xml中会出现某些内容,但我不知道确切的位置。 PLus内存不足,是否要在内存中保存与xml相关的所有元数据。

答案 1 :(得分:1)

您可以使用@XmlAnyElement提供嵌套元素,尽管它们以相当原始的形式出现-例如org.w3c.dom.Element实例:

@XmlRootElement(name = "Validation")
public class Validation {
    private List<Element> options;

    @XmlElementWrapper(name = "Options")
    @XmlAnyElement
    public List<Element> getOptions() {
        return options;
    }

    ...
}

然后可以将数据深入到:

    Validation validation = (Validation) unmarshaller.unmarshal(source);
    for (Element element : validation.getOptions()) {
        System.out.println(element.getNodeName() + ":");
        NodeList childNodes = element.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node childNode = childNodes.item(i);
            if (childNode.getNodeType() == Node.ELEMENT_NODE)
                System.out.println("  " + childNode.getNodeName() + "=" +
                        childNode.getTextContent());
        }
    }

其中显示了所有通过的数据:

AllowUnspecifiedParameters:
  Header= True 
  Query= True 
  Cookies= True 

答案 2 :(得分:0)

原来我的问题有一个简单的答案:

XML:

<Validation> 
...
        <Options>
             <AllowUnspecifiedParameters>
                  <Header> True </Header>
                  <Query> True </Query>
                  <Cookies> True </Cookies>
             </AllowUnspecifiedParameters>
        </Options>
</Validation> 

Java对象:

@XmlRootElement(name = "Validation")
public class Validation {

  // some more fields
  // ...


  private Options option = new Options();

  @XmlElement(name = "Options")
  public Options getOptions() {
    return options;
  }

}

public class Options {

  @XmlElement(name = "AllowUnspecifiedParameters")
  public StrictOptions allowUnspecifiedParameters = new StrictOptions();

  public static class StrictOptions {
    @XmlElement(name = "Header")
    public boolean header = true;

    @XmlElement(name = "Query")
    public boolean query = true;

    @XmlElement(name = "Cookie")
    public boolean cookie = true;

  }
}

但是,如果您有一个非常复杂的xml模式或java对象结构,如@ df778899和@Alexandar Petrov建议的那样,XmlAdapter@ XmlAnyElement是强大的工具。

以下是我发现的一个示例:Mapping an Arbitrary List of Objects Using JAXB's @XmlAnyElement and XmlAdapter