Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I would like to deserialize XML like the following using JAXB in Java:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <container>
        inner text that I need
        <foo attrib="meh">
            <bar>value</bar>
        </foo>
    </container>
</root>

The thing that is tripping me up is capturing the inner text of <container>: I can't use both an @XmlValue to get the inner text and @XmlElement to grab foo elements that come after the inner text. See below for an outline of what I am looking to do

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;

public class App {

    private static final String xml = "<?xml version="1.0" encoding="UTF-8"?><root><container>text<foo attrib="meh"><bar>waffles</bar></foo></container></root>";

    @XmlRootElement(name = "foo") static class Foo {
        @XmlAttribute public String attrib;
        @XmlElement   public String bar;
    }

    @XmlRootElement(name = "container") static class Container {
        //@XmlValue   public String innerText;
        @XmlElement public Foo foo;
    }

    public static void main(String[] args) {
        try {
            final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
            final XMLEventReader xer = xmlInputFactory.createXMLEventReader(new ByteArrayInputStream(xml.getBytes("UTF-8")));

            XMLEvent evt = xer.nextEvent(); // start document
            evt = xer.nextEvent(); // <root>
            evt = xer.peek(); // advance to <container>

            JAXBContext ctx = JAXBContext.newInstance(Container.class);
            Unmarshaller um = ctx.createUnmarshaller();
            Object o = um.unmarshal(xer);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
        } catch (XMLStreamException ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
        } catch (JAXBException ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
361 views
Welcome To Ask or Share your Answers For Others

1 Answer

This is called "mixed-mode content", and it's generally a pain in the ass to process.

The key in JAXB is to use the @XmlMixed annotation - see javadoc.

Try something like this:

@XmlRootElement(name = "container") 
static class Container {
    @XmlMixed 
    @XmlElementRefs({
            @XmlElementRef(name="foo", type=Foo.class)
    })
    List<?> content;

    // ... plus the usual getters/setters
}

The content list should contain a sequence of Foo objects and Strings.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...