内部文本和子元素
我想在 Java 中使用 JAXB 反序列化 XML,如下所示:
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>
让我失望的是捕获 <container>
的内部文本:我不能同时使用 @XmlValue
来获取内部文本和@XmlElement
获取内部文本之后的 foo 元素.请参阅下文,了解我要做什么的大纲
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);
}
}
}
这被称为混合模式内容",通常处理起来很麻烦.
This is called "mixed-mode content", and it's generally a pain in the ass to process.
JAXB 中的关键是使用 @XmlMixed
注释 - 参见 javadoc.
The key in JAXB is to use the @XmlMixed
annotation - see javadoc.
试试这样的:
@XmlRootElement(name = "container")
static class Container {
@XmlMixed
@XmlElementRefs({
@XmlElementRef(name="foo", type=Foo.class)
})
List<?> content;
// ... plus the usual getters/setters
}
content
列表应该包含一系列 Foo
对象和字符串.
The content
list should contain a sequence of Foo
objects and Strings.