2016-01-15 53 views
1

源文檔:如何使用JDOM2將CDATA轉換爲CDATA?

<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> 
+1

FWIW,你的方法確實既Xalan和撒克遜人的工作(見:http://xsltransform.net/94rmq6A) - 這樣的問題是不是與代碼,但與處理器。 –

回答

2

您正在轉換爲JDOMResult,即樹表示形式,而不是流或文件。像cdata-section-elements這樣的輸出指令僅在XSLT處理器將結果序列化到流或文件時使用,而不是在內存中構建結果樹時使用。所以我想如果你想用XSLT的結果構建CDATA部分,你需要確保你寫入文件或者流或者至少是一個StringWriter,然後你可以從分別創建的文件或者流中加載JDOM結果串。

重寫變換的方法:

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

感謝Martin,我不知道這一點。添加修改後的代碼,使其在您的答案中發揮作用。這產生了所需的輸出。 –

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