Java 使用JAXB将多个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)”中放置断点时,这两

我有以下XML文件

<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
注释表示对应的属性映射到具有该名称的元素。因此Java
text
属性派生自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”不仅包含12345

helloworld
“好的,我发现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;
    }
}