2016-01-15 6 views
1

Источник документа:Как преобразовать документ XML с помощью CDATA с помощью 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> 

Wanted результат:

<?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 и Saxon (см http://xsltransform.net/94rmq6A) - так что проблема не с кодом, но с процессором. –

ответ

2

Вы преобразовывают к JDOMResult, то есть дерево представление, а не в поток или файл. Директивы вывода, такие как cdata-section-elements, используются только тогда, когда процессор XSLT преобразует результат в поток или файл, но не при построении результирующего дерева в памяти. Поэтому я думаю, что если вы хотите построить разделы CDATA в результате XSLT с cdata-section-elements, вам нужно убедиться, что вы пишете файл или поток или, по крайней мере, 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

Спасибо, Мартин, я не знал об этом. Добавлен модифицированный код, необходимый для работы в вашем ответе. Это дает желаемый результат. –

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