java - 使用 JAXB 解码嵌套 XML 元素

标签 java xml class dictionary jaxb

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

当我尝试映射嵌套元素(例如绝对元素)时,我的问题就出现了,它可以包含任意数量的 <absolute-item>元素。我现在正在尝试:

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 不是编译属性,但我不知道它意味着什么。我是否应该为 <relative> 再创建一个类元素?

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 处理假定每个复杂元素都有一个单独的元素定义。复杂元素是指包含其他元素的元素。

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

为了解码(从 xml 文本转换为 Java 代码)您上面提供的数据结构,JAXB 例程将期望找到以下公共(public)类定义:

绝对 元素 地点 对象工厂 相对

在 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 希望找到公共(public) Absolute 和relative 类。由于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;
   }

}

根据我的经验,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>

关于java - 使用 JAXB 解码嵌套 XML 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49181125/

相关文章:

java - 从 Android Java 调用 ndk c++ 函数后,字符串得到一个奇怪的形式

java - 如何创建这样的 Java swing UI?

java - 在类(而不是 Activity )之间传递数据会导致空指针异常

javascript - 具有默认参数值的 es6 类构造函数上的 NodeJS 错误

python - 属性还是方法?

java - 如何将数据存储在以下结构中?

java - 在单独的线程中运行一个进程,以便 Java FX 应用程序的其余部分可用?

java - 单击按钮后打开一个新 Activity

wpf - 部署 WPF 应用程序时包括 xml 文件

python - 使用 python 更改 xml