XML/XSLT stylesheet/for each group

Материал из Web эксперт
Перейти к: навигация, поиск

Alternate group

File: Data.xml
<?xml version="1.0"?>
<SCENE>
  <TITLE>title 1</TITLE>
  <STAGEDIR>Enter</STAGEDIR>
  <SPEECH>
    <SPEAKER>I</SPEAKER>
    <LINE>A</LINE>
    <LINE>A</LINE>
    <LINE>C</LINE>
    <LINE>B</LINE>
    <LINE>H</LINE>
    <LINE>A</LINE>
  </SPEECH>
</SCENE>
File: Transform.xslt
<xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     
<xsl:output method="html" indent="yes"/>     
<xsl:template match="SPEECH">
  <tr>
  <xsl:for-each-group select="*" 
           group-adjacent="if (self::SPEAKER) then 0 else 1">
    <td valign="top">
       <xsl:for-each select="current-group()">
             <xsl:apply-templates select="."/>
          <xsl:if test="position()!=last()"><br/></xsl:if>
       </xsl:for-each>
    </td>
  </xsl:for-each-group>
  </tr>
</xsl:template>
<xsl:template match="/">
<html>
  <head>
    <title><xsl:value-of select="SCENE/TITLE"/></title>
  </head>
  <body>
    <h1><xsl:value-of select="SCENE/TITLE"/></h1>
    <xsl:apply-templates select="SCENE"/>
  </body>
</html>
</xsl:template>
<xsl:template match="ACT">
  <h2><xsl:value-of select="TITLE"/></h2>
  <xsl:apply-templates select="* except TITLE"/>
</xsl:template>
  
<xsl:template match="SCENE">
<table>
  <xsl:variable name="sequence" as="element()*">
    <xsl:for-each-group select="* except TITLE" 
        group-adjacent="if (self::SPEAKER) 
                        then "SPEAKERS" else "LINES"">
      <xsl:element name="{current-grouping-key()}">
        <xsl:copy-of select="current-group()"/>
      </xsl:element>
    </xsl:for-each-group>
  </xsl:variable>
  <xsl:for-each-group select="$sequence" group-starting-with="SPEAKERS">
    <tr>
      <xsl:for-each select="current-group()">
        <td valign="top">
          <xsl:for-each select="*">
            <xsl:apply-templates/>  
            <xsl:if test="position() != last()"><br/></xsl:if>
          </xsl:for-each>
        </td>
      </xsl:for-each>
    </tr>
  </xsl:for-each-group>
</table>
</xsl:template>   
<xsl:template match="STAGEDIR">
<i>&#xa0;&#xa0;<xsl:value-of select="."/></i>
</xsl:template>
</xsl:stylesheet>
Output:
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>title 1</title>
   </head>
   <body>
      <h1>title 1</h1>
      <table>
         <tr>
            <td valign="top">Enter<br>
                   I
                   A
                   A
                   C
                   B
                   H
                   A
                 
            </td>
         </tr>
      </table>
   </body>
</html>



Composite

File: Data.xml
<?xml version="1.0"?>
<staff>
  <employee name="J" department="sales" />
  <employee name="B" department="personnel" />
  <employee name="C" department="transport" />
  <employee name="W" department="personnel" />
  <employee name="M" department="sales" />
</staff>

File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />
  <xsl:template match="staff">
    <xsl:for-each-group select="employee" group-by="@location">
      <xsl:for-each-group select="current-group()"
        group-by="@department">
        <h2>
          <xsl:value-of
            select=""Department:", @department, "Location:", @location"
            separator=" " />
        </h2>
        <xsl:for-each select="current-group()">
          <xsl:sort select="@name" />
          <p>
            <xsl:value-of select="@name" />
          </p>
        </xsl:for-each>
      </xsl:for-each-group>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>



for-each-group select="current-group() except ."

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="body">
    <xsl:copy>
      <xsl:for-each-group select="*" group-starting-with="h1">
        <xsl:apply-templates select="." mode="group" />
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="h1" mode="group">
    <div>
      <head>
        <xsl:value-of select="." />
      </head>
      <xsl:for-each-group select="current-group() except ."
        group-starting-with="h2">
        <xsl:apply-templates select="." mode="group" />
      </xsl:for-each-group>
    </div>
  </xsl:template>
  <xsl:template match="h2" mode="group">
    <div>
      <head>
        <xsl:value-of select="." />
      </head>
      <xsl:for-each-group select="current-group() except ."
        group-starting-with="h3">
        <xsl:apply-templates select="." mode="group" />
      </xsl:for-each-group>
    </div>
  </xsl:template>
  <xsl:template match="h3" mode="group">
    <div>
      <head>
        <xsl:value-of select="." />
      </head>
      <xsl:copy-of select="current-group() except ." />
    </div>
  </xsl:template>
  <xsl:template match="p" mode="group">
    <xsl:copy-of select="current-group()" />
  </xsl:template>

</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
  A
  B
  C
  D
  E
  F
  G
  H
  I
  J
  K
  L



for-each-group select="html/body/*" group-adjacent

File: Data.xml
<?xml version="1.0"?>
<html>
  <body>
    <h2>S</h2>
    <p class="item">D <code>key</code> </p>
    <p class="item">S</p>
    <p class="note">T</p>
    <p class="note">M</p>
    <p class="note">X</p>
    <p class="item">F</p>
    <h2>Steps for grouping in XSLT 2.0</h2>
    <p class="item">A</p>
    <p class="item">B</p>
    <p class="note">C</p>
    <p class="item">D</p>
  </body>
</html>

File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" include-content-type="no"/>
  <xsl:template match="/">
      <xsl:for-each-group select="html/body/*"
          group-adjacent="if (self::p[@class="item"]) then 1 
                          else if (self::p[@class="note"]) then 2 
                          else 3">
          <xsl:choose>
            <xsl:when test="current-grouping-key() = 1">
              <ul>
                <xsl:for-each select="current-group()">
                  <li>
                    <xsl:copy-of select="@*[not(name()="class")]"/>
                    <xsl:apply-templates select="*|text()"/>
                  </li>
                </xsl:for-each>
              </ul>
            </xsl:when>
            <xsl:when test="current-grouping-key() = 2">
              <xsl:variable name="starting-point">
                <xsl:number count="p[@class="note"]" level="any" format="1"/>
              </xsl:variable>
                <p>
                      <xsl:value-of 
                        select="if (count(current-group()) gt 1)
                                then "Notes" 
                                else "Note""/>
                </p>
                    <ol start="{$starting-point}">
                      <xsl:for-each select="current-group()">
                        <li>
                          <xsl:copy-of select="@*[not(name()="class")]"/>
                          <xsl:apply-templates select="*|text()"/>
                        </li>
                      </xsl:for-each>
                    </ol> 
            </xsl:when>
            <xsl:otherwise>
              <xsl:for-each select="current-group()">
                <xsl:apply-templates select="."/>
              </xsl:for-each>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each-group>
  </xsl:template>
  <xsl:template match="*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
Output:
<h2>S</h2>
<ul>
   <li>D <code>key</code> 
   </li>
   <li>S</li>
</ul>
<p>Notes</p>
<ol start="1">
   <li>T</li>
   <li>M</li>
   <li>X</li>
</ol>
<ul>
   <li>F</li>
</ul>
<h2>Steps for grouping in XSLT 2.0</h2>
<ul>
   <li>A</li>
   <li>B</li>
</ul>
<p>Note</p>
<ol start="4">
   <li>C</li>
</ol>
<ul>
   <li>D</li>
</ul>



Group by department

File: Data.xml
<?xml version="1.0"?>
<staff>
  <employee name="J" department="sales" />
  <employee name="B" department="personnel" />
  <employee name="C" department="transport" />
  <employee name="W" department="personnel" />
  <employee name="M" department="sales" />
</staff>

File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />
  <xsl:template match="staff">
    <xsl:for-each-group select="employee" group-by="@department">
      <h2>
        <xsl:value-of select="current-grouping-key()" />
        <xsl:text> department</xsl:text>
      </h2>
      <xsl:for-each select="current-group()">
        <p>
          <xsl:value-of select="@name" />
        </p>
      </xsl:for-each>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>
Output:
<h2>sales department</h2>
<p>J</p>
<p>M</p>
<h2>personnel department</h2>
<p>B</p>
<p>W</p>
<h2>transport department</h2>
<p>C</p>



Multi-level

File: Data.xml
<?xml version="1.0"?>
<staff>
  <employee name="J" department="sales" location="New York" />
  <employee name="B" department="personnel" location="Los Angeles" />
  <employee name="C" department="transport" location="New York" />
  <employee name="W" department="personnel" location="Los Angeles" />
  <employee name="M" department="sales" location="Seattle" />
</staff>

File: Transform.xslt

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />
  <xsl:template match="staff">
    <xsl:for-each-group select="employee" group-by="@location">
      <xsl:sort select="current-grouping-key()" />
      <p class="indent0">
        <xsl:text>Location </xsl:text>
        <xsl:value-of select="current-grouping-key()" />
      </p>
      <xsl:for-each-group select="current-group()"
        group-by="@department">
        <xsl:sort select="current-grouping-key()" />
        <p class="indent1">
          <xsl:text>Location </xsl:text>
          <xsl:value-of select="current-grouping-key()" />
        </p>
        <xsl:for-each select="current-group()">
          <xsl:sort select="@name" />
          <p class="indent2">
            <xsl:text>Location </xsl:text>
            <xsl:value-of select="@name" />
          </p>
        </xsl:for-each>
      </xsl:for-each-group>
    </xsl:for-each-group>
  </xsl:template>
</xsl:stylesheet>
Output:
<p class="indent0">Location Los Angeles</p>
<p class="indent1">Location personnel</p>
<p class="indent2">Location B</p>
<p class="indent2">Location W</p>
<p class="indent0">Location New York</p>
<p class="indent1">Location sales</p>
<p class="indent2">Location J</p>
<p class="indent1">Location transport</p>
<p class="indent2">Location C</p>
<p class="indent0">Location Seattle</p>
<p class="indent1">Location sales</p>
<p class="indent2">Location M</p>



Sort by department

File: Data.xml
<?xml version="1.0"?>
<staff>
  <employee name="J" department="sales" />
  <employee name="B" department="personnel" />
  <employee name="C" department="transport" />
  <employee name="W" department="personnel" />
  <employee name="M" department="sales" />
</staff>
File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />
  <xsl:template match="staff">
    <xsl:for-each-group select="employee" group-by="@department">
      <xsl:sort select="current-grouping-key()" />
      <h2>
        <xsl:value-of select="current-grouping-key()" />
        <xsl:text> department</xsl:text>
      </h2>
      <xsl:for-each select="current-group()">
        <xsl:sort select="@name" />
        <p>
          <xsl:value-of select="@name" />
        </p>
      </xsl:for-each>
    </xsl:for-each-group>
  </xsl:template>
</xsl:stylesheet>
Output:
<h2>personnel department</h2>
<p>B</p>
<p>W</p>
<h2>sales department</h2>
<p>J</p>
<p>M</p>
<h2>transport department</h2>
<p>C</p>



use for-each-group

File: Data.xml
<?xml version="1.0"?>
<towns>
  <town>A</town>
  <town>B</town>
  <town>C</town>
  <town>D</town>
  <town>E</town>
  <town>F</town>
  <town>G</town>
  <town>H</town>
  <town>I</town>
  <town>J</town>
  <town>K</town>
  <town>L</town>
</towns>

File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:param name="cols" select="4" />
  <xsl:template match="towns">
    <table>
      <xsl:for-each-group select="town"
        group-adjacent="(position()-1) idiv $cols">
        <tr>
          <xsl:for-each select="current-group()">
            <td>
              <xsl:value-of select="." />
            </td>
          </xsl:for-each>
        </tr>
      </xsl:for-each-group>
    </table>
  </xsl:template>

</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<table>
   <tr>
      <td>A</td>
      <td>B</td>
      <td>C</td>
      <td>D</td>
   </tr>
   <tr>
      <td>E</td>
      <td>F</td>
      <td>G</td>
      <td>H</td>
   </tr>
   <tr>
      <td>I</td>
      <td>J</td>
      <td>K</td>
      <td>L</td>
   </tr>
</table>