tags:

views:

54

answers:

2

Using the XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="xml"/>
    <xsl:template match="/">
        <records>
            <record>
                <!-- Group record by bigID, for further processing -->
                <xsl:for-each-group select="records/record" group-by="bigID">
                    <xsl:sort select="bigID"/>
                    <xsl:for-each select="current-group()">
                        <!-- Create new combined record -->
                        <bigID>
                            <!-- <xsl:value-of select="."/> -->
                            <xsl:for-each select=".">
                                <xsl:value-of select="bigID"/>
                            </xsl:for-each>
                        </bigID>
                        <text>
                            <xsl:value-of select="text"/>
                        </text>
                    </xsl:for-each>
                </xsl:for-each-group>
            </record>
        </records>
    </xsl:template>
</xsl:stylesheet>

I'm trying to change:

<?xml version="1.0" encoding="UTF-8"?>
<records>
    <record>
        <bigID>123</bigID>
        <text>Contains text for 123</text>
        <bigID>456</bigID>
        <text>Some 456 text</text>
        <bigID>123</bigID>
        <text>More 123 text</text>
        <bigID>123</bigID>
        <text>Yet more 123 text</text>
    </record>
</records>

into:

<?xml version="1.0" encoding="UTF-8"?>
<records>
    <record>
        <bigID>123
            <text>Contains text for 123</text>
            <text>More 123 text</text>
            <text>Yet more 123 text</text>
        </bigID>
        <bigID>456
            <text>Some 456 text</text>
        </bigID>
    </record>
</records>

Right now, I'm just listing the grouped <bigID>s, individually. I'm missing the step after grouping, where I combine the grouped <bigID> nodes. My suspicion is that I need to use the "key" function somehow, but I'm not sure.

Thanks for any help.

A: 

Here is the wanted XSLT 2.0 transformation:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:key name="kTextforId" match="text"
         use="preceding-sibling::bigID[1]"/>

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

  <xsl:template match="record">
   <record>
    <xsl:for-each-group select="bigID" group-by=".">
     <bigID>
       <xsl:sequence select="current-grouping-key()"/>

       <xsl:copy-of select=
       "key('kTextforId', current-grouping-key())"/>
     </bigID>
    </xsl:for-each-group>
   </record>
  </xsl:template>
</xsl:stylesheet>

When performed on the provided XML document, the wanted result is produced.

Dimitre Novatchev
I thought that I was looking for the output that Lachlan Roche's code gave above, in his second example. However, it ends up that the output that I needed, was created by this code of Dimitre's. Thanks so much for both of your help! It's greatly appreciated.
LOlliffe
A: 

In XSLT 2.0 you don't need keys for grouping.

Since you are just copying the text elements in the group, the inner for-each can be removed.

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

    <xsl:output method="xml" indent="yes" />

    <xsl:template match="/">
        <records>
            <record>
                <xsl:for-each-group select="records/record/bigID" group-by=".">
                    <xsl:sort select="." data-type="number" />
                    <bigID>
                        <xsl:value-of select="." />
                        <xsl:copy-of select="current-group()/following-sibling::text[1]" />
                    </bigID>
                </xsl:for-each-group>
            </record>
        </records>
    </xsl:template>

</xsl:stylesheet>

If you instead wanted to output the bigID elements followed by their text elements, then my loop would be replaced by the following.

<xsl:for-each-group select="records/record/bigID" group-by=".">
    <xsl:sort select="." data-type="number" />
    <xsl:copy-of select="." />
    <xsl:copy-of select="current-group()/following-sibling::text[1]" />
</xsl:for-each-group>
Lachlan Roche