Re: [xsl] Wrap changing element sequence into container: with 'for-each-group'?

Subject: Re: [xsl] Wrap changing element sequence into container: with 'for-each-group'?
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Fri, 26 Jan 2007 11:33:14 +0100
Hi Yves,

You did not show how the output should really look like. But I suppose "inside a <b> container" means a <b> element with children <b1>, <b2> etc. Here's what I came up with, which does not involve grouping, but instead uses mode-switching. If you have textual content in your real input, you may need some changes, because I neglect the default template below.

Output of below stylesheet on your input:

<a>
  <b>
     <b1/>
     <b2/>
  </b>
  <c/>
</a>
<a>
  <b>
     <b2/>
  </b>
  <c/>
</a>


The Stylesheet:


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

<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:apply-templates select="$abc/*" />
</xsl:template>
<xsl:template match="*[starts-with(name(), 'b')][1]">
<b>
<xsl:apply-templates
select="self::* | following-sibling::*"
mode="b"/>
</b>
</xsl:template>
<xsl:template match="*[starts-with(name(), 'b')]" mode="b">
<xsl:copy>
<xsl:apply-templates select="node() | @*" mode="#current"/>
</xsl:copy>
</xsl:template>


<!-- copy all others -->
<xsl:template match="*[not(starts-with(name(), 'b'))]">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>




Cheers,
-- Abel Braaksma
  http://www.nuntia.nl

Yves Forkl wrote:
Given two XML fragments

<a>
 <b1/>
 <b2/>
 <c/>
</a>

and

<a>
 <b2/>
 <c/>
</a>

I would like to wrap <b1/><b2/> into a <b/> container, and the same should happen to <b2/> when occurring alone. The other elements can be assumed to remain unchanged.

While I found quite some hints on solving grouping problems in the XSLT FAQ and in the XSL list archive, I can't figure out how to solve this wrapping task using XSLT 2.0. There is an interesting posting here: http://www.biglist.com/lists/xsl-list/archives/200201/msg00804.html
But I don't know how this could serve as a basis for a solution to my problem.


I suspect that "for-each-group" should be my friend; how would I need to use it here? Or is there any other, more elegant solution?

Yours,

Yves

Current Thread