JAXB - 将继承用于动态标记名称

ABR*_*ABR 2 java xml inheritance jaxb

我试图使用JAXB将XML编组为类heiarchy - 我希望heiarchy以通用方式使用继承.我会更好地解释一下:

我有以下XML:

<Country name="USA">
    <City name="NewYork">
      <Street name="Something"/>
      <Street name="Something2"/>
    </City>
    <City name="LosAngeles">
       <Street name="Something"/>
       <Street name="Something2"/>
    </City>
<Country>
<Country .....>
   <.....>
    <.....
</Country>
Run Code Online (Sandbox Code Playgroud)

等eatch国家可以有多个城市,每个城市可以有多条街道.

我想创建一个名为GeneralLocation的类,它看起来像这样:

 @XmlTransient
    public abstract class GeneralLocation {

        private String name;
        protected List<GeneralLocation> sons;


        @XmlAttribute(name="name")  
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public List<GeneralLocation> getSons(){
              return this.sons
        }

        public void setSons(List<GeneralLocation> sons){
              this.sons = sons;
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后创建Country,City和Street类以从GeneralLocation继承并使用正确的JAXB解析名称覆盖getSons方法.

public class Country extends GeneralLocation{

        @XmlElement(name="City")
        public List<GeneralLocation> getSons(){
              return this.sons
        }

        public void setSons(List<GeneralLocation> sons){
              this.sons = sons;
        }
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试过这个基本代码的各种变体,但没有一个能够完成这项工作.我没有添加任何特定的一个,因为他们都抛出了一些似乎表明我真的不在正确的道路上的奇怪的例外,所以我决定添加这个基本的骨架并希望你们的任何指针......

谁能帮我这个?谢谢

bdo*_*han 5

您可以将@XmlElementRef注释用于您的用例.

Java模型

GeneralLocation

您可以@XmlElementRefsons属性上使用注释.XML中元素的名称将基于与引用的对象的子类关联的根元素.

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlSeeAlso({Country.class, City.class, Street.class})
public abstract class GeneralLocation {

    private String name;
    protected List<GeneralLocation> sons;

    @XmlAttribute(name="name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlElementRef
    public List<GeneralLocation> getSons(){
        return this.sons;
    }

    public void setSons(List<GeneralLocation> sons){
        this.sons = sons;
    }

}
Run Code Online (Sandbox Code Playgroud)

国家

子类不需要覆盖该sons属性.他们唯一需要的是@XmlRootElement注释将用于派生元素名称的@XmlElementRef注释GeneralLocation.

import javax.xml.bind.annotation.*;

@XmlRootElement(name="Country")
public class Country extends GeneralLocation {
}
Run Code Online (Sandbox Code Playgroud)

import javax.xml.bind.annotation.*;

@XmlRootElement(name="City")
public class City extends GeneralLocation {
}
Run Code Online (Sandbox Code Playgroud)

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="Street")
public class Street extends GeneralLocation {
}
Run Code Online (Sandbox Code Playgroud)

演示代码

下面是一些示例代码,它将XML解组为对象,然后再将其封送回XML.请注意,由于我们@XmlSeeAlsoGeneralLocation类上使用了注释,因此在引导时我们不需要指定所有子类JAXBContext.

演示

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(GeneralLocation.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("input.xml");
        GeneralLocation result = (GeneralLocation) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(result, System.out);
    }

}
Run Code Online (Sandbox Code Playgroud)

input.xml中/输出

你问题中的XML无效,因为你没有一个根元素,所以对于我的回答,我选择只使用一个国家.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Country name="USA">
    <City name="NewYork">
        <Street name="Something"/>
        <Street name="Something2"/>
    </City>
    <City name="LosAngeles">
        <Street name="Something"/>
        <Street name="Something2"/>
    </City>
</Country>
Run Code Online (Sandbox Code Playgroud)