有没有一种优雅的方法可以用 XSLT 添加多个 HTML 类?

Posted

技术标签:

【中文标题】有没有一种优雅的方法可以用 XSLT 添加多个 HTML 类?【英文标题】:Is there an elegant way to add multiple HTML classes with XSLT? 【发布时间】:2010-12-10 04:18:23 【问题描述】:

假设我正在将多项选择测验从任意 XML 格式转换为 html。每个选择都将在结果文档中表示为 HTML <li> 标记。对于每个选择,如果该选择是正确的答案,我想将correct 的 HTML class 添加到 <li>。此外,如果该选项是用户选择的选项,我想将 submitted 类添加到 <li>。因此,如果选择是正确的以及提交的一个,<li> 应该有一个classcorrect submitted

据我所知,空格分隔的属性值不是 XML 数据模型的一部分,因此不能直接通过 XSLT 创建。但是,我觉得有一种更好的方法来执行此操作,而不是为每个可能的类组合使用一个条件来乱扔代码(这在本示例中是可以接受的,但在更复杂的场景中会很笨拙)。

我怎样才能优雅地解决这个问题?

期望结果示例:

<p>Who trained Obi-Wan Kenobi?</p>
<ul>
    <li>Mace Windu</li>
    <li class="correct submitted">Qui-Gon Jinn</li>
    <li>Ki-Adi-Mundi</li>
    <li>Yaddle</li>
</ul>

【问题讨论】:

【参考方案1】:

首先,XML中的属性值中的空格并没有什么问题:粗略地说,attribute value normalization在解析文档时会将空格字符转换为空格并将相邻的空格折叠为单个空格,但空格绝对是允许的。 编辑:请参阅下文了解更多信息。

正如您在评论中提到的那样,Matthew Wilson 的方法未能在可能的值之间包含空格。但是,他的方法基本上是合理的。拼图的最后一块是你不喜欢多余的空间:这些可以通过使用@987654322@ XPath 函数来消除。

以下样式表将所有部分放在一起 - 请注意,它不会对其输入文档做任何事情,因此出于测试目的,您可以针对任何 XML 文档甚至针对自身运行它,以验证输出是否符合您的要求要求。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:variable name="foo0" select="false()"/>
  <xsl:variable name="bar0" select="true()"/>

  <xsl:variable name="foo1" select="true()"/>
  <xsl:variable name="bar1" select="false()"/>

  <xsl:variable name="foo2" select="true()"/>
  <xsl:variable name="bar2" select="true()"/>

  <xsl:template match="/">

    <xsl:variable name="foobar0">
      <xsl:if test="$foo0"> foo</xsl:if>
      <xsl:if test="$bar0"> bar</xsl:if>
    </xsl:variable>

    <xsl:variable name="foobar1">
      <xsl:if test="$foo1"> foo</xsl:if>
      <xsl:if test="$bar1"> bar</xsl:if>
    </xsl:variable>

    <xsl:variable name="foobar2">
      <xsl:if test="$foo2"> foo</xsl:if>
      <xsl:if test="$bar2"> bar</xsl:if>
    </xsl:variable>

    <li>
      <xsl:attribute name="class">
        <xsl:value-of select="normalize-space($foobar0)"/>
      </xsl:attribute>
    </li>
    <li>
      <xsl:attribute name="class">
        <xsl:value-of select="normalize-space($foobar1)"/>
      </xsl:attribute>
    </li>
    <li>
      <xsl:attribute name="class">
        <xsl:value-of select="normalize-space($foobar2)"/>
      </xsl:attribute>
    </li>

  </xsl:template>
</xsl:stylesheet>

编辑:关于在属性值中分隔离散组件的空格问题:XML 规范将许多可能的有效构造定义为attribute types,包括 IDREFS 和 NMTOKENS。第一种情况匹配Names生产,第二种情况匹配NMTokens生产;这两个产生式都被定义为包含多个适当类型的值,由空格分隔。因此,以空格分隔的值列表作为单个属性的值是 XML 信息集的固有组成部分。

【讨论】:

实际上,关于空格分隔的属性值,我的观点是 XML 不会将它们识别为不同的值——它都是一个长字符串(除非我忽略了 XML 的某些部分)。这就是我在开始使用类属性时总觉得有点脏的原因。话虽如此,我确实意识到对于我们的编码人员来说,用空格分隔类比到处塞满&lt;class&gt; 子元素要容易得多。 @Jakob:我在回复末尾添加了一些关于空格分隔的值列表形成单个属性值的更多详细信息。【参考方案2】:

在我的脑海中,您可以建立一个以空格分隔的列表,例如:

<li>
    <xsl:attribute name="class">
        <xsl:if cond="...">correct</xsl:if>
        <xsl:if cond="...">submitted</xsl:if>
  </xsl:attribute>
</li>

【讨论】:

那行不通(至少不使用 php)。除了 if 元素周围的内容外,其中没有空格,这不会影响输出(您需要为此使用 text 元素)。当然,我可以使用这个解决方案,并在每个可能的类名之后简单地添加一个空格,但这会导致多余的空格,并且看起来比应有的更混乱。 我已经成功使用了它,所以可能是 XSLT 处理器在处理 XSLT 文件本身的空白方面有所不同。 不应该condtest【参考方案3】:

据我所知,空格分隔的属性值不是 XML 数据模型的一部分,因此不能直接通过 XSLT 创建

除非您要转换为 XML 语言(HTML 不是,XHTML 是),否则您不必担心 XSLT 输出 的 XML 有效性。这可以是任何东西,并且不需要符合 XML!

【讨论】:

我并不是说空格分隔的属性值是无效的 XML,只是(据我所知)没有专门生成它们的 XSLT 构造。

以上是关于有没有一种优雅的方法可以用 XSLT 添加多个 HTML 类?的主要内容,如果未能解决你的问题,请参考以下文章

可以将 XSLT 样式表添加到序列化的 XML 文档吗?

有没有更优雅的方法来添加可为空的整数?

为啥 XSLT 生态系统没有与数据可视化广泛关联?

应用所有模板

XSLT - 动态添加元素

是否可以用另一个 XSLT 代码(元 XSLT)转换 XSLT 代码?