4

So I have input like:

<Root>
 <Item id="1" group="foo" />
 <Item id="2" group="bar" />
 <Item id="3" />
</Root>

And a template instruction like:

<xsl:for-each-group select="Root" group-by="@group" />

It would seem that I only get groups for foo and bar. (Why? I expected I might get a 3rd group with current-group-key() = '').

I really want that 3rd group. What options do I have?

thanks, David.

David Bullock
  • 6,112
  • 3
  • 33
  • 43
  • using `group-by="concat('',@group)"` gives me the 3rd group. I'm still not clear why group-by behaves it behaves the way it does. – David Bullock Oct 28 '12 at 03:08

2 Answers2

3

Martin gave a good explanation.

If what you want is allowed, then elements that don't have a group attribute at all, would be in the same group as elements that do have a group='' attribute -- and this is not precise.

The simplest solution is to indicate in the group-by attribute that whether or not a group attribute exists doesn't matter.

The simplest way to do so is:

<xsl:for-each-group select="Root/*" group-by="string(@group)">

Here is a complete transformation:

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

 <xsl:template match="/">
  <xsl:for-each-group select="Root/*" group-by="string(@group)">
   "<xsl:sequence select="string(@group)"/>"
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<Root>
    <Item id="1" group="foo" />
    <Item id="2" group="bar" />
    <Item id="3" />
</Root>

the wanted result is produced:

   "foo"

   "bar"

   ""
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
1

The XSLT 2.0 specification http://www.w3.org/TR/xslt20/#xsl-for-each-group says the following about group-by:

If the group-by attribute is present, the items in the population are examined, in population order. For each item J, the expression in the group-by attribute is evaluated to produce a sequence of zero or more grouping key values. For each one of these grouping keys, if there is already a group created to hold items having that grouping key value, J is added to that group; otherwise a new group is created for items with that grouping key value, and J becomes its first member.

An item in the population may thus be assigned to zero, one, or many groups.

So in your case when the group-by expression @group is evaluated for the third Item element it evaluates to the empty sequence and thus there is no grouping key found causing the item to be added to any group. That way the third Item does not belong to any group.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110