通过按顺序识别某种类型的第一个节点来分组兄弟姐妹

时间:2015-06-22 19:52:45

标签: xml xslt xpath

不确定该描述是否最佳...但是给出了这个xml:

<?xml version="1.0"?>
<root>
    <type1 num="1" first="1"/>
    <type1 num="2" />
    <type2 num="3" />
    <type2 num="4" />
    <type1 num="5" first="2"/>
    <type1 num="6" />
    <type2 num="7" />
    <type2 num="8" />
    <type1 num="9" first="3"/>
    <type1 num="10" />
    <type2 num="11" />
    <type2 num="12" />

</root>

我想加深层次结构,并添加一个新的&#39;组&#39;每次我在一个type1节点序列中遇到第一个节点。 (注意:@first就是这样,我可以看到模板正在拾取的确切节点......我不想用它来启动组)

这是我的样式表。

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

<xsl:key name="kFirstText" match="*" use="generate-id(preceding-sibling::type1[not(preceding-sibling::*[1][self::type1])][1])"/>

<xsl:template match="/">
    <newroot>
        <xsl:apply-templates/>
    </newroot>
</xsl:template>

<xsl:template match="type1[not(preceding-sibling::*[1][self::type1])]">
    <group>
        <type1>
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="first-in-group">true</xsl:attribute>
        </type1>
        <xsl:copy-of select="key('kFirstText', generate-id())"/>
    </group>
</xsl:template>
</xsl:stylesheet>

我得到的结果是:

<?xml version='1.0' ?>
<newroot>
    <group><type1 num="1" first="1" first-in-group="true"/><type1 num="2"/><type2 num="3"/><type2 num="4"/><type1 num="5" first="2"/></group>
    <group><type1 num="5" first="2" first-in-group="true"/><type1 num="6"/><type2 num="7"/><type2 num="8"/><type1 num="9" first="3"/></group>
    <group><type1 num="9" first="3" first-in-group="true"/><type1 num="10"/><type2 num="11"/><type2 num="12"/></group>
</newroot>

我发现this question让我非常接近,但正如您在输出中所看到的,type1节点的第一个实例在前两组中被复制。

我也意识到我对钥匙正在捡到的东西有点模糊。我的阅读是它正在拾取任何跟在前面没有类型1的type1的前一个实例之后的节点......就是这样吗?

我还试图在模板中使用相同的xpath排除@match中的那个节点(@num =&#34; 5&#34;),但这只是被忽略了。知道如何完成我上面描述的内容吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

以这种方式尝试:

<xsl:key name="kFirstText" match="*[not(self::type1[not(preceding-sibling::*[1][self::type1])])]" use="generate-id(preceding-sibling::type1[not(preceding-sibling::*[1][self::type1])][1])"/>

这排除了&#34;领导者&#34;来自密钥检索的组中的节点。