Reputation: 23
I've tried a variety of solutions but can't seem to get this working.
I am doing an XSL transformation of XML to XML (FOP) for PDF creation. The source XML has <code> elements whose contents start with a CDATA declaration. The transformation removes newlines.
Example input XML:
<?xml version="1.0" encoding="iso-8859-1"?>
<myxml>
<code><![CDATA[import java.nio.charset.Charset;
import com.my.library.AClass;
import com.my.library.AnotherClass;
public String getStringValue(String key) {
// Just some ramblings
// Dummy code...
if (key != null && key.length() > 0) {
System.out.println(key);
}
}
]]></code>
</myxml>
Example XSL:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/strict"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
exclude-result-prefixes="fo"
>
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" cdata-section-elements="code"/>
<xsl:preserve-space elements="code" />
<fo:block font-family="Courier New" font-size="12pt" color="black"
space-after="12pt" space-before="12pt" space-before.precedence="4">
<fo:block>
<xsl:text>Copy</xsl:text>
<xsl:copy>
<xsl:value-of select="code"/>
</xsl:copy>
</fo:block>
<fo:block>
<xsl:text>Copy Text</xsl:text>
<xsl:copy>
<xsl:value-of select="code/text()"/>
</xsl:copy>
</fo:block>
<fo:block>
<xsl:text>Original</xsl:text>
<xsl:value-of select="code"/>
</fo:block>
<fo:block>
<xsl:text>Normalise space</xsl:text>
<value-of select="normalize-space(code)" disable-output-escaping="yes"/>
</fo:block>
<fo:block>
<xsl:text>Copy with extra CDATA wrapper?</xsl:text>
<xsl:copy>
<xsl:text disable-output-escaping="yes"><![CDATA[<![CDATA[]]></xsl:text>
<xsl:value-of select="code"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:copy>
</fo:block>
<fo:block>
<xsl:text>Again, an attempt to wrap</xsl:text>
<xsl:text disable-output-escaping="yes">
<![CDATA[
</xsl:text>
<xsl:value-of select="code" />
<xsl:text disable-output-escaping="yes">
]]>
</xsl:text>
</fo:block>
</fo:block>
Permutations... I have tried all permutations of the following:
In total, 6 permutations.
These settings seem to make little difference for me. The following is output for each test block:
Upvotes: 2
Views: 3031
Reputation: 20469
(Posted on behalf of the OP. This solution was an edit to the question, so I've rolled that edit back and posted this here.)
Input XML:
<?xml version="1.0" encoding="iso-8859-1"?>
<solution>
<solution_name>A Set of Functions</solution_name>
<description>Just for the sake of example</description>
<functions>
<function>
<code><![CDATA[function String getStringSafely(String textToCheck, String defaultValue) {
if (textToCheck == null || textToCheck.length() <= 0) {
return defaultValue;
}
return textToCheck;
}
]]></code>
</function>
<function><code><![CDATA[import java.nio.charset.Charset;
import com.example.library.Something;
function String doSomething(String key) {
if (key == null || key.length() <= 0) {
return "";
}
System.out.println(String.format("Yep, got a value[%1$s]", key));
}
]]></code>
</function>
</functions>
</solution>
Example XSL:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/strict"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
exclude-result-prefixes="fo"
>
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" cdata-section-elements="code"/>
<xsl:preserve-space elements="code" />
<xsl:template match="solution">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="solution-page">
<fo:region-body margin="1in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="solution-page">
<fo:flow flow-name="xsl-region-body" id="solution">
<fo:block text-align="center"
space-after="40pt" space-before="100pt" space-after.precedence="3"
font-family="Helvetica" font-weight="bold" font-size="14pt" color="#0050B2" >
<xsl:value-of select="solution_name"/>
</fo:block>
<fo:block font-family="Helvetica" font-size="12pt" color="black"
space-after="12pt" space-before="12pt" space-before.precedence="4">
<xsl:value-of select="description"/>
</fo:block>
<xsl:for-each select="functions">
<xsl:variable name="this" select="." />
<xsl:call-template name="solution_functions">
<xsl:with-param name="data" select="$this"/>
</xsl:call-template>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template name="solution_functions">
<xsl:param name="data"/>
<fo:block id="functions" break-before="page"
font-family="Helvetica"
font-weight="bold"
font-size="14pt"
color="#0050B2" space-after="12pt"
space-before="16pt" space-after.precedence="3">
Functions
</fo:block>
<xsl:for-each select="$data/function">
<xsl:variable name="this" select="." />
<xsl:call-template name="present_function">
<xsl:with-param name="data" select="$this"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="present_function">
<xsl:param name="data"/>
<fo:block
font-family="Helvetica"
font-weight="bold"
font-size="12pt"
space-after="12pt"
space-before="16pt" space-after.precedence="3">
Code
</fo:block>
<fo:block font-family="Helvetica" font-size="12pt" color="black"
space-after="12pt" space-before="12pt" space-before.precedence="4">
<fo:block>
<xsl:text>This works! Thanks ...</xsl:text>
<fo:block linefeed-treatment="preserve"
white-space-collapse="false"
white-space-treatment="preserve">
<xsl:value-of select="$data/code"/>
</fo:block>
</fo:block>
<fo:block>
[ All following examples were part of the original post. The above is the one which works. The below, kept for future reference to original question. ]
</fo:block>
<fo:block>
<xsl:text>Original</xsl:text>
<fo:block linefeed-treatment="preserve"
white-space-collapse="false"
white-space-treatment="preserve">
<xsl:value-of select="$data/code"/>
</fo:block>
</fo:block>
<fo:block>
<xsl:text>Copy</xsl:text>
<xsl:copy>
<xsl:value-of select="$data/code"/>
</xsl:copy>
</fo:block>
<fo:block>
<xsl:text>Copy Text</xsl:text>
<xsl:copy>
<xsl:value-of select="$data/code/text()"/>
</xsl:copy>
</fo:block>
<fo:block>
<xsl:text>Original</xsl:text>
<xsl:value-of select="$data/code"/>
</fo:block>
<fo:block>
<xsl:text>Normalise space</xsl:text>
<value-of select="normalize-space($data/code)" disable-output-escaping="yes"/>
</fo:block>
<fo:block>
<xsl:text>Copy with extra CDATA wrapper?</xsl:text>
<xsl:copy>
<xsl:text disable-output-escaping="yes"><![CDATA[<![CDATA[]]></xsl:text>
<xsl:value-of select="$data/code"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:copy>
</fo:block>
<fo:block>
<xsl:text>Again, an attempt to wrap</xsl:text>
<xsl:text disable-output-escaping="yes">
<![CDATA[
</xsl:text>
<xsl:value-of select="$data/code" />
<xsl:text disable-output-escaping="yes">
]]>
</xsl:text>
</fo:block>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2
Reputation: 111686
Let's clear up a few fundamental misunderstandings reflected in your code.
xsl:template
constructs. This is actually ok for simplified stylesheets that
you're attempting, but such form has no xsl:stylesheet
root
element; it simply begins with the XML root element desired in your
output XML. It then pulls from the input XML as you're doing with
xsl:value-of/@select
constructs. So, major fix #1 is to add
<xsl:template match="/">...
or remove <xsl:stylesheet>
. We'll
go with the second option (simplified stylesheets) since it seems to be what you've favoring."code/'
, select "/myxml/code"
in all of your test
cases.Here are your test cases with the above changes (and a few other minor fixes) made:
<?xml version="1.0" encoding="iso-8859-1"?>
<fo:block font-family="Courier New" font-size="12pt" color="black"
space-after="12pt" space-before="12pt" space-before.precedence="4"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xsl:version="1.0">
<fo:block>
<xsl:text>Copy</xsl:text>
<xsl:copy>
<xsl:value-of select="/myxml/code"/>
</xsl:copy>
</fo:block>
<fo:block>
<xsl:text>Copy Text</xsl:text>
<xsl:copy>
<xsl:value-of select="/myxml/code/text()"/>
</xsl:copy>
</fo:block>
<fo:block>
<xsl:text>Original</xsl:text>
<xsl:value-of select="/myxml/code"/>
</fo:block>
<fo:block>
<xsl:text>Normalise space</xsl:text>
<xsl:value-of select="normalize-space(code)" disable-output-escaping="yes"/>
</fo:block>
<fo:block>
<xsl:text>Copy with extra CDATA wrapper?</xsl:text>
<xsl:copy>
<xsl:text disable-output-escaping="yes"><![CDATA[<![CDATA[]]></xsl:text>
<xsl:value-of select="/myxml/code"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:copy>
</fo:block>
<fo:block>
<xsl:text>Again, an attempt to wrap</xsl:text>
<xsl:text disable-output-escaping="yes">
<![CDATA[
</xsl:text>
<xsl:value-of select="/myxml/code" />
<xsl:text disable-output-escaping="yes">
]]>
</xsl:text>
</fo:block>
</fo:block>
Running the above XSLT against your input XML yields more useful test results:
<?xml version="1.0" encoding="UTF-8"?><fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format" font-family="Courier New" font-size="12pt" color="black" space-after="12pt" space-before="12pt" space-before.precedence="4"><fo:block>Copyimport java.nio.charset.Charset;
import com.my.library.AClass;
import com.my.library.AnotherClass;
public String getStringValue(String key) {
// Just some ramblings
// Dummy code...
if (key != null && key.length() > 0) {
System.out.println(key);
}
}
</fo:block><fo:block>Copy Textimport java.nio.charset.Charset;
import com.my.library.AClass;
import com.my.library.AnotherClass;
public String getStringValue(String key) {
// Just some ramblings
// Dummy code...
if (key != null && key.length() > 0) {
System.out.println(key);
}
}
</fo:block><fo:block>Originalimport java.nio.charset.Charset;
import com.my.library.AClass;
import com.my.library.AnotherClass;
public String getStringValue(String key) {
// Just some ramblings
// Dummy code...
if (key != null && key.length() > 0) {
System.out.println(key);
}
}
</fo:block><fo:block>Normalise space</fo:block><fo:block>Copy with extra CDATA wrapper?<![CDATA[import java.nio.charset.Charset;
import com.my.library.AClass;
import com.my.library.AnotherClass;
public String getStringValue(String key) {
// Just some ramblings
// Dummy code...
if (key != null && key.length() > 0) {
System.out.println(key);
}
}
]]></fo:block><fo:block>Again, an attempt to wrap
<![CDATA[
import java.nio.charset.Charset;
import com.my.library.AClass;
import com.my.library.AnotherClass;
public String getStringValue(String key) {
// Just some ramblings
// Dummy code...
if (key != null && key.length() > 0) {
System.out.println(key);
}
}
]]>
</fo:block></fo:block>
I believe from there you'll be able to identify the test case results that produce the results you seek.
Upvotes: 1
Reputation: 66783
Put your code inside of an fo:block and set the following attributes to control the treatment of whitespace and carriage returns:
Like this:
<fo:block>
<xsl:text>Original</xsl:text>
<fo:block linefeed-treatment="preserve"
white-space-collapse="false"
white-space-treatment="preserve">
<xsl:value-of select="code"/>
</fo:block>
</fo:block>
Upvotes: 1