When working with XSLT Compiled Transform I can't quite get output to format, it always strips all the spaces and is not in human readable form.
However If I run the same transform through Visual studio XSLT Debugger the output is neatly indented.Here is what my code looks like:
XDocument xDoc = XDocument.Load(_xmlFilePath, LoadOptions.PreserveWhitespace);
var xslDoc = new XmlDocument();
xslDoc.Load(_xsltFilePath);
xslDoc.PreserveWhitespace = true;
using (Stream outputFile = File.Create(_outputFileName))
{
XsltArgumentList xsltParameter = null;
StringReader tr = new StringReader(xslDoc.OuterXml);
XmlReader xr = new XmlTextReader(tr);
XslCompiledTransform transform = new XslCompiledTransform();
XsltSettings setting = new XsltSettings();
setting.EnableScript = true;
transform.Load(xr, setting, new XmlUrlResolver());
transform.Transform(xDoc.CreateReader(), xsltParameter, outputFile);
}
The transform would create a text file ,what is the Visual studio's XSLT Debugger doing differently that it preserves output formatting?
I have already taken a look at this link:XSLT Transform not indenting properly
This doesn't apply to me as I output to text. Should I be using something other than Stream ?
My sample XSLT :
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root">
<xsl:text>{Start:</xsl:text>
<xsl:text disable-output-escaping="yes">
</xsl:text>
<xsl:value-of select="Child1"/>
<xsl:text disable-output-escaping="yes">
</xsl:text>
<xsl:value-of select="Child2"/>
<xsl:text disable-output-escaping="yes">
</xsl:text>
<xsl:text>End:}</xsl:text>
</xsl:template>
<?xml version="1.0" encoding="utf-8"?>
<root>
<Child1>Value1</Child1>
<Child2>value2</Child2>
</root>
Expected Output:
{Start:
Value1
value2
End:}
Output with XSLT Compiled transform:
{Start:Value1value2End:}
Visual Studio XSLT debugger gives me the expected output format but XSLT Compiled transform strips all spaces and new line.
Unfortunately, that's still not actually a complete code example. Please read the link I provided earlier to see what I mean.
That said, after some effort, I was able to take the bits and pieces and create a single, self-contained code example. I was able to verify your concern, which I was able to address by replacing your use of disable-output-escaping
(which is not needed) with xml:space="preserve"
, which is needed.
Note that part of the XSL transform is to first generate an XML graph representing your output. Only after that's done is the actual output created. In the process, whitespace that stands alone is removed from the document. By adding xml:space="preserve"
, you tell the processing code to not remove that stand-alone whitespace.
Here is a version of your XSL that works the way you want:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root">
<xsl:text>{Start:</xsl:text>
<xsl:text xml:space="preserve">
</xsl:text>
<xsl:value-of select="Child1"/>
<xsl:text xml:space="preserve">
</xsl:text>
<xsl:value-of select="Child2"/>
<xsl:text xml:space="preserve">
</xsl:text>
<xsl:text>End:}</xsl:text>
</xsl:template>
</xsl:stylesheet>
Notes:
</xsl:stylesheet>
closing tag
to LF entities 

. It also works with carriage returns the way you had it, but I feel line-feeds are more "portable" from a readability point of view.xml:space="preserve"
to each xsl:text
element that contains only whitespace. This ensures that the processor doesn't remove these elements.There is a trade-off on that last point. As you'll note, it means you have to specify that attribute on each xsl:text
node where you want to preserve whitespace. An alternative, at the expense of readability of the XSL, is to apply the attribute to the entire stylesheet:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xml:space="preserve">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/"><xsl:apply-templates/></xsl:template>
<xsl:template match="root"><xsl:text>{Start:</xsl:text><xsl:text>
</xsl:text><xsl:value-of select="Child1"/><xsl:text xml:space="preserve">
</xsl:text><xsl:value-of select="Child2"/><xsl:text xml:space="preserve">
</xsl:text><xsl:text>End:}</xsl:text></xsl:template>
</xsl:stylesheet>
Obviously the downside is that the contents of each template must contain whitespace only where you want it to appear in the output. So you can't use whitespace to make the XSL itself more readable. But at least you don't have to type xml:space="preserve"
over and over. You pick. :)
I guess technically this means this isn't a C# question after all. Probably should remove that tag from your question. :)