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);
}
}
}
The innerText property of the HTMLElement interface represents the rendered text content of a node and its descendants. As a getter, it approximates the text the user would get if they highlighted the contents of the element with the cursor and then copied it to the clipboard.
A child element will be included in a UC award where a claimant is responsible for a child or qualifying young person who normally lives with them. Where a child lives in 2 separate households, claimants will be expected to agree who has main responsibility and claim accordingly.
textContent gets the content of all elements, including <script> and <style> elements. In contrast, innerText only shows "human-readable" elements. textContent returns every element in the node. In contrast, innerText is aware of styling and won't return the text of "hidden" elements.
innerText returns all text contained by an element and all its child elements. innerHtml returns all text, including html tags, that is contained by an element.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With