[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] for-each-group - only get elements in each group


Subject: Re: [xsl] for-each-group - only get elements in each group
From: "Rick Quatro rick@xxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 20 Jan 2016 18:19:26 -0000

Hi Martin,

I am basically dropping the <Story> element and need to keep a flat
structure. Your solution basically works. However, I am trying to figure out
a more general solution because I may have a variable number of siblings
between the <Category> elements. For example, if this is my input:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Cases>
  <Story>
    <Category>Category1</Category>
    <Case>Case1</Case>
    <Author>Author1</Author>
    <Category>Category1</Category>
    <Case>Case2</Case>
    <Author>Author2</Author>
    <Category>Category1</Category>
    <Case>Case3</Case>
    <Author>Author3</Author>
    <Category>Category1</Category>
    <Case>Case4</Case>
    <Author>Author4</Author>
    <Category>Category2</Category>
    <Case>Case5</Case>
    <Author>Author5</Author>
    <Category>Category2</Category>
    <Case>Case6</Case>
    <Author>Author6</Author>
    <Category>Category2</Category>
    <Case>Case7</Case>
    <Author>Author7</Author>
    <Category>Category2</Category>
    <Case>Case8</Case>
    <Author>Author8</Author>
  </Story>
</Cases>

And this is my stylesheet and output:

<?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" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="/">
        <cases><xsl:apply-templates select="Cases"/></cases>
    </xsl:template>
    
    <xsl:template match="Cases">
        <xsl:for-each-group select="Story/Category" group-by=".">
            <category><xsl:copy-of
select="current-grouping-key()"/></category>
            <xsl:apply-templates
select="current-group()/following-sibling::*[position()&lt;=2]"/>
        </xsl:for-each-group>
    </xsl:template>
    
    <xsl:template match="Case">
        <Case><xsl:value-of select="."/></Case>
    </xsl:template>
    
    <xsl:template match="Author">
        <Author><xsl:value-of select="."/></Author>
    </xsl:template>
    
</xsl:stylesheet>

<?xml version="1.0" encoding="UTF-8"?>
<cases>
   <category>Category1</category>
   <Case>Case1</Case>
   <Author>Author1</Author>
   <Case>Case2</Case>
   <Author>Author2</Author>
   <Case>Case3</Case>
   <Author>Author3</Author>
   <Case>Case4</Case>
   <Author>Author4</Author>
   <category>Category2</category>
   <Case>Case5</Case>
   <Author>Author5</Author>
   <Case>Case6</Case>
   <Author>Author6</Author>
   <Case>Case7</Case>
   <Author>Author7</Author>
   <Case>Case8</Case>
   <Author>Author8</Author>
</cases>

There may be instances that I have additional siblings between some of the
<Category> elements. I want to grab everything after the first unique
<Category> element up to the next unique <Category> element. Thank you.

Rick


Current Thread