xslt根据元素值对xml进行分组

时间:2018-07-06 13:50:58

标签: xslt

想使用手动XSLT根据相似的包ID对请求进行分组 这是包含plan_id且需要分组的输入xml

<subscriptions>
    <package>
        <package_plan>
            <plan_id>1111</plan_id>
            <plan_name>economy1</plan_name>
        </package_plan>
        <rate_channel>
            <rateid>1F1</rateid>
            <currency>USD</currency>
            <package_duration>monthly</package_duration>
            <price>3</price>
        </rate_channel>
    </package>
    <package>
        <package_plan>
            <plan_id>1111</plan_id>
            <plan_name>economy1</plan_name>
        </package_plan>
        <rate_channel>
            <rateid>1F2</rateid>
            <currency>USD</currency>
            <package_duration>quaterly</package_duration>
            <price>11</price>
        </rate_channel>
    </package>
    <package>
        <package_plan>
            <plan_id>2222</plan_id>
            <plan_name>economy2</plan_name>
        </package_plan>
        <rate_channel>
            <rateid>1F3</rateid>
            <currency>INR</currency>
            <package_duration>monthly</package_duration>
            <price>250</price>
        </rate_channel>
    </package>
</subscriptions>

寻找输出为:

<subscriptions>
    <package>
        <plan_id>1111</plan_id>
        <plan_name>economy1</plan_name>
        <channels>
            <rate_channel>
                <rateid>1F1</rateid>
                <currency>USD</currency>
                <package_duration>monthly</package_duration>
                <price>3</price>
            </rate_channel>
            <rate_channel>
                <rateid>1F2</rateid>
                <currency>USD</currency>
                <package_duration>quaterly</package_duration>
                <price>11</price>
            </rate_channel>
        </channels>
    </package>
    <package>
        <plan_id>2222</plan_id>
        <plan_name>economy2</plan_name>
        <channels>
            <rate_channel>
                <rateid>1F3</rateid>
                <currency>INR</currency>
                <package_duration>monthly</package_duration>
                <price>250</price>
            </rate_channel>
        </channels>
    </package>
</subscriptions>

我一直在搜索并阅读其他帖子,但我认为它们并不能完全覆盖我想做的事情 预先感谢...

1 个答案:

答案 0 :(得分:2)

下面是XSLT 1.0和XSLT 2.0解决方案。两种解决方案都使用@Tim C在评论中正确指出的方法。

XSLT 1.0

对于XSLT 1.0,使用muenchian grouping。需要定义<xsl:key>才能对元素进行分组。在这种情况下,<plan_id>是进行分组的键。

<xsl:key name="plan" match="package" use="package_plan/plan_id" />

package元素将进行相应匹配,并将分组的数据复制到输出中。

<xsl:template match="package[generate-id() = generate-id(key('plan', package_plan/plan_id)[1])]">
    <xsl:copy>
        <xsl:variable name="varPlan" select="key('plan', package_plan/plan_id)" />
        <xsl:apply-templates select="$varPlan[1]/package_plan/plan_id" />
        <xsl:apply-templates select="$varPlan[1]/package_plan/plan_name" />
        <channels>
            <xsl:for-each select="$varPlan">
                <xsl:apply-templates select="rate_channel" />
            </xsl:for-each>
        </channels>
    </xsl:copy>
</xsl:template>

其余<package>个元素被删除。

<xsl:template match="package" />

XSLT 2.0

在XSLT 2.0中,<xsl-for-each-group>功能特别适用于元素分组。在这种情况下,使用此功能和current-group()函数可以实现分组。

<xsl:template match="subscriptions">
    <xsl:copy>
        <xsl:for-each-group select="package" group-by="package_plan/plan_id">
            <package>
                <xsl:apply-templates select="current-group()[1]/package_plan/plan_id" />
                <xsl:apply-templates select="current-group()[1]/package_plan/plan_name" />
                <channels>
                    <xsl:for-each select="current-group()">
                        <xsl:apply-templates select="rate_channel" />
                    </xsl:for-each>
                </channels>
            </package>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

在以上两种情况下,都应使用identity transform模板将数据原样复制到输出中。

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
</xsl:template>