Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inner Text and child elements

Tags:

java

xml

jaxb

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);
        }
    }
}
like image 773
rhollencamp Avatar asked May 12 '11 16:05

rhollencamp


People also ask

What is inner text of an element?

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.

What is a child element?

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.

What is the difference between textContent and innerText?

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.

What is difference between innerHTML and innerText?

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.


1 Answers

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.

like image 153
skaffman Avatar answered Sep 24 '22 05:09

skaffman