首页 > 解决方案 > XSLT 根据多个条件丢弃重复项

问题描述

我有以下数据结构,需要输出每个节点的 id,每个节点的 id 的每个组合都v1只有v2一次,其中vequals A

2,3,4,6,7应打印具有 id 的节点。

<root>
    <node>
        <v>A</v>
        <id>2</id>
        <v1>S</v1>
        <v2>S</v2>
    </node>
    <node>
        <v>A</v>
        <id>3</id>
        <v1>S</v1>
        <v2>S1</v2>
    </node>
    <node>
        <v>A</v>
        <id>4</id>
        <v1>S2</v1>
        <v2>S1</v2>
    </node>
    <node>
        <v>B</v>
        <id>5</id>
        <v1>S2</v1>
        <v2>S3</v2>
    </node>
    <node>
        <v>A</v>
        <id>6</id>
        <v1>S2</v1>
        <v2>S3</v2>
    </node>
    <node>
        <v>A</v>
        <id>7</id>
        <v1>S</v1>
        <v2>S3</v2>
    </node>
    <node>
        <v>A</v>
        <id>8</id>
        <v1>S</v1>
        <v2>S</v2>
    </node>
</root>

我尝试使用xsl:key,但不幸的是只打印了独特的元素(缺少 id=2)

如下所示使用preceeding都不会产生所需的结果。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <!-- pos 1 -->
    <xsl:key name="keys" match="node" use="concat(v1, '|', v2, '|', v)"/>
    <!-- /pos 1 -->

    <xsl:template match="root">
        <xsl:for-each select="node[v='A']">

            <!-- pos 1 -->
            <xsl:variable name="vDups" select="key('keys', concat(v1, '|', v2, '|', v))[not(generate-id() = generate-id(current()))]" />
            <xsl:if test="not($vDups)">
                <node>
                    <xsl:value-of select="current()/id"/>
                </node>
            </xsl:if>
            <!-- /pos 1 -->

            <!-- pos 2 -->
            <xsl:if test="not(preceding::node/v1=current()/v1 and preceding::node/v2 = current()/v2)">
                <node>
                    <xsl:value-of select="id" />
                </node>
            </xsl:if>
            <!-- /pos 2 -->

        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

我怎样才能达到预期的效果?

标签: xmlxsltxslt-2.0

解决方案


您已经标记了这个 XSLT 2.0,并且version="2.0"在您的样式表中有,在这种情况下,您可以利用它xsl:for-each-group来简化您的 XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:template match="root">
        <xsl:for-each-group select="node[v = 'A']" group-by="concat(v1, '|', v2)">
                <node>
                    <xsl:value-of select="id"/>
                </node>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

推荐阅读