XSLT对重复元素名称进行分组

时间:2013-12-04 16:37:20

标签: xslt grouping

我有一个扁平的源结构,需要按以下条件分组:

元素P2可在P1后多次出现。 P1和所有以下P2元素直到下一次出现P1需要被分组为“位置”结构。当下一个P1元素出现时,“位置”会重复。

来源示例:

    <P1><field1/><field2/></P1>
    <P2><field1/><field2/><field3/></P2>
    <P1><field1/><field2/></P1>
    <P2><field1/><field2/><field3/></P2>
    <P2><field1/><field2/><field3/></P2>
    <P2><field1/><field2/><field3/></P2>
    <P2><field1/><field2/><field3/></P2>
    <P1><field1/><field2/></P1>
    <P2><field1/><field2/><field3/></P2>
    <P2><field1/><field2/><field3/></P2>

结果应为:

<Position>
    <P1><field1/><field2/></P1>
    <P2><field1/><field2/><field3/></P2>
</Position>
<Position>
    <P1><field1/><field2/></P1>
    <P2><field1/><field2/><field3/></P2>
    <P2><field1/><field2/><field3/></P2>
    <P2><field1/><field2/><field3/></P2>
    <P2><field1/><field2/><field3/></P2>
</Position>
<Position>
    <P1><field1/><field2/></P1>
    <P2><field1/><field2/><field3/></P2>
    <P2><field1/><field2/><field3/></P2>
</Position>

我正在尝试使用轴跟随兄弟,但无法弄清楚如何选择所有P2元素到P1的下一个出现。或者我应该在这种情况下使用xsl:key?

1 个答案:

答案 0 :(得分:3)

在XSLT 2.0中,for-each-group

就是一个简单的问题
<xsl:for-each-group select="*" group-starting-with="P1">
  <Position>
    <xsl:copy-of select="current-group()" />
  </Position>
</xsl:for-each-group>

在1.0中,我能想到的最有效的方法是定义一个键

<xsl:key name="P2key" match="P2" use="generate-id(preceding-sibling::P1[1])" />

将P2元素按最近的 P1分组。然后只处理P1元素并使用键拉出正确的P2:

<xsl:for-each select="P1">
  <Position>
    <xsl:copy-of select=". | key('P2key', generate-id())" />
  </Position>
</xsl:for-each>

(我个人使用模板而不是for-eachfor-each是一个更简单的例子)