如何使用 JDOM2 使用 CDATA 转换 XML 文档?
How to transform XML document with CDATA using JDOM2?
源文件:
<content><![CDATA[>&< test]]></content>
XSLT 文档 (cdata-transformation.xslt):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" cdata-section-elements="transformed" />
<xsl:template match="/content">
<transformed>
<xsl:value-of select="." />
</transformed>
</xsl:template>
</xsl:stylesheet>
想要的结果:
<?xml version="1.0" encoding="UTF-8"?>
<transformed><![CDATA[>&< test]]></transformed>
实际结果:
<?xml version="1.0" encoding="UTF-8"?>
<transformed>>&< test</transformed>
用于使用 JDOM2 进行测试的代码:
import java.io.IOException;
import java.io.InputStream;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import org.jdom2.CDATA;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;
import org.jdom2.transform.JDOMResult;
import org.jdom2.transform.JDOMSource;
import org.junit.Test;
public class CdataTransformationTest {
@Test
public void learning_cdataTransformationWithJdom() throws Exception {
Document xslt = loadResource("xslt/cdata-transformation.xslt");
Document source = new Document(new Element("content")
.addContent(new CDATA(">&< test")));
Document transformed = transform(source, xslt);
XMLOutputter outputter = new XMLOutputter();
System.out.println(outputter.outputString(transformed));
}
private static Document transform(Document sourceDoc, Document xsltDoc) throws TransformerException {
JDOMSource source = new JDOMSource(sourceDoc);
JDOMResult result = new JDOMResult();
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(new JDOMSource(xsltDoc));
transformer.transform(source, result);
return result.getDocument();
}
private static Document loadResource(String resource) throws IOException, JDOMException {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = classloader.getResourceAsStream(resource);
if (inputStream != null) {
try {
SAXBuilder builder = new SAXBuilder();
return builder.build(inputStream);
} finally {
inputStream.close();
}
} else {
return null;
}
}
}
使用的 JDOM 版本:
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6</version>
</dependency>
使用的 XSLT 处理器:
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.7.1</version>
</dependency>
我四处寻找执行此操作的方法,最好的答案是在 CDATA 中包装内容所需的是在 cdata-section-elements
属性中添加标签名称。我无法让它与 JDOM 一起使用,也无法在使用 Free online XSL Transformer 时使用。我也尝试过使用 saxon 而不是 xalan,但结果相同。
为什么这行不通?我 missing/doing 哪里错了? JDOM 是否忽略了 cdata-section-elements
属性?
我也试过这样包装内容:
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:value-of select="." />
<xsl:text disable-output-escaping="yes">]]></xsl:text>
但这会在 JDOM 中产生不需要的结果,使其难以使用。设置 outputer.getFormat().setIgnoreTrAXEscapingPIs(true);
时可见,使用漂亮格式时看起来真的很难看。
<?xml version="1.0" encoding="UTF-8"?>
<transformed>
<?javax.xml.transform.disable-output-escaping?>
<![CDATA[
<?javax.xml.transform.enable-output-escaping?>
>&< test
<?javax.xml.transform.disable-output-escaping?>
]]>
<?javax.xml.transform.enable-output-escaping?>
</transformed>
您正在转换为 JDOMResult
,即树表示,而不是流或文件。像 cdata-section-elements
这样的输出指令仅在 XSLT 处理器将结果序列化为流或文件时使用,而不是在内存中构建结果树时使用。所以我认为如果你想构建 CDATA 部分作为 XSLT 的结果 cdata-section-elements
,你需要确保你写入文件或流或至少一个 StringWriter,然后你可以从该文件加载 JDOM 结果或流分别创建String.
将转换方法重写为:
private static Document transform(Document sourceDoc, Document xsltDoc) throws JDOMException, IOException, TransformerException {
StringWriter writer = new StringWriter();
JDOMSource source = new JDOMSource(sourceDoc);
Result result = new StreamResult(writer);
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(new JDOMSource(xsltDoc));
transformer.transform(source, result);
SAXBuilder builder = new SAXBuilder();
return builder.build(new StringReader(writer.toString()));
}
源文件:
<content><![CDATA[>&< test]]></content>
XSLT 文档 (cdata-transformation.xslt):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" cdata-section-elements="transformed" />
<xsl:template match="/content">
<transformed>
<xsl:value-of select="." />
</transformed>
</xsl:template>
</xsl:stylesheet>
想要的结果:
<?xml version="1.0" encoding="UTF-8"?>
<transformed><![CDATA[>&< test]]></transformed>
实际结果:
<?xml version="1.0" encoding="UTF-8"?>
<transformed>>&< test</transformed>
用于使用 JDOM2 进行测试的代码:
import java.io.IOException;
import java.io.InputStream;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import org.jdom2.CDATA;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;
import org.jdom2.transform.JDOMResult;
import org.jdom2.transform.JDOMSource;
import org.junit.Test;
public class CdataTransformationTest {
@Test
public void learning_cdataTransformationWithJdom() throws Exception {
Document xslt = loadResource("xslt/cdata-transformation.xslt");
Document source = new Document(new Element("content")
.addContent(new CDATA(">&< test")));
Document transformed = transform(source, xslt);
XMLOutputter outputter = new XMLOutputter();
System.out.println(outputter.outputString(transformed));
}
private static Document transform(Document sourceDoc, Document xsltDoc) throws TransformerException {
JDOMSource source = new JDOMSource(sourceDoc);
JDOMResult result = new JDOMResult();
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(new JDOMSource(xsltDoc));
transformer.transform(source, result);
return result.getDocument();
}
private static Document loadResource(String resource) throws IOException, JDOMException {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = classloader.getResourceAsStream(resource);
if (inputStream != null) {
try {
SAXBuilder builder = new SAXBuilder();
return builder.build(inputStream);
} finally {
inputStream.close();
}
} else {
return null;
}
}
}
使用的 JDOM 版本:
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6</version>
</dependency>
使用的 XSLT 处理器:
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.7.1</version>
</dependency>
我四处寻找执行此操作的方法,最好的答案是在 CDATA 中包装内容所需的是在 cdata-section-elements
属性中添加标签名称。我无法让它与 JDOM 一起使用,也无法在使用 Free online XSL Transformer 时使用。我也尝试过使用 saxon 而不是 xalan,但结果相同。
为什么这行不通?我 missing/doing 哪里错了? JDOM 是否忽略了 cdata-section-elements
属性?
我也试过这样包装内容:
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:value-of select="." />
<xsl:text disable-output-escaping="yes">]]></xsl:text>
但这会在 JDOM 中产生不需要的结果,使其难以使用。设置 outputer.getFormat().setIgnoreTrAXEscapingPIs(true);
时可见,使用漂亮格式时看起来真的很难看。
<?xml version="1.0" encoding="UTF-8"?>
<transformed>
<?javax.xml.transform.disable-output-escaping?>
<![CDATA[
<?javax.xml.transform.enable-output-escaping?>
>&< test
<?javax.xml.transform.disable-output-escaping?>
]]>
<?javax.xml.transform.enable-output-escaping?>
</transformed>
您正在转换为 JDOMResult
,即树表示,而不是流或文件。像 cdata-section-elements
这样的输出指令仅在 XSLT 处理器将结果序列化为流或文件时使用,而不是在内存中构建结果树时使用。所以我认为如果你想构建 CDATA 部分作为 XSLT 的结果 cdata-section-elements
,你需要确保你写入文件或流或至少一个 StringWriter,然后你可以从该文件加载 JDOM 结果或流分别创建String.
将转换方法重写为:
private static Document transform(Document sourceDoc, Document xsltDoc) throws JDOMException, IOException, TransformerException {
StringWriter writer = new StringWriter();
JDOMSource source = new JDOMSource(sourceDoc);
Result result = new StreamResult(writer);
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(new JDOMSource(xsltDoc));
transformer.transform(source, result);
SAXBuilder builder = new SAXBuilder();
return builder.build(new StringReader(writer.toString()));
}