Java 使用JAXB将多个XML元素的内容提取为文本
我有以下XML文件Java 使用JAXB将多个XML元素的内容提取为文本,java,xml,jaxb,Java,Xml,Jaxb,我有以下XML文件 <items> <title><a href="blabla">blabla</a></title> <text><a href="123">123</a></text> </items> 但是,当我在TitleHandler和TextHandler的方法“String getElement(StreamResult rt)”中放置断点时,这两
<items>
<title><a href="blabla">blabla</a></title>
<text><a href="123">123</a></text>
</items>
但是,当我在TitleHandler和TextHandler的方法“String getElement(StreamResult rt)”中放置断点时,这两个元素都使用TextHandler.class进行解组。元素“title”使用TextHandler而不是TitleHandler。
任何帮助都将受到极大的感谢
更新
XmlAnyElement注释的限制使用限制:
一个类及其超类中只能有一个带XmlAnyElement注释的JavaBean属性。
@XmlAnyElement
注释用作XML输入中未按名称映射到某些特定属性的元素的总括。这就是为什么每个类只能有一个这样的注释(包括继承的属性)。你想要的是:
public class Item implements Serializable {
private String title;
private String text;
public String getTitle() {
return title;
}
@XmlElement(name = "title")
@XmlJavaTypeAdapter(value = TitleHandler.class)
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
@XmlElement(name = "text")
@XmlJavaTypeAdapter(value = TextHandler.class)
public void setText(String text) {
this.text = text;
}
}
@xmlement
注释表示对应的属性映射到具有该名称的元素。因此Javatext
属性派生自XML
元素,而title
属性派生自
元素。由于属性和元素的名称相同,因此这也是没有@xmlement
注释的默认行为,因此可以省略它们
为了处理从XML内容到字符串而不是实际结构(如Title
类或Text
类)的转换,您需要一个适配器。这就是@XmlJavaTypeAdapter
注释的用途。它指定必须如何处理该属性的编组/解编组
请参阅以下有用的答案:
关于如何实现标题处理程序的示例
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class TitleHandler extends XmlAdapter<Object, String> {
/**
* Factory for building DOM documents.
*/
private final DocumentBuilderFactory docBuilderFactory;
/**
* Factory for building transformers.
*/
private final TransformerFactory transformerFactory;
public TitleHandler() {
docBuilderFactory = DocumentBuilderFactory.newInstance();
transformerFactory = TransformerFactory.newInstance();
}
@Override
public String unmarshal(Object v) throws Exception {
// The provided Object is a DOM Element
Element titleElement = (Element) v;
// Getting the "a" child elements
NodeList anchorElements = titleElement.getElementsByTagName("a");
// If there's none or multiple, return empty string
if (anchorElements.getLength() != 1) {
return "";
}
Element anchor = (Element) anchorElements.item(0);
// Creating a DOMSource as input for the transformer
DOMSource source = new DOMSource(anchor);
// Default transformer: identity tranformer (doesn't alter input)
Transformer transformer = transformerFactory.newTransformer();
// This is necessary to avoid the <?xml ...?> prolog
transformer.setOutputProperty("omit-xml-declaration", "yes");
// Transform to a StringWriter
StringWriter stringWriter = new StringWriter();
StreamResult result = new StreamResult(stringWriter);
transformer.transform(source, result);
// Returning result as string
return stringWriter.toString();
}
@Override
public Object marshal(String v) throws Exception {
// DOM document builder
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
// Creating a new empty document
Document doc = docBuilder.newDocument();
// Creating the <title> element
Element titleElement = doc.createElement("title");
// Setting as the document root
doc.appendChild(titleElement);
// Creating a DOMResult as output for the transformer
DOMResult result = new DOMResult(titleElement);
// Default transformer: identity tranformer (doesn't alter input)
Transformer transformer = transformerFactory.newTransformer();
// String reader from the input and source
StringReader stringReader = new StringReader(v);
StreamSource source = new StreamSource(stringReader);
// Transforming input string to the DOM
transformer.transform(source, result);
// Return DOM root element (<title>) for JAXB marshalling to XML
return doc.getDocumentElement();
}
}
正如您已经发现的,
@xmlanyement
不适合您的需要。
我不会使用DomHandler
,而是选择直截了当的方式,让JAXB为您完成所有工作
让类项
有两个元素标题
和文本
:
public class Item {
private Title title;
private Text text;
@XmlElement(name = "title")
public Title getTitle() {
return title;
}
public void setTitle(Title title) {
this.title = title;
}
@XmlElement(name = "text")
public Text getText() {
return text;
}
public void setText(Text text) {
this.text = text;
}
}
创建只有元素a
的类Title
和Text
:
public class Title {
private A a;
@XmlElement(name = "a")
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
public class Text {
private A a;
@XmlElement(name = "a")
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
创建具有属性href
和内部文本值的类A
(通过@XmlValue
):
您希望字符串
标题
包含
还是blabla
?换句话说,您需要元素的内容作为XML字符串还是只需要嵌套元素的文本?我希望字符串“title”包含“”,字符串“text”包含“”,根据对问题的评论,想法是将实际的
元素作为XML字符串,而不是作为数据结构。@G_H ah ok,我似乎错过了这个要求。我编辑了这个问题,以便更清楚地说明元素的XML内容必须作为字符串获取。谢谢您的回答。如果字段“title”不仅包含12345helloworld“好的,我发现solutions@DmitryIgumnov我做了一个编辑来显示处理一般情况的处理程序的版本。
public class Item {
private Title title;
private Text text;
@XmlElement(name = "title")
public Title getTitle() {
return title;
}
public void setTitle(Title title) {
this.title = title;
}
@XmlElement(name = "text")
public Text getText() {
return text;
}
public void setText(Text text) {
this.text = text;
}
}
public class Title {
private A a;
@XmlElement(name = "a")
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
public class Text {
private A a;
@XmlElement(name = "a")
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
public class A {
private String href;
private String value;
@XmlAttribute(name = "href")
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
@XmlValue
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}