使用XSLT编译的转换时,我无法完全将输出格式化,它总是去掉所有空格,并且不是人类可读的形式。
但是,如果我通过Visual studio XSLT调试器运行相同的转换,则输出会整齐地缩进。以下是我的代码:
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);
}
转换将创建一个文本文件,Visual studio的XSLT调试器在保留输出格式方面有什么不同之处?
我已经看了这个链接:XSLT转换没有正确缩进
当我输出到文本时,这不适用于我。我应该使用Stream以外的东西吗?
我的示例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>
预期输出:
{Start:
Value1
value2
End:}
使用XSLT编译的转换输出:{Start:Value1value2End:}
VisualStudioXSLT调试器为我提供了预期的输出格式,但XSLT编译的转换去掉了所有空格和新行。
不幸的是,这实际上还不是一个完整的代码示例。请阅读我之前提供的链接,了解我的意思。
也就是说,经过一些努力,我能够把这些零碎的东西放在一起,创建一个单独的、自包含的代码示例。我能够验证您的担忧,我能够通过将您使用的disable-output-escaping
(不需要)替换为xml:space="preserve"
(需要)来解决这一问题。
请注意,XSL转换的一部分是首先生成一个表示输出的XML图。只有在完成之后,才能创建实际的输出。在此过程中,会从文档中删除单独存在的空白。通过添加xml:space="preserve"
,您可以告诉处理代码不要删除独立的空白。
以下是您的XSL的一个版本,它按照您想要的方式工作:
<?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>
注:
- 我不得不添加
</xsl:stylesheet>
结束标记 - 我将CR实体

更改为LF实体

。它也可以像以前那样处理回车,但从可读性的角度来看,我觉得换行更"便携" - 在上面的例子中,我将
xml:space="preserve"
应用于每个只包含空白的xsl:text
元素。这样可以确保处理器不会删除这些元素
在最后一点上有一个权衡。正如您将注意到的,这意味着您必须在每个xsl:text
节点上指定要保留空白的属性。以牺牲XSL可读性为代价的另一种选择是将属性应用于整个样式表:
<?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>
显然,缺点是每个模板的内容必须只包含空格,您希望它出现在输出中的位置。因此,不能使用空白来提高XSL本身的可读性。但至少你不必一遍又一遍地键入xml:space="preserve"
。您选择。:)
我想从技术上讲,这意味着这毕竟不是一个C#问题。可能应该从你的问题中删除该标签。:)