在新节点下对重复节点进行排序和分组

时间:2017-09-25 15:07:37

标签: xml xslt xslt-1.0

我正在尝试将新节点下的重复节点分组(按排序顺序)。这是我的xml。

<NodeRoot>
    <NodeA>
        <NodeB>
            <NodeC>101</NodeC>
            <NodeC>102</NodeC>
            <NodeC>101</NodeC>
            <NodeC>104</NodeC>
        </NodeB>
    </NodeA>
    <NodeA>
        <NodeB>
            <NodeC>102</NodeC>
            <NodeC>103</NodeC>
            <NodeC>101</NodeC>
            <NodeC>102</NodeC>
        </NodeB>
    </NodeA>
</NodeRoot>

这就是我想要实现的目标。请注意,首先对重复的NodeC进行排序,然后将其分组到新的NodeGroup节点下。

<NodeRoot>
    <NodeA>
        <NodeB>
            <NodeGroup>
                <NodeC>101</NodeC>
                <NodeC>101</NodeC>
            </NodeGroup>
            <NodeGroup>
                <NodeC>102</NodeC>
            </NodeGroup>
            <NodeGroup>
                <NodeC>104</NodeC>
            </NodeGroup>
        </NodeB>
    </NodeA>
    <NodeA>
        <NodeB>
            <NodeGroup>
                <NodeC>101</NodeC>
            </NodeGroup>
            <NodeGroup>
                <NodeC>102</NodeC>
                <NodeC>102</NodeC>
            </NodeGroup>
            <NodeGroup>
                <NodeC>103</NodeC>
            </NodeGroup>
        </NodeB>
    </NodeA>
</NodeRoot>

这是我的xslt(我只能访问xslt1)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

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

    <xsl:template match="NodeB">
        <NodeB>
                <xsl:apply-templates select="NodeB[not(NodeC = preceding-sibling::NodeB/NodeC)]" mode="GroupC">
                    <xsl:sort select="NodeC" data-type="number"/>
                </xsl:apply-templates>
        </NodeB>
    </xsl:template>

    <xsl:template match="NodeB" mode="GroupC">
        <xsl:variable name="GC" select="NodeC"/>
        <NodeB>
            <NodeGroup>
                <xsl:apply-templates select="NodeB[NodeC/text()=$GC]" mode="SameC" />
            </NodeGroup>
        </NodeB>
    </xsl:template>

    <xsl:template match="NodeC" mode="SameC">
        <xsl:copy-of select="NodeC"/>
    </xsl:template>

</xsl:stylesheet>

这不是对重复的NodeC进行分组。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

如果你想对前面的兄弟姐妹采取这种方法,那么你只需要确保你处理NodeC孩子:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

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

    <xsl:template match="NodeB">
        <NodeB>
                <xsl:apply-templates select="NodeC[not(. = preceding-sibling::NodeC)]" mode="GroupC">
                    <xsl:sort select="." data-type="number"/>
                </xsl:apply-templates>
        </NodeB>
    </xsl:template>

    <xsl:template match="NodeC" mode="GroupC">
        <NodeGroup>
            <xsl:copy-of select="../NodeC[. = current()]"/>
        </NodeGroup>
    </xsl:template>

</xsl:stylesheet>

甚至不需要额外的模式。

使用Muenchian grouping在XSLT 1.0中进行分组通常更有效,尽管在这里您需要一个密钥,将NodeB父级的生成ID与NodeC值连接起来,以便识别NodeB的子树内的组:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <xsl:key name="group" match="NodeC" use="concat(generate-id(..), '|', .)"/>

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

    <xsl:template match="NodeB">
        <NodeB>
                <xsl:apply-templates select="NodeC[generate-id() = generate-id(key('group', concat(generate-id(..), '|', .))[1])]" mode="GroupC">
                    <xsl:sort select="." data-type="number"/>
                </xsl:apply-templates>
        </NodeB>
    </xsl:template>

    <xsl:template match="NodeC" mode="GroupC">
        <NodeGroup>
            <xsl:copy-of select="key('group', concat(generate-id(..), '|', .))"/>
        </NodeGroup>
    </xsl:template>

</xsl:stylesheet>
相关问题