...">

Inner text and children

I would like to deserialize XML as follows 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> 

What turns me off is capturing the inner text of <container> : I cannot use both @XmlValue to get the inner text and @XmlElement to capture the foo elements that appear after the inner text. See below for a diagram of what I'm looking for.

 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); } } } 
+6
source share
1 answer

This is called “mixed-mode content,” and is usually a pain in the ass for processing.

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.

+4
source

Source: https://habr.com/ru/post/887948/


All Articles