如何组织邻居兄弟姐妹

时间:2013-05-13 07:41:52

标签: xslt xslt-1.0

我有这样的事情:

<root>
  <a>foo</a>
  <b>bar</b>
  <groupme>foobar</groupme>
  <groupme>baz</groupme>
  <groupme>42</groupme>
  <c>abc</c>
  <d>def</d>
  <groupme>foo</groupme>
  <x>xyz</x>
  <groupme>bar</groupme>
  <groupme>foo</groupme>
  <z>thats it</z>
</root>

现在我需要所有直接邻居的groume是一个单节点,如:

<root>
  <a>foo</a>
  <b>bar</b>
  <groupme>foobar baz 42</groupme>
  <c>abc</c>
  <d>def</d>
  <groupme>foo</groupme>
  <x>xyz</x>
  <groupme>bar foo</groupme>
  <z>thats it</z>
</root>

也包含其他节点的groupme节点,我只是留下它们来提供一个简单的例子。 groupme节点只在特定级别的apear,其他组中没有groupme节点,然后是root。

对我有任何帮助吗?

1 个答案:

答案 0 :(得分:0)

这种分组可以通过一种称为“兄弟递归”的方法来实现,对于你的问题,我建议使用如下样式表:

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

<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>

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

<xsl:template match="root/groupme[not(preceding-sibling::*[1][self::groupme])]">
  <xsl:copy>
    <xsl:apply-templates select="node()"/>
    <xsl:apply-templates select="following-sibling::*[1][self::groupme][1]" mode="list"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="root/groupme[preceding-sibling::*[1][self::groupme]]"/>


<xsl:template match="root/groupme[preceding-sibling::*[1][self::groupme]]" mode="list">
  <xsl:text> </xsl:text>
  <xsl:apply-templates select="node()"/>
  <xsl:apply-templates select="following-sibling::*[1][self::groupme][1]" mode="list"/>
</xsl:template>

</xsl:stylesheet>

应用于输入

<root>
  <a>foo</a>
  <b>bar</b>
  <groupme>foobar</groupme>
  <groupme>baz</groupme>
  <groupme>42</groupme>
  <c>abc</c>
  <d>def</d>
  <groupme>foo</groupme>
  <x>xyz</x>
  <groupme>bar</groupme>
  <groupme>foo</groupme>
  <z>thats it</z>
</root>

结果是

<root>
  <a>foo</a>
  <b>bar</b>
  <groupme>foobar baz 42</groupme>
  <c>abc</c>
  <d>def</d>
  <groupme>foo</groupme>
  <x>xyz</x>
  <groupme>bar foo</groupme>
  <z>thats it</z>
</root>

作为兄弟递归的替代方案,也可以使用基于密钥的方法“抓住”以下兄弟姐妹:

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

<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>

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

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

<xsl:template match="root/groupme[not(preceding-sibling::*[1][self::groupme])]">
  <xsl:copy>
    <xsl:apply-templates select="node()"/>
    <xsl:apply-templates select="key('first', generate-id())" mode="list"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="root/groupme[preceding-sibling::*[1][self::groupme]]"/>

<xsl:template match="root/groupme" mode="list">
  <xsl:text> </xsl:text>
  <xsl:apply-templates select="node()"/>
</xsl:template>

</xsl:stylesheet>