XML Tutorial/XSLT stylesheet/for each

Материал из Web эксперт
Версия от 18:22, 25 мая 2010; (обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

compares sorted and unsorted xsl:for-each element

File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
    <AAA>
      <BBB>
        <CCC>A</CCC>
      </BBB>
      <BBB/>
      <BBB/>
    </AAA>
    <AAA>
      <BBB/>
      <BBB>
        <CCC>B</CCC>
        <CCC>C</CCC>
        <CCC>D</CCC>
        <CCC>E</CCC>
      </BBB>
    </AAA>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
      <TABLE border="1">
        <TR>
          <td>Position</TH>
          <td>Last</TH>
          <td>Name</TH>
        </TR>
        <xsl:for-each select="//AAA[last()]//CCC">
          <TR>
            <TD>
              <xsl:value-of select="position()"/>
            </TD>
            <TD>
              <xsl:value-of select="last()"/>
            </TD>
            <TD>
              <xsl:value-of select="text()"/>
            </TD>
          </TR>
        </xsl:for-each>
      </TABLE>
      <TABLE border="1">
        <TR>
          <td>Position</TH>
          <td>Last</TH>
          <td>Name</TH>
        </TR>
        <xsl:for-each select="//AAA[last()]//CCC">
          <xsl:sort order="ascending" select="text()"/>
          <TR>
            <TD>
              <xsl:value-of select="position()"/>
            </TD>
            <TD>
              <xsl:value-of select="last()"/>
            </TD>
            <TD>
              <xsl:value-of select="text()"/>
            </TD>
          </TR>
        </xsl:for-each>
      </TABLE>
    </xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?><TABLE border="1"><TR><td>Position</TH><td>Last</TH><td>Name</TH></TR><TR><TD>1</TD><TD>4</TD><TD>B</TD></TR><TR><TD>2</TD><TD>4</TD><TD>C</TD></TR><TR><TD>3</TD><TD>4</TD><TD>D</TD></TR><TR><TD>4</TD><TD>4</TD><TD>E</TD></TR></TABLE><TABLE border="1"><TR><td>Position</TH><td>Last</TH><td>Name</TH></TR><TR><TD>1</TD><TD>4</TD><TD>E</TD></TR><TR><TD>2</TD><TD>4</TD><TD>C</TD></TR><TR><TD>3</TD><TD>4</TD><TD>B</TD></TR><TR><TD>4</TD><TD>4</TD><TD>D</TD></TR></TABLE>


for-each select="addressbook/address" and sort

File: Data.xml
<?xml version="1.0"?>
<!-- names.xml -->
<addressbook>
  <address>
    <name>
      <title>Mr.</title>
      <first-name>Doris</first-name>
      <last-name>Smith</last-name>
    </name>
    <street>1234 Main Street</street>
    <city>New York</city>
    <state>WI</state>
    <zip>48392</zip>
  </address>
  <address>
    <name>
      <title>Ms.</title>
      <first-name>Jane</first-name>
      <last-name>Lee</last-name>
    </name>
    <street>930-A Chestnut Street</street>
    <city>Twincity</city>
    <state>MA</state>
    <zip>02930</zip>
  </address>
</addressbook>

File: Transform.xslt
<?xml version="1.0"?>
<!-- namegrouper2a.xsl -->
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="/">
    <addressbook>
      <xsl:for-each select="addressbook/address">
        <xsl:sort select="zip"/>
        <xsl:copy-of select="."/>
      </xsl:for-each>
    </addressbook>
  </xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?><addressbook><address><name><title>Ms.</title><first-name>Jane</first-name><last-name>Lee</last-name></name><street>930-A Chestnut Street</street><city>Twincity</city><state>MA</state><zip>02930</zip></address><address><name><title>Mr.</title><first-name>Doris</first-name><last-name>Smith</last-name></name><street>1234 Main Street</street><city>New York</city><state>WI</state><zip>48392</zip></address></addressbook>


for-each select=//address[generate-id(.)=generate-id(key(zipcodes, zip)[1])]

File: Data.xml
<?xml version="1.0"?>
<addressbook>
  <address>
    <name>
      <title>Ms.</title>
      <first-name>Doris</first-name>
      <last-name>Smith</last-name>
    </name>
    <street>707 New Way</street>
    <city>New York</city>
    <state>ME</state>
    <zip>00218</zip>
  </address>
  <address>
    <name>
      <first-name>Jane</first-name>
      <last-name>Lee</last-name>
    </name>
    <street>283 First Avenue</street>
    <city>Big City</city>
    <state>MA</state>
    <zip>02718</zip>
  </address>
</addressbook>
File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="no"/>
  <xsl:key name="zipcodes" match="address" use="zip"/>
  <xsl:template match="/">
    <table border="1">
      <xsl:for-each select="//address[generate-id(.)=generate-id(key("zipcodes", zip)[1])]">
        <xsl:sort select="zip"/> 
        <xsl:for-each select="key("zipcodes", zip)">
          <xsl:sort select="name/last-name"/>
          <xsl:sort select="name/first-name"/>
          <tr>
            <xsl:if test="position() = 1">
              <td valign="center" bgcolor="#999999">
                <xsl:attribute name="rowspan">
                  <xsl:value-of select="count(key("zipcodes", zip))"/>
                </xsl:attribute>
                <b>
                  <xsl:text>Zip code </xsl:text><xsl:value-of select="zip"/>
                </b>
              </td>
            </xsl:if>
            <td align="right">
              <xsl:value-of select="name/first-name"/>
              <xsl:text> </xsl:text>
              <b><xsl:value-of select="name/last-name"/></b>
            </td>
            <td>
              <xsl:value-of select="street"/>
              <xsl:text>, </xsl:text>
              <xsl:value-of select="city"/>
              <xsl:text>, </xsl:text>
              <xsl:value-of select="state"/>
              <xsl:text> </xsl:text>
              <xsl:value-of select="zip"/>
            </td>
          </tr>
        </xsl:for-each>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>
Output:
<table border="1"><tr><td valign="center" bgcolor="#999999" rowspan="1"><b>Zip code 00218</b></td><td align="right">Doris <b>Smith</b></td><td>707 New Way, New York, ME 00218</td></tr><tr><td valign="center" bgcolor="#999999" rowspan="1"><b>Zip code 02718</b></td><td align="right">Jane <b>Lee</b></td><td>283 First Avenue, Big City, MA 02718</td></tr></table>


for-each select=preceding-sibling::address[zip=./zip]

File: Data.xml
<?xml version="1.0"?>
<addressbook>
  <address>
    <name>
      <title>Ms.</title>
      <first-name>Doris</first-name>
      <last-name>Smith</last-name>
    </name>
    <street>707 New Way</street>
    <city>New York</city>
    <state>ME</state>
    <zip>00218</zip>
  </address>
  <address>
    <name>
      <title>Ms.</title>
      <first-name>Jane</first-name>
      <last-name>Lee</last-name>
    </name>
    <street>930-A Street</street>
    <city>Twincity</city>
    <state>MA</state>
    <zip>02930</zip>
  </address>
</addressbook>
File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="no"/>
  <xsl:variable name="newline">
  <xsl:text></xsl:text>
  </xsl:variable>
  <xsl:template match="/">
    <xsl:text>Addresses sorted by zip code</xsl:text>
    <xsl:value-of select="$newline"/>
    <xsl:for-each select="addressbook/address">
      <xsl:sort select="zip"/>
      <xsl:choose>
        <xsl:when test="not(preceding-sibling::address[zip=./zip])">
          <xsl:value-of select="$newline"/>
          <xsl:text>Zip code </xsl:text>
          <xsl:value-of select="zip"/>
          <xsl:text> (</xsl:text>
          <xsl:value-of select="city"/>
          <xsl:text>, </xsl:text>
          <xsl:value-of select="state"/>
          <xsl:text>): </xsl:text>
          <xsl:value-of select="$newline"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:message terminate="no">
            <xsl:text>./zip=</xsl:text><xsl:value-of select="./zip"/><xsl:text>, </xsl:text>
            <xsl:for-each select="preceding-sibling::address[zip=./zip]">
              <xsl:text>preceding-sibling=</xsl:text><xsl:value-of select="name/first-name"/><xsl:text> </xsl:text><xsl:value-of select="name/last-name"/>
            </xsl:for-each>
          </xsl:message>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:if test="name/title">
        <xsl:value-of select="name/title"/>
        <xsl:text> </xsl:text>
      </xsl:if>
      <xsl:value-of select="name/first-name"/>
      <xsl:text> </xsl:text>
      <xsl:value-of select="name/last-name"/>
      <xsl:value-of select="$newline"/>
      <xsl:value-of select="street"/>
      <xsl:value-of select="$newline"/>
      <xsl:value-of select="$newline"/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
Output:
Addresses sorted by zip codeZip code 00218 (New York, ME): Ms. Doris Smith707 New WayMs. Jane Lee930-A Street


Nested for-each loop with sorting

File: Data.xml
<?xml version="1.0"?>
<addressbook>
  <address>
    <name>
      <title>Ms.</title>
      <first-name>Doris</first-name>
      <last-name>Smith</last-name>
    </name>
    <street>707 New Way</street>
    <city>New York</city>
    <state>ME</state>
    <zip>00218</zip>
  </address>
</addressbook>
File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="no"/>
  <xsl:strip-space elements="*"/>
  <xsl:variable name="newline">
  <xsl:text></xsl:text>
  </xsl:variable>
  <xsl:template match="/">
    <xsl:for-each select="addressbook/address">
      <xsl:sort select="name/last-name"/>
      <xsl:sort select="name/first-name"/>
      <xsl:for-each select=".">
        <xsl:if test="name/title">
          <xsl:value-of select="name/title"/>
          <xsl:text> </xsl:text>
        </xsl:if>
        <xsl:value-of select="name/first-name"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="name/last-name"/>
        <xsl:value-of select="$newline"/>
        <xsl:value-of select="street"/>
        <xsl:value-of select="$newline"/>
        <xsl:value-of select="city"/>
        <xsl:text>, </xsl:text>
        <xsl:value-of select="state"/>
        <xsl:text>  </xsl:text>
        <xsl:value-of select="zip"/>
        <xsl:value-of select="$newline"/>
        <xsl:value-of select="$newline"/>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
Output:
Ms. Doris Smith707 New WayNew York, ME  00218


Output xml elements in for-each loop

File: Data.xml
<?xml version="1.0"?>
<addressbook>
  <address>
    <name>
      <title>Ms.</title>
      <first-name>Doris</first-name>
      <last-name>Smith</last-name>
    </name>
    <street>707 New Way</street>
    <city>New York</city>
    <state>ME</state>
    <zip>00218</zip>
  </address>
  <address>
    <name>
      <title>Ms.</title>
      <first-name>Jane</first-name>
      <last-name>Lee</last-name>
    </name>
    <street>930-A Street</street>
    <city>Twincity</city>
    <state>MA</state>
    <zip>02930</zip>
  </address>
</addressbook>
File: Transform.xslt

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no"/>
  <xsl:strip-space elements="*"/>
  <xsl:variable name="newline">
  <xsl:text></xsl:text>
  </xsl:variable>
  <xsl:template match="/">
    <addressbook>
      <xsl:for-each select="addressbook/address">
        <xsl:sort select="name/last-name"/>
        <xsl:sort select="name/first-name"/>
        <xsl:copy-of select="."/>
      </xsl:for-each>
    </addressbook>
  </xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?><addressbook><address><name><title>Ms.</title><first-name>Doris</first-name><last-name>Smith</last-name></name><street>707 New Way</street><city>New York</city><state>ME</state><zip>00218</zip></address><address><name><title>Ms.</title><first-name>Jane</first-name><last-name>Lee</last-name></name><street>930-A Street</street><city>Twincity</city><state>MA</state><zip>02930</zip></address></addressbook>


The xsl:for-each element allows all nodes in a node-set to be processed according to the XSLT instructions nested inside the xsl:for-each element.

Use for-each to output table row
File: Data.xml 
<?xml version="1.0"?>
<results group="A">
  <match>
    <date>10-Jun-98</date>
    <team score="2">team 1</team>
    <team score="1">team 2</team>
  </match>
  <match>
    <date>10-Jun-98</date>
    <team score="2">team 3</team>
    <team score="2">team 4</team>
  </match>
  <match>
    <date>16-Jun-98</date>
    <team score="1">team 2</team>
    <team score="1">team 4</team>
  </match>
</results>
File: Transform.xslt
<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">
  <xsl:variable name="league">
    <xsl:apply-templates select="results" />
  </xsl:variable>
  <xsl:template match="/">
    <html>
      <head>
        <title>League Table</title>
      </head>
      <body>
        <h1>League Table</h1>
        <table border="2" cellpadding="5">
          <thead>
            <td>Team</th>
            <td>Played</th>
            <td>Won</th>
            <td>Lost</th>
            <td>Drawn</th>
            <td>For</th>
            <td>Against</th>
          </thead>
          <tbody>
            <xsl:for-each select="$league/league/team">
              <tr>
                <td>
                  <xsl:value-of select="@name" />
                </td>
                <td>
                  <xsl:value-of select="@played" />
                </td>
                <td>
                  <xsl:value-of select="@won" />
                </td>
                <td>
                  <xsl:value-of select="@lost" />
                </td>
                <td>
                  <xsl:value-of select="@drawn" />
                </td>
                <td>
                  <xsl:value-of select="@for" />
                </td>
                <td>
                  <xsl:value-of select="@against" />
                </td>
              </tr>
            </xsl:for-each>
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:transform>
Output:
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>League Table</title>
   </head>
   <body>
      <h1>League Table</h1>
      <table border="2" cellpadding="5">
         <thead>
            <td>Team</th>
            <td>Played</th>
            <td>Won</th>
            <td>Lost</th>
            <td>Drawn</th>
            <td>For</th>
            <td>Against</th>
         </thead>
         <tbody></tbody>
      </table>
   </body>
</html>


Use for-each loop to output list items

File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- tutorial.xml -->
<tutorial>
  <section>
    <title>Java</title>
    <panel>
      <title>Introduction</title>
      <!-- ... -->
    </panel>
    <panel>
      <title>Swing</title>
      <!-- ... -->
    </panel>
    <panel>
      <title>GUI</title>
      <!-- ... -->
    </panel>
    <panel>
      <title>2D animation</title>
      <!-- ... -->
    </panel>
  </section>
</tutorial>

File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<!-- tutorial.xsl -->
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html"/>
  <xsl:template match="tutorial">
    <xsl:for-each select="section">
      <h1>
        <xsl:text>Section </xsl:text>
        <xsl:value-of select="position()"/>
        <xsl:text>. </xsl:text>
        <xsl:value-of select="title"/>
      </h1>
      <ul>
        <xsl:for-each select="panel">
          <li>
            <xsl:value-of select="position()"/>
            <xsl:text>. </xsl:text>
            <xsl:value-of select="title"/>
          </li>
        </xsl:for-each>
      </ul>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
Output:
<h1>Section 1. Java</h1>
<ul>
   <li>1. Introduction</li>
   <li>2. Swing</li>
   <li>3. GUI</li>
   <li>4. 2D animation</li>
</ul>


xsl:for-each instruction contains a template, which is applied to each node selected with select attribute.

File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
    <AAA id="a1" pos="start">
      <BBB id="b1"/>
      <BBB id="b2"/>
    </AAA>
    <AAA id="a2">
      <BBB id="b3"/>
      <BBB id="b4"/>
      <CCC id="c1">
        <DDD id="d1"/>
      </CCC>
      <BBB id="b5">
        <CCC id="c2"/>
      </BBB>
    </AAA>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
      <xsl:for-each select="//BBB">
        <DIV style="color:red">
          <xsl:value-of select="name()"/>
          <xsl:text> id=</xsl:text>
          <xsl:value-of select="@id"/>
        </DIV>
      </xsl:for-each>
      <xsl:for-each select="source/AAA/CCC">
        <DIV style="color:navy">
          <xsl:value-of select="name()"/>
          <xsl:text> id=</xsl:text>
          <xsl:value-of select="@id"/>
        </DIV>
      </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?><DIV style="color:red">BBB id=b1</DIV><DIV style="color:red">BBB id=b2</DIV><DIV style="color:red">BBB id=b3</DIV><DIV style="color:red">BBB id=b4</DIV><DIV style="color:red">BBB id=b5</DIV>