tags:

views:

29

answers:

1

I have a xml need to group by category I try to use

<xsl:for-each-group  select="ItemList/Item"  group-by="CategoryID">

How can I get the CategoryName, CategoryID or any information related to Category during the transformation?

Original XML

<ItemList>
<Item>
    <CategoryID>1</CategoryID>
    <CategoryName>Book</CategoryName>
    <ItemName>ASP.NET</ItemName>
    <ItemDetails>ASP.NET12345</ItemDetails>
</Item>
<Item>
    <CategoryID>1</CategoryID>
    <CategoryName>Book</CategoryName>
    <ItemName>PHP</ItemName>
    <ItemDetails>PHP12345</ItemDetails>
</Item>
<Item>
    <CategoryID>2</CategoryID>
    <CategoryName>Tool</CategoryName>
    <ItemName>ToolAbcde</ItemName>
    <ItemDetails>sth details</ItemDetails>
</Item></ItemList>

New XML

<NewXML>
<Category>
    <CategoryID>1</CategoryID>
    <CategoryName>Book</CategoryName>
    <ItemList>
        <Item>
            <ItemName>ASP.NET</ItemName>
            <ItemDetails>ASP.NET12345</ItemDetails>
        </Item>
        <Item>
            <ItemName>PHP</ItemName>
            <ItemDetails>PHP12345</ItemDetails>
        </Item>
        <ItemName>PHP</ItemName>
    </ItemList>
</Category>
<Category>
    <CategoryID>2</CategoryID>
    <CategoryName>Tool</CategoryName>
    <ItemList>
        <Item>
            <ItemName>ToolAbcde</ItemName>
            <ItemDetails>sth details</ItemDetails>
        </Item>
    </ItemList>
</Category></NewXML>
+1  A: 

The xslt spec has an extensive doucmentation on grouping, complete with examples at http://www.w3.org/TR/xslt20/#xsl-for-each-group. You are probably looking for the current-group() and current-grouping-key() functions. Also

Within the sequence constructor, the context item is the initial item of the relevant group, the context position is the position of this item among the sequence of initial items (one item for each group) arranged in processing order of the groups, the context size is the number of groups, the current group is the group being processed, and the current grouping key is the grouping key for that group.

Meaning that these two expressions would be equivalent inside xsl:for-each-group: CategoryId and current-group()[1]/CategoryId. Since CategoryId is the grouping key this is also the same as current-grouping-key(). Here is a complete example for your use case:

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output method="xml" indent="yes" encoding="utf-8" />

    <xsl:template match="/">
        <NewXml>
            <xsl:for-each-group select="ItemList/Item" group-by="CategoryID">
                <Category>
                    <CategoryID><xsl:value-of select="CategoryID" /></CategoryID>
                    <CategoryName><xsl:value-of select="CategoryName" /></CategoryName>
                    <ItemList>
                        <xsl:for-each select="current-group()">
                            <Item>
                                <ItemName><xsl:value-of select="ItemName" /></ItemName>
                                <ItemDetails><xsl:value-of select="ItemDetails" /></ItemDetails>
                            </Item>
                        </xsl:for-each>
                    </ItemList>
                </Category>
            </xsl:for-each-group>
        </NewXml>
    </xsl:template>

</xsl:stylesheet>
Jörn Horstmann
+1 for a very detailed and precise answer.
Dimitre Novatchev