【发布时间】:2019-09-20 14:57:18
【问题描述】:
问题
如何利用 XSL 提供由运行代码确定的条件格式(例如,表格行之间的增加或减少)?
背景
编辑: 这是一个使用 ASP.NET Core 作为主机运行的 BackgroundService 实现,用于审计外部资源的运行状况的长期运行服务。这可能是 .NET Core 缺少 .NET Framework 中存在的某些功能的问题,所以我认为值得一提
这个想法之所以开始,是因为我一直在寻找一种方法来制作一个简单的 HTML 模板,我的 C# 数据对象可以以一种不涉及操作 StringBuilder 的简单有效的方式映射到该模板。为此,我找到了this StackOverflow response,它说 XSLT 将是一个很好的解决方案,而无需执行完整的 MVC 方法。
一切从这里开始(为简洁起见):
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="utf-8"/>
<xsl:template match='/Email'>
<html>
<head>
<style>
<xsl:value-of select="Styles"/>
</style>
</head>
<body>
<h1>Total</h1>
<table id="tblTotal" class="clsPositive">
<tr>
<th>Audit Date</th>
<th>Source 1</th>
<th>Source 2</th>
...
</tr>
<xsl:for-each select="Total/ArrayOfElement/AuditElement">
<xsl:sort select="ReportDate" order="descending"/>
<tr>
<td><xsl:value-of select="ReportDate"/></td>
<td><xsl:value-of select="Source1CountFormatted"/> (<xsl:value-of select="Source1GrowthFormatted"/>)</td>
<td><xsl:value-of select="Source2CountFormatted"/> (<xsl:value-of select="Source2GrowthFormatted"/>)</td>
...
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
有了这个,我有了一个想法,根据所表示的数据类型有条件地格式化增长百分比(你可以在表上的 class 属性中看到它的开头,我用它来识别是增加还是减少为阳性或阴性)。但是,当我尝试这样做时,Visual Studio 告诉我 XSL 格式错误:
<td><xsl:value-of select="Source1CountFormatted"/> (<i class="<xsl:value-of select="Source1GrowthCss"/>"><xsl:value-of select="Source1GrowthFormatted"/> </i>)</td>
我还尝试了一种方法,其中“...GrowthFormatted”属性将返回它的内联样式,但所有 HTML 在解析为要转换的 XML 树时立即被转义。我来这里之前的最后一次尝试是使用 xsl:text 方法,禁用输出转义:“是”。这导致了 XSL 的这种怪物(注意两种不同的方法来查看它是否可以工作):
<td><xsl:value-of select="Source1CountFormatted"/> (<xsl:text disable-output-escaping="yes"><</xsl:text>i class=<xsl:text disable-output-escaping="yes">"</xsl:text><xsl:value-of select="Source1GrowthCssClass"/><xsl:text disable-output-escaping="yes">"></xsl:text><xsl:value-of select="Source1GrowthFormatted"/><xsl:text disable-output-escaping="yes"><</xsl:text>/i<xsl:text disable-output-escaping="yes">></xsl:text>)</td>
<td><xsl:value-of select="Source2CountFormatted"/> (<xsl:text disable-output-escaping="yes"><i class="</xsl:text><xsl:value-of select="Source2GrowthCssClass"/><xsl:text disable-output-escaping="yes">"></xsl:text><xsl:value-of select="Source2GrowthFormatted"/><xsl:text disable-output-escaping="yes"></i></xsl:text>)</td>
眼尖的你们甚至可能注意到我使用了<xsl:text disable-output-escaping="yes">&lt;</xsl:text> 的Microsoft here 提供的教科书示例,您可能会问,结果是什么?嗯,Visual Studio 没有错,因为嵌套元素不能很好地与 XSL 一起工作并引发了这个异常:
XslLoadException: XSLT compile error. An error occurred at , (66, 84). ---> System.Xml.XmlException: '<', hexadecimal value 0x3C is an invalid attribute character. Line 66, poisition 84.
至于极其冗长的方法,以及超级简单的方法,它们都导致生成以下 HTML:
...
<tr>
<td>2019-09-19 12:30:40Z</td>
<td>35,991,744 (<i class="clsDecrease">0.00%</i>)</td>
<td>755,412 (<i class="clsDecrease">0.00%</i>)</td>
...
【问题讨论】:
标签: c# asp.net-core xslt