gpt4 book ai didi

java - 使用 JAXB 将多个 XML 元素的内容提取为文本

转载 作者:行者123 更新时间:2023-11-29 04:31:01 26 4
gpt4 key购买 nike

我有以下 XML 文件

<items>
<title><a href="blabla">blabla</a></title>
<text><a href="123">123</a></text>
</items>

我通过 JAXB 和 XmlAnyElement 注释将 XML 解码为下一个 java 对象,其中两个类实现了 DOMHandler。我想将元素“title”和“text”的内部 XML 提取为字符串。

public class Item implements Serializable {
private String title;
private String text;

public String getTitle() {
return title;
}
@XmlAnyElement(value = TitleHandler.class)
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
@XmlAnyElement(value = TextHandler.class)
public void setText(String text) {
this.text = text;
}
}

但是当我在 TitleHandler 和 TextHandler 的方法“String getElement(StreamResult rt)”中放置断点时,两个元素都使用 TextHandler.class 进行解码。元素“title”使用 TextHandler 而不是 TitleHandler。任何帮助将不胜感激

更新XmlAnyElement 注解的限制使用约束:一个类及其父类(super class)中只能有一个 XmlAnyElement 注释的 JavaBean 属性。

最佳答案

@XmlAnyElement annotation 用作 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;
}
}

@XmlElement annotation 指示相应的属性映射到具有该名称的元素。所以 Java text属性源自 XML <text>元素,以及 title来自 <title> 的属性(property)元素。由于属性和元素的名称相同,这也是没有 @XmlElement 的默认行为。注释,因此您可以将它们省略。

为了处理从 XML 内容到字符串而不是实际结构(如 Title 类或 Text 类)的转换,您需要一个适配器。这就是@XmlJavaTypeAdapter注释是为了。它指定必须如何处理该属性的编码/解码。

查看这个有用的答案:https://stackoverflow.com/a/18341694/630136

如何实现 TitleHandler 的示例.

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();
}

}

如果解码输入/编码输出的类型保留为 Object ,JAXB 将提供 DOM 节点。上面使用 XSLT 转换(虽然没有实际的样式表,只是一个“身份”转换)将 DOM 输入转换为字符串,反之亦然。我已经在一个最小的输入文档上对其进行了测试,它适用于 XML 到 Item。对象,反之亦然。

编辑:

以下版本将处理 <title> 中的任何 XML 内容而不是期待一个<a>元素。你可能想把它变成一个抽象类然后有 TitleHanderTextHandler扩展它,以便当前硬编码的 <title>标签由实现提供。

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;

/**
* XSLT that will strip the root element. Used to only take the content of an element given
*/
private final static String UNMARSHAL_XSLT = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<xsl:transform xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n" +
"\n" +
" <xsl:output method=\"xml\" omit-xml-declaration=\"yes\" />\n" +
"\n" +
" <xsl:template match=\"/*\">\n" +
" <xsl:apply-templates select=\"@*|node()\"/>\n" +
" </xsl:template>\n" +
"\n" +
" <xsl:template match=\"@*|node()\">\n" +
" <xsl:copy>\n" +
" <xsl:apply-templates select=\"@*|node()\"/>\n" +
" </xsl:copy>\n" +
" </xsl:template>\n" +
" \n" +
"</xsl:transform>";

public TitleHandler() {
docBuilderFactory = DocumentBuilderFactory.newInstance();
transformerFactory = TransformerFactory.newInstance();
}

@Override
public String unmarshal(Object v) throws Exception {
// The provided Object is a DOM Element
Element rootElement = (Element) v;
// Creating a DOMSource as input for the transformer
DOMSource source = new DOMSource(rootElement);
// Creating a transformer that will strip away the root element
StreamSource xsltSource = new StreamSource(new StringReader(UNMARSHAL_XSLT));
Transformer transformer = transformerFactory.newTransformer(xsltSource);
// 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 a DOMResult as output for the transformer
DOMResult result = new DOMResult(doc);
// Default transformer: identity tranformer (doesn't alter input)
Transformer transformer = transformerFactory.newTransformer();
// String reader from the input and source
StringReader stringReader = new StringReader("<title>" + v + "</title>");
StreamSource source = new StreamSource(stringReader);
// Transforming input string to the DOM
transformer.transform(source, result);
// Return DOM root element for JAXB marshalling to XML
return doc.getDocumentElement();
}

}

关于java - 使用 JAXB 将多个 XML 元素的内容提取为文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43776239/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com