【问题标题】:How to do Nesting of Elements in XSLT for Conditional Styling?如何在 XSLT 中嵌套元素以实现条件样式?
【发布时间】: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">&lt;</xsl:text>i class=<xsl:text disable-output-escaping="yes">&quot;</xsl:text><xsl:value-of select="Source1GrowthCssClass"/><xsl:text disable-output-escaping="yes">&quot;&gt;</xsl:text><xsl:value-of select="Source1GrowthFormatted"/><xsl:text disable-output-escaping="yes">&lt;</xsl:text>/i<xsl:text disable-output-escaping="yes">&gt;</xsl:text>)</td>
<td><xsl:value-of select="Source2CountFormatted"/> (<xsl:text disable-output-escaping="yes">&lt;i class=&quot;</xsl:text><xsl:value-of select="Source2GrowthCssClass"/><xsl:text disable-output-escaping="yes">&quot;&gt;</xsl:text><xsl:value-of select="Source2GrowthFormatted"/><xsl:text disable-output-escaping="yes">&lt;/i&gt;</xsl:text>)</td>

眼尖的你们甚至可能注意到我使用了&lt;xsl:text disable-output-escaping="yes"&gt;&amp;lt;&lt;/xsl:text&gt;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 (&lt;i class="clsDecrease"&gt;0.00%&lt;/i&gt;)</td>
    <td>755,412 (&lt;i class="clsDecrease"&gt;0.00%&lt;/i&gt;)</td>
  ...

【问题讨论】:

    标签: c# asp.net-core xslt


    【解决方案1】:

    这里的语法错误:

    <i class="<xsl:value-of select="Source1GrowthCss"/>">
    

    要动态设置属性的值,您可以像这样使用xsl:attribute

    <i>
       <xsl:attribute name="class">
          <xsl:value-of select="Source1GrowthCss"/>
       </xsl:attribute>
    </i>
    

    但这是相当冗长的。理想的方法是使用更简洁的“属性值模板”

    <i class="{Source1GrowthCss}">
    

    这里,大括号表示要计算表达式,而不是按字面输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 2018-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多