Простая XML-десериализация различных типов элементов с одним и тем же именем

Я пытаюсь десериализовать этот фрагмент XML в Java:

<anime id="16986">
    <info type="Picture" src="http://~.jpg" width="141" height="200">
        <img src="http://~" width="141" height="200"/>
        <img src="http://~" width="318" height="450"/>
    </info>
    <info type="Main title" lang="EN">Long Riders!</info>
    <info type="Alternative title" lang="JA">ろんぐらいだぁす!</info>
</anime>

Проблема, с которой я сталкиваюсь, заключается в том, что элемент info либо может иметь встроенный список img, либо просто содержать текст. Я думал рассматривать info как @Element в моем классе AnimeHolder, но я не могу иметь повторяющиеся аннотации. Я также хотел бы получить доступ к атрибуту lang информации, чтобы проверить, является ли он EN или JP.

Я использую эти классы для хранения десериализованных данных:

@Root(name="anime", strict=false)
public class AnimeHolder {

    @Attribute(name="id")
    private String ANNID;

    @ElementList(inline=true)
    private List<InfoHolder> infoList;

    public String getANNID() {
        return ANNID;
    }

    public List<InfoHolder> getInfoList() {
        return infoList;
    }
}

и для информационных элементов:

@Root(name="info", strict = false)
public class InfoHolder {

    @ElementList(inline=true, required = false)
    private List<ImgHolder> imgList;

    @Attribute(name = "lang", required = false)
    private String language;

    public List<ImgHolder> getImgList() {
        return imgList;
    }
}

person Jake Moritz    schedule 28.09.2016    source источник
comment
Возможно, вам потребуется определить <info> как имеющий смешанный контент и обработать элементы text vs <img> в коде, например. чтобы запретить одновременное использование текста и <img>. См. Как работать с JAXB ComplexType с данными MixedContent?.   -  person Andreas    schedule 29.09.2016
comment
Спасибо! Это указало мне правильное направление. Публикую свое решение.   -  person Jake Moritz    schedule 29.09.2016


Ответы (1)


С Андреасом я обнаружил, что мне нужно изучить обработку смешанного контента. Поиск привел меня к этому решению о создании пользовательского Converter. Написав свой собственный и обнаружив, что он не вызывается, это помогло разобраться. Вот мой переработанный класс InfoHolder и преобразователь:

@Root(name="info", strict = false)
@Convert(InfoHolder.InfoConverter.class)
public class InfoHolder {

    private String englishTitle;
    private String imageURL;

    static class InfoConverter implements Converter<InfoHolder> {
        @Override
        public InfoHolder read(InputNode node) throws Exception {
            String value = node.getValue();
            InfoHolder infoHolder = new InfoHolder();

            if (value == null){
                InputNode nextNode = node.getNext();
                while (nextNode != null){
                    String tag = nextNode.getName();

                    if (tag.equals("img") && nextNode.getAttribute("src") != null){
                        infoHolder.imageURL = nextNode.getAttribute("src").getValue();
                    }
                    nextNode= node.getNext();
                }
            } else {
                while (node != null){
                    if (node.getAttribute("lang") != null){
                        if (node.getAttribute("lang").getValue().equals("EN")){
                            infoHolder.englishTitle = value;
                            break;
                        }
                    }
                    node = node.getNext();
                }
            }

            return infoHolder;
        }

        @Override
        public void write(OutputNode node, InfoHolder value) throws Exception {

        }
    }
}

Мне также нужно было создать экземпляр SimpleXmlConverterFactory с Serializer, используя AnnotationStrategy, например:

SimpleXmlConverterFactory factory = SimpleXmlConverterFactory.create(new Persister(new AnnotationStrategy()));

Использование пользовательского преобразователя открыло узлы XML, что позволило мне выяснить, есть ли у узла info img дочерние элементы, и, если нет, получить само значение узла.

person Jake Moritz    schedule 29.09.2016