XML/XSLT stylesheet/for each group
Содержание
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>  <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>