2016-02-25 3 views
0

Я пытаюсь создать объектную модель, чтобы иметь возможность вывести следующий XML с помощью JAXB:Override имя элемента внутри элемента объекта

<root version="1"> 
    <first version="1"/> 
</root> 

Или это:

<root version="1"> 
    <second version="1"/> 
</root> 

Очевидно упрощенная версия для этого примера. Может быть только подэлемент типа first или second, но не оба сразу.

Мой корневой элемент выглядит следующим образом:

@XmlRootElement(name = "root") 
public class ExampleRootElement { 
    private int version; 
    private ExampleBaseSubElement subElement; 

    @XmlAttribute(name = "version") 
    public int getVersion() { 
     return version; 
    } 

    public void setVersion(int version) { 
     this.version = version; 
    } 

    public ExampleBaseSubElement getSubElement() { 
     return subElement; 
    } 

    public void setSubElement(ExampleBaseSubElement subElement) { 
     this.subElement = subElement; 
    } 
} 

Поскольку дочерний элемент должен быть либо first или second я создал пустой абстрактный класс манекена ExampleBaseSubElement простирается от в конкретных классах для first и second. Я бы использовал интерфейс здесь, но, судя по всему, JAXB не может справиться с этим. (Я обычно делал такого рода вещи в C#, так что простите меня, если это очень плохой способ сделать это в Java с помощью JAXB)

Фиктивная класс:

public abstract class ExampleBaseSubElement { 
} 

Код для first:

@XmlRootElement(name="first") 
public class ExampleFirstSubElement extends ExampleBaseSubElement { 
    private int version; 

    @XmlAttribute(name="version") 
    public int getVersion() { 
     return version; 
    } 

    public void setVersion(int version) { 
     this.version = version; 
    } 
} 

Код для second: (Только ради этого образца в значительной степени так же, как first)

@XmlRootElement(name = "second") 
public class ExampleSecondSubElement extends ExampleBaseSubElement { 
    private int version; 

    @XmlAttribute(name = "version") 
    public int getVersion() { 
     return version; 
    } 

    public void setVersion(int version) { 
     this.version = version; 
    } 
} 

Что, вероятно, неверно, так это мое ожидание установки имени элемента из класса с помощью аннотации XmlRootElement, потому что оно не работает. Я пытался создать нужный вывод XML путем создания ExampleRootElement с вложенной ExampleFirstSubElement как это:

ExampleRootElement exampleRootElement = new ExampleRootElement(); 
exampleRootElement.setVersion(1); 
ExampleFirstSubElement exampleFirstSubElement = new ExampleFirstSubElement(); 
exampleFirstSubElement.setVersion(1); 
exampleRootElement.setSubElement(exampleFirstSubElement); 

JAXBContext jaxbContext = JAXBContext.newInstance(ExampleRootElement.class); 
Marshaller marshaller = jaxbContext.createMarshaller(); 
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 

marshaller.marshal(exampleRootElement, System.out); 

Это приводит к:

<root version="1"> 
    <subElement/> 
</root> 

Ожидалось:

<root version="1"> 
    <first version="1"/> 
</root> 

Хорошо, я понимаю, что это не работает. Аннотацию просто игнорируют. Вероятно, потому что JAXB не разрешает расширенный тип, что объясняет, почему отсутствует атрибут version для вложенного элемента. И я очень уверен в том, что unmarshalling это провалится еще тяжелее ...

Итак, мой вопрос: я пропустил какую-то магическую аннотацию здесь, чтобы это могло работать так, как предполагалось, или это совсем не тот подход, и если да, то в чем лучшая практика?

ответ

0

Хорошо, после того, как мастерить вокруг с различными примечаниями (в основном грубой заставляя его) я придумал следующее решение:

Добавление XmlSeeAlso в абстрактный базовый класс ExampleBaseSubElement:

@XmlSeeAlso({ 
     ExampleFirstSubElement.class, 
     ExampleSecondSubElement.class 
}) 
public abstract class ExampleBaseSubElement { 
} 

Добавление XmlElementRef к добытчиком subElement в пределах ExampleRootElement:

@XmlRootElement(name = "root") 
public class ExampleRootElement { 
    private int version; 
    private ExampleBaseSubElement subElement; 

    @XmlAttribute(name = "version") 
    public int getVersion() { 
     return version; 
    } 

    public void setVersion(int version) { 
     this.version = version; 
    } 

    @XmlElementRef // here! 
    public ExampleBaseSubElement getSubElement() { 
     return subElement; 
    } 

    public void setSubElement(ExampleBaseSubElement subElement) { 
     this.subElement = subElement; 
    } 
} 

Теперь это приводит к ожидаемому выходу:

<root version="1"> 
    <first version="1"/> 
</root> 

Я до сих пор не уверен, если это плохо в целом или на самом деле, как это должно быть сделано. Это работает, и я надеюсь, что это поможет кому-то, кто сталкивается с той же проблемой.

+0

Hello Num Lock вы можете взглянуть на этот вопрос? http://stackoverflow.com/questions/41875849/how-to-utilize-jaxb-for-object-serialization-for-sub-elements-with-same-tag-name/41876211?noredirect=1#comment70978243_41876211 – Jesse

Смежные вопросы