开发者

Inner Text and child elements

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 clas开发者_如何学运维s 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);
        }
    }
}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜