如何在XSLT中获取walkins变量的去重且含指定字符的值?
解决XSLT遍历变量筛选去重的问题
核心问题分析
你遇到的空白结果,大概率是因为XSLT版本兼容问题(比如1.0中未将结果树片段转为节点集)、筛选逻辑错误或去重方法不对。下面分版本给出可直接复用的解决方案:
方案1:XSLT 1.0(兼容多数旧处理器)
XSLT1.0中直接用<xsl:variable>包含节点会生成结果树片段,无法直接遍历,必须先转为节点集;去重则依赖Muenchian分组法。
完整代码示例
<!-- 首先声明必要的命名空间(用于节点集转换) --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl"> <!-- 定义输入参数(假设你的Walkin1-Walkin8是外部传入的参数) --> <xsl:param name="Walkin1"/> <xsl:param name="Walkin2"/> <xsl:param name="Walkin3"/> <xsl:param name="Walkin4"/> <xsl:param name="Walkin5"/> <xsl:param name="Walkin6"/> <xsl:param name="Walkin7"/> <xsl:param name="Walkin8"/> <!-- 1. 生成处理后的结果树片段 --> <xsl:variable name="walkins-rtf"> <Item><xsl:value-of select="translate($Walkin1, ' ', '')"/></Item> <Item><xsl:value-of select="translate($Walkin2, ' ', '')"/></Item> <Item><xsl:value-of select="translate($Walkin3, ' ', '')"/></Item> <Item><xsl:value-of select="translate($Walkin4, ' ', '')"/></Item> <Item><xsl:value-of select="translate($Walkin5, ' ', '')"/></Item> <Item><xsl:value-of select="translate($Walkin6, ' ', '')"/></Item> <Item><xsl:value-of select="translate($Walkin7, ' ', '')"/></Item> <Item><xsl:value-of select="translate($Walkin8, ' ', '')"/></Item> </xsl:variable> <!-- 2. 将结果树片段转为可遍历的节点集 --> <xsl:variable name="walkins" select="exsl:node-set($walkins-rtf)/Item"/> <!-- 3. 定义分组键(用于去重) --> <xsl:key name="unique-walkin-key" match="$walkins" use="."/> <!-- 4. 筛选+去重并输出 --> <xsl:template match="/"> <html> <body> <h3>筛选去重后的结果</h3> <ul> <xsl:for-each select="$walkins[ normalize-space() != '' and (contains(., 'abc') or contains(., 'AP')) ]"> <!-- 只保留每个唯一值的第一个实例 --> <xsl:if test="generate-id() = generate-id(key('unique-walkin-key', .)[1])"> <li><xsl:value-of select="."/></li> </xsl:if> </xsl:for-each> </ul> </body> </html> </xsl:template> </xsl:stylesheet>
关键修复点
- 用
exsl:node-set()将结果树片段转为节点集,解决无法遍历的问题; - 用
contains()实现包含指定字符的筛选,同时加normalize-space() != ''排除空值; - 借助Muenchian分组的
generate-id()判断,实现去重。
方案2:XSLT 2.0+(更简洁高效)
XSLT2.0+支持序列和distinct-values()函数,无需处理结果树片段,代码更简洁:
完整代码示例
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义输入参数 --> <xsl:param name="Walkin1"/> <xsl:param name="Walkin2"/> <xsl:param name="Walkin3"/> <xsl:param name="Walkin4"/> <xsl:param name="Walkin5"/> <xsl:param name="Walkin6"/> <xsl:param name="Walkin7"/> <xsl:param name="Walkin8"/> <!-- 生成处理后的字符串序列 --> <xsl:variable name="walkins-sequence" as="xs:string*"> <xsl:sequence select="translate($Walkin1, ' ', '')"/> <xsl:sequence select="translate($Walkin2, ' ', '')"/> <xsl:sequence select="translate($Walkin3, ' ', '')"/> <xsl:sequence select="translate($Walkin4, ' ', '')"/> <xsl:sequence select="translate($Walkin5, ' ', '')"/> <xsl:sequence select="translate($Walkin6, ' ', '')"/> <xsl:sequence select="translate($Walkin7, ' ', '')"/> <xsl:sequence select="translate($Walkin8, ' ', '')"/> </xsl:variable> <!-- 筛选+去重并输出 --> <xsl:template match="/"> <html> <body> <h3>筛选去重后的结果</h3> <ul> <xsl:for-each select="distinct-values( $walkins-sequence[ normalize-space() != '' and (contains(., 'abc') or contains(., 'AP')) ] )"> <li><xsl:value-of select="."/></li> </xsl:for-each> </ul> </body> </html> </xsl:template> </xsl:stylesheet>
优势
- 直接用
distinct-values()去重,无需分组; - 序列处理更高效,代码可读性更强。
额外提示
如果需要忽略大小写筛选(比如同时匹配ap和AP),可以结合translate()统一转换大小写:
contains(translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'AP')
内容的提问来源于stack exchange,提问作者JZnrgn
相关产品推荐
相关产品推荐

