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>

今、私は次のような単一のノードになるために、直接の隣人であるすべてのグロームが必要です:

<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 ノードは特定のレベルでのみ表示され、root 以外では groupme ノードは表示されません。

私に何か助けはありますか?

4

1 に答える 1

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>
于 2013-05-13T09:06:29.603 に答える