如何使用JDOM2使用CDATA转换XML文档?

时间:2016-01-15 13:18:41

标签: xslt cdata jdom-2

来源文件:

<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>&gt;&amp;&lt; 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,但结果相同。

为什么这不起作用?我在这里错过了什么/做错了什么? JDOM是否忽略cdata-section-elements属性?

我也试过包装这样的内容:

<xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
<xsl:value-of select="." />
<xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>

但是这会在JDOM中产生不需要的结果,这使得它很难使用。设置outputer.getFormat().setIgnoreTrAXEscapingPIs(true);时可见,使用漂亮格式时看起来很难看。

<?xml version="1.0" encoding="UTF-8"?>
<transformed>
  <?javax.xml.transform.disable-output-escaping?>
  &lt;![CDATA[
  <?javax.xml.transform.enable-output-escaping?>
  &gt;&amp;&lt; test
  <?javax.xml.transform.disable-output-escaping?>
  ]]&gt;
  <?javax.xml.transform.enable-output-escaping?>
</transformed>

2 个答案:

答案 0 :(得分:2)

您正在转换为JDOMResult,即树形表示,而不是流或文件。像cdata-section-elements这样的输出指令仅在XSLT处理器将结果序列化为流或文件时使用,而不是在内存中构建结果树时使用。所以我认为如果你想用cdata-section-elements作为XSLT的结果来构造CDATA部分,你需要确保你写一个文件或流或至少一个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()));
}

答案 1 :(得分:0)

试试这个:

<?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"  encoding="utf-8"/>

  <xsl:template match="/content">
    <transformed>
      <xsl:value-of disable-output-escaping="yes" select="."/>
    </transformed>
  </xsl:template>
</xsl:stylesheet>

我使用了msxsl命令行工具,它工作正常!

> msxsl.exe source.xml tamplate.xslt > output.xml