使用JAXB解组嵌套的XML元素

时间:2018-03-08 19:35:48

标签: java xml class dictionary jaxb

我开始使用JAXB并且我试图阅读以下xml以将其映射到classe:

<element id="0">
        <type>1</type>
        <color>0</color>
        <size>1</size>
        <location>
          <absolute>
            <absolute-item>top</absolute-item>
            <absolute-item>left</absolute-item>
          </absolute>
          <relative>
            <right>0</right>
            <left>0</left>            
          </relative>
        </location>
    </element>

当我尝试映射像abslute这样的嵌套元素时,我的问题来了,它可以包含任意数量的元素。我现在正在尝试这个:

public class Element {
    @XmlAttribute
    private int id;
    @XmlElement
    private int type;
    @XmlElement
    private int color;
    @XmlElement
    private int size;
    @XmlElementWrapper(name="absolute")
    @XmlElement(name="absolute-item")
    private ArrayList<String> absoluteItems;

    @Override
    public String toString() {
        return "Element "+id+" {" +
                "type=" + type +
                ", color=" + color +
                ", size=" + size +
                ", Location Relative: "+ absoluteItems
                +"}";
    }
}

我得到了简单的元素,但没有嵌套的元素。显然我不能一起注释包装,所以我不知道如何解决它。

更新: 我按照建议尝试这个。我得到一个IllegalAnnotationExceptions,因为Element $ Location.right不是编译属性,但我不知道它意味着什么。我应该为元素再创建一个类吗?

public class Element {
    @XmlAttribute
    private int id;
    @XmlElement
    private int type;
    @XmlElement
    private int color;
    @XmlElement
    private int size;

    @XmlElement(name="location")
    private Location location;

    public static class Location {
        @XmlElementWrapper(name="absolute")
        @XmlElement(name="absolute-item")
        private ArrayList<String> absoluteItems;


        @XmlElementWrapper(name="relative")
        @XmlElement(name="right")
        private int right;
        @XmlElement(name="left")
        private int left;

        @Override
        public String toString() {
            return "Location{" +
                    "Absolute=" + absoluteItems +
                    ", relative {right=" + right +
                    ", left=" + left +
                    "}}";
        }
    }

1 个答案:

答案 0 :(得分:0)

JAXB处理假定每个复杂元素都有一个单独的元素定义。复杂元素表示包含其他元素的元素。

你提到的错误,指的是Element $ Location,可能表明jaxb例程找到了字段的注释&#34; right&#34;在嵌套的Location类中;在运行时,嵌套类具有包含类的名称,在本例中为Element,作为通过美元符号与嵌套类隔开的前缀。

要解组(从xml文本转换为Java代码)上面提供的数据结构,JAXB例程可能会找到以下公共类定义:

绝对 元件 地点 的ObjectFactory 相对

在jaxb编译器生成的java代码中,主元素定义有自己的类,以及以下注释:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
   "type",
    "color",
    "size",
    "location"
})
@XmlRootElement(name = "element")
public class Element 
{
   @XmlElement(required = true)
   protected BigInteger type;
      .
      .   additional element definitions go here
      . 
   // note: location here is a public class
   @XmlElement(required = true)
   protected Location location;
   // the attribute is defined thus:
   @XmlAttribute(name = "id")
   protected BigInteger id;

   /**
    * Gets the value of the type property.
    * @return BigInteger type code
    */
   public BigInteger getType() { return type; }

   /**
    * Sets the value of the type property.
    * @param value BigInteger type code to set
    */
   public void setType(BigInteger value) { this.type = value; }
      .
      . all other getters and setters defined here
      .
}

包含的元素(在本例中为Location)具有自己的类,其中包含以下注释:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Location", propOrder = {
   "absolute",
   "relative"
})
public class Location 
{
    protected Absolute absolute;
    protected Relative relative;
      .
      .  getters and setters go here: note these fields have no 
      .  annotations
}

同样,jaxb希望找到公开的Absolute和Relative类。由于绝对项元素可以无限重复,因此jaxb希望将其定义为集合(List),因此:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Absolute", propOrder = {
   "absoluteItem"
})
public class Absolute 
{
   @XmlElement(name = "absolute-item", required = true)
   protected List<String> absoluteItem;

   /**
    * Gets the value of the absoluteItem property.
    * 
    * <p>This accessor returns a reference to the live list; any
    * modification to the returned list will be reflected in the 
    * JAXB object.
    * This is why there is not a setter for absoluteItem.
    * 
    * To add a new item, do as follows:
    *    getAbsoluteItem().add(newItem)
    */
   public List<String> getAbsoluteItem() 
   {
      if (absoluteItem == null) 
          absoluteItem = new ArrayList <> ();        
      return this.absoluteItem;
   }

}

根据我的经验,jaxb模式编译器xjc提供了迄今为止生成类或与jaxb一起使用的最简单方法。 xjc采用XML模式定义,并将其转换为Java代码;然后,您只需要在项目中包含生成的java文件。大多数Java开发工具都会自动为您处理。为了生成我用作上述示例的源代码(我做了一些精简,我编写了以下架构:

<?xml version="1.0" encoding="UTF-8"?>

<!--
  Component ==> example for stack overflow
  Purpose: show how the jaxb compiler works
 -->

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
           xmlns:desc = "http://sox.org/element"
           targetNamespace = "http://sox.org/element"
           jxb:version="2.0">

    <xs:element name="element">
       <xs:complexType>
          <xs:sequence>
             <xs:element name = "type" type = "xs:integer" />
             <xs:element name = "color" type = "xs:integer" />
             <xs:element name = "size" type = "xs:integer" />
             <xs:element name = "location" type = "desc:Location" />
          </xs:sequence>
          <xs:attribute name="id" type="xs:integer" use="optional"
                        default="0" />
       </xs:complexType>
    </xs:element>     

    <xs:complexType name="Location">
       <xs:sequence>
          <xs:element name = "absolute" type = "desc:Absolute" 
                      minOccurs="0" />
          <xs:element name = "relative" type = "desc:Relative" 
                      minOccurs="0" /> 
       </xs:sequence>
    </xs:complexType>

    <xs:complexType name="Absolute">
       <xs:sequence>
          <xs:element name="absolute-item" type="xs:string"  
                      maxOccurs="unbounded" />
       </xs:sequence>
    </xs:complexType> 

    <xs:complexType name="Relative">
       <xs:sequence>
          <xs:element name="right" type="xs:string" /> 
          <xs:element name="left" type="xs:string" /> 
       </xs:sequence>
    </xs:complexType>