1

I'm trying to deserialize this snippet of XML in 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>

The problem I'm running into is that the info element either can have an inline list of img's or it can just contain text. I was thinking of treating info as an @Element in my AnimeHolder class, but I can't have duplicate annotations. I would also like to access the lang attribute of info to check if it is EN or JP.

I am using these classes to hold the deserialized data:

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

and for the info items:

@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;
    }
}
2
  • 1
    You may need to define <info> as having "mixed" content and handle the text vs <img> elements in code, e.g. to disallow having both text and <img> at the same time. See "How to deal with JAXB ComplexType with MixedContent data?". Commented Sep 28, 2016 at 21:24
  • Thanks! That pointed me in the right direction. Posting my solution. Commented Sep 29, 2016 at 1:09

1 Answer 1

0

With Andreas' I found out I needed to look into handling mixed content. Doing some searching lead me to this solution about creating a custom Converter. After writing my own and finding out it wasn't being called, this helped sort it out. Here is my re-worked InfoHolder class and converter:

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

        }
    }
}

I also needed to instantiate a SimpleXmlConverterFactory with a Serializer using AnnotationStrategy like so:

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

Using a custom Converter exposed the XML nodes, which allowed me to figure out if the info node had img children, and if not, get the node value itself.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.