XSLT1.0中如何在重复查询中筛选唯一Selected属性值
XSLT1.0实现AllOptions对应唯一Selected值输出
示例XML数据
<?xml version="1.0" encoding="UTF-8"?> <root> <AllOptions Id="123"></AllOptions> <AllOptions Id="456"></AllOptions> <AllOptions Id="789"></AllOptions> <AllOptions Id="789"></AllOptions> <AllOptions Id="101"></AllOptions> <SelectedOptions> <SelectedOption Id="101" Selected="No"></SelectedOption> <SelectedOption Id="789" Selected="Yes"></SelectedOption> <SelectedOption Id="789" Selected="No"></SelectedOption> <SelectedOption Id="123" Selected="No"></SelectedOption> <SelectedOption Id="456" Selected="No"></SelectedOption> </SelectedOptions> </root>
问题背景
使用仅支持XSLT1.0的工具结合XSLFO做数据转换,现有模板逻辑为:
- 遍历
<AllOptions>节点 - 内部循环匹配同
@Id的<SelectedOption>节点,要求每个<AllOptions>对应唯一的@Selected值输出
现有模板代码:
<xsl:template name="ShowOptions"> <xsl:for-each select="/root/AllOptions"> <fo:block><xsl:value-of select="@Id"/></fo:block> <xsl:for-each select="../SelectedOptions/SelectedOption[@Id = current()/@Id]"> <fo:block> <xsl:value-of select="@Selected"/> </fo:block> </xsl:for-each> </xsl:for-each> </xsl:template>
当前输出问题
同一@Id的<AllOptions>会重复输出所有匹配的@Selected值,例如:
123 No 456 No 789 Yes No 789 Yes No 101 No
期望输出
每个<AllOptions>对应唯一的@Selected值,相同@Id的<AllOptions>分别对应不同的@Selected状态:
123 No 456 No 789 Yes 789 No 101 No
解决方案
利用XSLT1.0的Muenchian分组实现去重,同时结合节点位置匹配,为每个同@Id的<AllOptions>分配唯一的@Selected值:
<xsl:template name="ShowOptions"> <!-- 定义复合分组键:按@Id和@Selected组合,确保每个组合唯一 --> <xsl:key name="selected-group" match="SelectedOption" use="concat(@Id, '|', @Selected)"/> <xsl:for-each select="/root/AllOptions"> <fo:block><xsl:value-of select="@Id"/></fo:block> <!-- 记录当前AllOptions在同Id节点中的位置(从1开始计数) --> <xsl:variable name="current-index" select="count(preceding-sibling::AllOptions[@Id = current()/@Id]) + 1"/> <!-- 筛选当前Id下所有唯一的SelectedOption项 --> <xsl:variable name="unique-selected" select="../SelectedOptions/SelectedOption[ @Id = current()/@Id and generate-id() = generate-id(key('selected-group', concat(@Id, '|', @Selected))[1]) ]"/> <!-- 根据当前位置输出对应的Selected值 --> <xsl:if test="$unique-selected[$current-index]"> <fo:block> <xsl:value-of select="$unique-selected[$current-index]/@Selected"/> </fo:block> </xsl:if> </xsl:for-each> </xsl:template>
逻辑说明
- Muenchian分组:通过
<xsl:key>创建@Id+@Selected的复合键,将相同组合的<SelectedOption>归为一组,利用generate-id()筛选出每组的第一个节点,实现去重。 - 位置匹配:计算当前
<AllOptions>在同@Id节点中的位置,从去重后的SelectedOption列表中取出对应位置的项,确保每个<AllOptions>只输出一个@Selected值。
内容的提问来源于stack exchange,提问作者iwasaki
相关产品推荐
相关产品推荐

