XML+XSL场景下,是否必须将变量层层传递至各模板?
不用层层传递变量的解决方案
嘿,我完全懂你的困惑——一开始我也以为必须把变量挨个传到每个模板里,但其实XSLT提供了更优雅的方式来处理这种全局查找的需求!
方法1:使用<xsl:key>(推荐,兼容XSLT 1.0+)
这是最常用也最高效的方案,key相当于一个全局索引,你可以在任何模板里直接调用,根本不用传参数。
首先在样式表的顶层(所有模板外面)定义key:
<xsl:key name="highlight-name-index" match="HighlightNames/Name" use="." />
这个key会把所有HighlightNames/Name节点的值作为索引键。
接下来,在匹配那些需要高亮的“Name使用位置”的模板里,直接用key检查当前文本是否在高亮列表中:
<!-- 匹配所有属于Name使用位置的文本节点 --> <xsl:template match="your-name-usage-element/text()"> <xsl:choose> <!-- 用normalize-space避免空格干扰匹配 --> <xsl:when test="key('highlight-name-index', normalize-space(.))"> <span style="color: green;"><xsl:value-of select="." /></span> </xsl:when> <xsl:otherwise> <xsl:value-of select="." /> </xsl:otherwise> </xsl:choose> </xsl:template>
或者更简洁的写法:
<xsl:template match="text()[key('highlight-name-index', normalize-space(.))]"> <span style="color: green;"><xsl:value-of select="." /></span> </xsl:template>
这个模板会自动匹配所有属于高亮列表的文本节点,并给它们加上绿色高亮。
方法2:全局变量(适用于XSLT 2.0+)
如果你用的是XSLT 2.0或更高版本,可以把所有高亮Name存成一个全局序列变量,同样不需要层层传递:
在样式表顶层定义全局变量:
<xsl:variable name="highlight-names" select="/root/HighlightNames/Name" as="xs:string*" />
然后在任意模板里直接判断当前文本是否在这个序列中:
<xsl:template match="your-name-usage-element/text()"> <xsl:choose> <xsl:when test="normalize-space(.) = $highlight-names"> <span style="color: green;"><xsl:value-of select="." /></span> </xsl:when> <xsl:otherwise> <xsl:value-of select="." /> </xsl:otherwise> </xsl:choose> </xsl:template>
关于生成日程表的部分
循环生成每个Name的日程表时,直接遍历HighlightNames/Name即可,不用额外处理变量传递:
<xsl:for-each select="HighlightNames/Name"> <div class="schedule-item"> <h3 style="color: orange;"><xsl:value-of select="." /></h3> <!-- 这里插入该Name对应的日程内容 --> </div> </xsl:for-each>
为什么不用层层传递变量?
XSLT里的全局变量(顶层定义)和<xsl:key>都是全局可访问的,整个样式表的任何模板都能直接调用,完全不需要把变量作为参数挨个传给每个模板——这样不仅代码更简洁,维护起来也轻松很多!
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

