title: XSLT - Grouping by analyzing attribute values
body: <p>I have a xml like follows,</p>
  
  <pre><code>&lt;doc&gt;
      &lt;section&gt;
          &lt;p id="main"&gt;aa&lt;/p&gt;
          &lt;p id="main"&gt;bb&lt;/p&gt;
          &lt;p id="main"&gt;cc&lt;/p&gt;
          &lt;p id="para1"&gt;dd&lt;/p&gt;
          &lt;p id="st_main"&gt;ee&lt;/p&gt;
          &lt;p id="st_chap"&gt;ff&lt;/p&gt;
          &lt;p id="st_chap"&gt;gg&lt;/p&gt;
          &lt;p id="st_main"&gt;hh&lt;/p&gt;
          &lt;p id="main"&gt;ii&lt;/p&gt;
          &lt;p id="main"&gt;cc&lt;/p&gt;
          &lt;p id="para2"&gt;xx&lt;/p&gt;
          &lt;p id="main"&gt;yy&lt;/p&gt;
          &lt;p id="main"&gt;cc&lt;/p&gt;
      &lt;/section&gt;
  &lt;/doc&gt;
  </code></pre>
  
  <p>My requirements are</p>
  
  <p>1) grouping <code>&lt;p&gt;</code> by para attribute and add separate section to each <code>&lt;p&gt;</code> group.</p>
  
  <p>2) identify <code>&lt;p&gt;</code> node groups which id attribute starting from <code>st</code> put <code>&lt;st_start&gt;</code> and <code>&lt;st_end&gt;</code> at the start and the end on the group</p>
  
  <p>SO my desired output is,</p>
  
  <pre><code>&lt;doc&gt;
      &lt;section&gt;
          &lt;p id="main"&gt;aa&lt;/p&gt;
          &lt;p id="main"&gt;bb&lt;/p&gt;
          &lt;p id="main"&gt;cc&lt;/p&gt;
      &lt;/section&gt;
      &lt;section type="para1"&gt;
          &lt;p id="para1"&gt;dd&lt;/p&gt;
          &lt;ss_start/&gt;
          &lt;p id="st_main"&gt;ee&lt;/p&gt;
          &lt;p id="st_chap"&gt;ff&lt;/p&gt;
          &lt;p id="st_chap"&gt;gg&lt;/p&gt;
          &lt;p id="st_main"&gt;hh&lt;/p&gt;
          &lt;ss_end/&gt;
          &lt;p id="main"&gt;ii&lt;/p&gt;
          &lt;p id="main"&gt;cc&lt;/p&gt;
      &lt;/section&gt;
      &lt;section type="para2"&gt;
          &lt;p id="para2"&gt;xx&lt;/p&gt;
          &lt;p id="main"&gt;yy&lt;/p&gt;
          &lt;p id="main"&gt;cc&lt;/p&gt;
      &lt;/section&gt;
  &lt;/doc&gt;
  </code></pre>
  
  <p>My xsl to achieve this task is follows,</p>
  
  <pre><code>&lt;xsl:template match="section"&gt;
          &lt;xsl:for-each-group select="p" group-starting-with="p[starts-with(@id, 'para')]"&gt;
              &lt;section&gt;
                  &lt;xsl:if test="current-group()[1][not(@id='main')]"&gt;
                      &lt;xsl:attribute name="type" select="current-group()[1]/@id"/&gt;
                  &lt;/xsl:if&gt;
                  &lt;xsl:for-each-group select="current-group()" group-adjacent="@id"&gt;
                      &lt;xsl:if test="starts-with(current-grouping-key(),'st')"&gt;
                          &lt;ss_start/&gt;
                      &lt;/xsl:if&gt;            
                      &lt;xsl:apply-templates select="current-group()"/&gt;
                      &lt;xsl:if test="starts-with(current-grouping-key(),'st')"&gt;
                          &lt;ss_end/&gt;
                      &lt;/xsl:if&gt;
                  &lt;/xsl:for-each-group&gt;
              &lt;/section&gt;
          &lt;/xsl:for-each-group&gt;
      &lt;/xsl:template&gt;
  </code></pre>
  
  <p>This xsl gives me following result,</p>
  
  <pre><code>&lt;doc&gt;
      &lt;section&gt;
          &lt;p id="main"&gt;aa&lt;/p&gt;
          &lt;p id="main"&gt;bb&lt;/p&gt;
          &lt;p id="main"&gt;cc&lt;/p&gt;
      &lt;/section&gt;
      &lt;section type="para1"&gt;
          &lt;p id="para1"&gt;dd&lt;/p&gt;
          &lt;ss_start/&gt;
          &lt;p id="st_main"&gt;ee&lt;/p&gt;
          &lt;ss_end/&gt;
          &lt;ss_start/&gt;
          &lt;p id="st_chap"&gt;ff&lt;/p&gt;
          &lt;p id="st_chap"&gt;gg&lt;/p&gt;
          &lt;ss_end/&gt;
          &lt;ss_start/&gt;
          &lt;p id="st_main"&gt;hh&lt;/p&gt;
          &lt;ss_end/&gt;
          &lt;p id="main"&gt;ii&lt;/p&gt;
          &lt;p id="main"&gt;cc&lt;/p&gt;
      &lt;/section&gt;
      &lt;section type="para2"&gt;
          &lt;p id="para2"&gt;xx&lt;/p&gt;
          &lt;p id="main"&gt;yy&lt;/p&gt;
          &lt;p id="main"&gt;cc&lt;/p&gt;
      &lt;/section&gt;
  &lt;/doc&gt;
  </code></pre>
  
  <p>As you can see it adds <code>&lt;ss_start/&gt;</code> and <code>&lt;ss_end/&gt;</code> separately for <code>&lt;p id="st_main"&gt;</code> and <code>&lt;p id="st_chap"&gt;</code>. but I need to identify consecutive <code>&lt;p&gt;</code> elements which has attr <code>id</code> starting from <code>st</code> and cover those node by <code>&lt;ss_start/&gt;</code> and <code>&lt;ss_end/&gt;</code>.</p>
  
  <p>Can anyone suggest how could I modify my code to get my expected result ?</p>