简体   繁体   English

使用JAXB解组嵌套的XML元素

[英]Unmarshal nested XML elements with JAXB

I'm starting with JAXB and im trying to read the following xml to map it to a classe: 我从JAXB开始,我试图读取以下xml以将其映射到类:

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

My porblem comes when I try to map the nested elements like abslute, wich can contain any number of elements. 当我尝试映射诸如abslute之类的嵌套元素时,我的麻烦就来了,它可以包含任意数量的元素。 I'm trying this right now: 我现在正在尝试:

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
                +"}";
    }
}

I got the simple elements but not the nested one. 我得到了简单的元素,但没有嵌套的元素。 Apparently I can't annotate to wrappers together, so I don't know how to fix it. 显然,我无法将包装器注释在一起,因此我不知道如何解决它。

UPDATE: I'm trying this as suggested. 更新:我正在尝试按照建议的方法。 I'm getting an IllegalAnnotationExceptions because Element$Location.right is not a compilation property, but i don't know what it means. 我收到一个IllegalAnnotationExceptions因为Element $ Location.right不是编译属性,但我不知道这意味着什么。 Should I create one more class for the element? 是否应该为该元素再创建一个类?

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 +
                    "}}";
        }
    }

JAXB processing assumes a separate element definition for each complex element. JAXB处理为每个复杂元素假定一个单独的元素定义。 A complex element means an element containing other elements. 复杂元素是指包含其他元素的元素。

The error you mention, referring to Element$Location, probably indicates the jaxb routines have found the annotation for the field "right" in the nested Location class; 您提到的涉及Element $ Location的错误可能表明jaxb例程已在嵌套的Location类中找到字段“ right”的注释; at runtime, nested classes have the name of the containing class, in this case Element, as a prefix separated from the nested class by a dollar sign. 在运行时,嵌套类具有包含类的名称(在本例中为Element),作为与嵌套类之间用美元符号分隔的前缀。

To unmarshall (translate from xml text to Java code) the data structure you provide above, the JAXB routines would expect to find the following public class definitions: 为了取消编组(从xml文本转换为Java代码)上面提供的数据结构,JAXB例程希望找到以下公共类定义:

Absolute Element Location ObjectFactory Relative 绝对元素位置ObjectFactory相对

In the java code the jaxb compiler produces, the main element definition has its own class, and the following annotations: 在jaxb编译器生成的Java代码中,main元素定义具有其自己的类以及以下注释:

@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
      .
}

The element contained, in this case Location, has its own class with the following annotations: 在这种情况下,元素包含的元素具有自己的类,带有以下注释:

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

Again, jaxb expects to find public Absolute and Relative classes. 再次,jaxb希望找到公共的Absolute和Relative类。 Since the absolute-item element can be repeated indefinitely, jaxb expects to find it defined as a collection (List), thus: 由于absolute-item元素可以无限期重复,因此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;
   }

}

In my experience, jaxb schema compiler, xjc, provides the easiest way, by far, to generate classes or use with jaxb. 以我的经验,到目前为止,jaxb模式编译器xjc提供了生成类或与jaxb一起使用的最简单方法。 xjc takes an XML schema definition, and translates it into java code for you; xjc采用XML模式定义,并为您将其转换为Java代码; you then have only to include the resulting java files in your project. 然后,您只需要在项目中包括生成的Java文件即可。 Most Java development tools will handle this for you automatically. 大多数Java开发工具都会自动为您处理此问题。 To generate the code I used as a source for the examples above (I did some condensing, I wrote the following schema: 为了生成用作以上示例的源代码(我做了一些压缩,编写了以下模式:

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

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

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