The xsl:key Element: Matching by Key

The <xsl:key> Element: Matching by Key

You use the <xsl:key> element when you want to create a key and match nodes using that key. The <xsl:key> element has the following attributes:

  • name (mandatory). The name of the key; set to a QName.

  • match (mandatory). Set to a match pattern to match the nodes to which this key applies.

  • use (mandatory). Set to an expression used to determine the value of the key.

Keys give you an easy way to identify elements, and you can match specific keys with the pattern key(). Chapter 4 gave you an introduction to single-valued keys. In that example, I used a key to match planets whose COLOR attribute was set to BLUE, which in that case was the Earth:

 <?xml version="1.0"?>  <?xml-stylesheet type="text/xml" href="planets.xsl"?>  <PLANETS>          .          .          .      <PLANET COLOR="BLUE">          <NAME>Earth</NAME>          <MASS UNITS="(Earth = 1)">1</MASS>          <DAY UNITS="days">1</DAY>          <RADIUS UNITS="miles">2107</RADIUS>          <DENSITY UNITS="(Earth = 1)">1</DENSITY>          <DISTANCE UNITS="million miles">128.4</DISTANCE><!--At perihelion-->      </PLANET>  </PLANETS> 

I created a key named COLOR that matches <PLANET> elements by checking their COLOR attribute. That key, COLOR , looks like this:

 <?xml version="1.0"?>  <xsl:stylesheet version="1.1"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">      <xsl:key name="COLOR" match="PLANET" use="@COLOR"/>          .          .          . 

Then I used the pattern key() to match <PLANET> elements with the COLOR attribute set to BLUE this way:

 <?xml version="1.0"?>  <xsl:stylesheet version="1.1"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">      <xsl:key name="COLOR" match="PLANET" use="@COLOR"/>      <xsl:template match="/PLANETS">          <HTML>              <HEAD>                  <TITLE>                      The Planets Table                  </TITLE>              </HEAD>              <BODY>                  <H1>                      The Planets Table                  </H1>                  <TABLE BORDER="2">                      <TR>                          <TD>Name</TD>                          <TD>Mass</TD>                          <TD>Radius</TD>                          <TD>Day</TD>                      </TR>                      <xsl:apply-templates select="key('COLOR', 'BLUE')"/>                  </TABLE>              </BODY>          </HTML>      </xsl:template>          .          .          . 

And heres the resultas you can see, Earth was the only planet that matched the pattern:

 <HTML>      <HEAD>          <TITLE>              The Planets Table          </TITLE>      </HEAD>      <BODY>          <H1>              The Planets Table          </H1>          <TABLE BORDER="2">              <TR>                  <TD>Name</TD>                  <TD>Mass</TD>                  <TD>Radius</TD>                  <TD>Day</TD>              </TR>              <TR>                  <TD>Earth</TD>                  <TD>1 (Earth = 1)</TD>                  <TD>2107 miles</TD>                  <TD>1 days</TD>              </TR>          </TABLE>      </BODY>  </HTML> 

However, theres more possible here. For example, multiple nodes can match a key, which means that the pattern using that key will return a node set. For example, say all planets had the same value for the COLOR attribute, unknown:

 <?xml version="1.0"?>  <?xml-stylesheet type="text/xml" href="planets.xsl"?>  <PLANETS>      <PLANET COLOR="UNKNOWN">          <NAME>Mercury</NAME>          <MASS UNITS="(Earth = 1)">.0553</MASS>          <DAY UNITS="days">58.65</DAY>          <RADIUS UNITS="miles">1516</RADIUS>          <DENSITY UNITS="(Earth = 1)">.983</DENSITY>          <DISTANCE UNITS="million miles">43.4</DISTANCE><!--At perihelion-->      </PLANET>      <PLANET COLOR="UNKNOWN">          <NAME>Venus</NAME>          <MASS UNITS="(Earth = 1)">.815</MASS>          <DAY UNITS="days">116.75</DAY>          <RADIUS UNITS="miles">3716</RADIUS>          <DENSITY UNITS="(Earth = 1)">.943</DENSITY>          <DISTANCE UNITS="million miles">66.8</DISTANCE><!--At perihelion-->      </PLANET>      <PLANET COLOR="UNKNOWN">          <NAME>Earth</NAME>          <MASS UNITS="(Earth = 1)">1</MASS>          <DAY UNITS="days">1</DAY>          <RADIUS UNITS="miles">2107</RADIUS>          <DISTANCE UNITS="million miles">128.4</DISTANCE><!--At perihelion-->          <DENSITY UNITS="(Earth = 1)">1</DENSITY>      </PLANET>  </PLANETS> 

Now when you create the COLOR this way: <xsl:key name="COLOR" match="PLANET" use="@COLOR"/> and match to it with this pattern: key(COLOR, BLUE), then you match all three planets:

 <HTML>      <HEAD>          <TITLE>              The Planets Table          </TITLE>      </HEAD>      <BODY>          <H1>              The Planets Table          </H1>          <TABLE BORDER="2">              <TR>                  <TD>Name</TD>                  <TD>Mass</TD>                  <TD>Radius</TD>                  <TD>Day</TD>              </TR>              <TR>                  <TD>Mercury</TD>                  <TD>.0553 (Earth = 1)</TD>                  <TD>1516 miles</TD>                  <TD>58.65 days</TD>              </TR>              <TR>                  <TD>Venus</TD>                  <TD>.815 (Earth = 1)</TD>                  <TD>3716 miles</TD>                  <TD>116.75 days</TD>              </TR>              <TR>                  <TD>Earth</TD>                  <TD>1 (Earth = 1)</TD>                  <TD>2107 miles</TD>                  <TD>1 days</TD>              </TR>          </TABLE>      </BODY>  </HTML> 

In addition to using a key that matches several nodes, a node can also match several values for one key. For example, you might set up a key to use the <NAME> element inside a <PLANET> element. But what if each <PLANET> element had more than one <NAME> element, as in this example:

 <?xml version="1.0"?>  <?xml-stylesheet type="text/xml" href="planets.xsl"?>  <PLANETS>      <PLANET>          <NAME>Mercury</NAME>          <NAME>Sister Planet</NAME>          <MASS UNITS="(Earth = 1)">.0553</MASS>          <DAY UNITS="days">58.65</DAY>          <RADIUS UNITS="miles">1516</RADIUS>          <DENSITY UNITS="(Earth = 1)">.983</DENSITY>          <DISTANCE UNITS="million miles">43.4</DISTANCE><!--At perihelion-->      </PLANET>      <PLANET>          <NAME>Venus</NAME>          <NAME>Sister Planet</NAME>          <MASS UNITS="(Earth = 1)">.815</MASS>          <DAY UNITS="days">116.75</DAY>          <RADIUS UNITS="miles">3716</RADIUS>          <DENSITY UNITS="(Earth = 1)">.943</DENSITY>          <DISTANCE UNITS="million miles">66.8</DISTANCE><!--At perihelion-->      </PLANET>      <PLANET>          <NAME>Earth</NAME>          <MASS UNITS="(Earth = 1)">1</MASS>          <DAY UNITS="days">1</DAY>          <RADIUS UNITS="miles">2107</RADIUS>          <DENSITY UNITS="(Earth = 1)">1</DENSITY>          <DISTANCE UNITS="million miles">128.4</DISTANCE><!--At perihelion-->      </PLANET>  </PLANETS> 

In this case, each <NAME> element is checked for a match to the key. For example, say that I wanted to match <NAME> elements with the text Sister Planet. Heres the stylesheet:

 <?xml version="1.0"?>  <xsl:stylesheet version="1.1"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">      <xsl:key name="NAME" match="PLANET" use="NAME"/>      <xsl:template match="/PLANETS">          <HTML>              <HEAD>                  <TITLE>                      The Planets Table                  </TITLE>              </HEAD>              <BODY>                  <H1>                      The Planets Table                  </H1>                  <TABLE BORDER="2">                      <TR>                          <TD>Name</TD>                          <TD>Mass</TD>                          <TD>Radius</TD>                          <TD>Day</TD>                      </TR>                      <xsl:apply-templates select="key('NAME', 'Sister Planet')"/>                  </TABLE>              </BODY>          </HTML>      </xsl:template>      <xsl:template match="PLANET">         <TR>            <TD><xsl:value-of select="NAME"/></TD>            <TD><xsl:apply-templates select="MASS"/></TD>            <TD><xsl:apply-templates select="RADIUS"/></TD>            <TD><xsl:apply-templates select="DAY"/></TD>         </TR>     </xsl:template>      <xsl:template match="MASS">          <xsl:value-of select="."/>          <xsl:text> </xsl:text>          <xsl:value-of select="@UNITS"/>      </xsl:template>          .          .          .      <xsl:template match="DAY">          <xsl:value-of select="."/>          <xsl:text> </xsl:text>          <xsl:value-of select="@UNITS"/>      </xsl:template>  </xsl:stylesheet> 

And heres the result document:

 <HTML>      <HEAD>          <TITLE>              The Planets Table          </TITLE>      </HEAD>      <BODY>          <H1>              The Planets Table          </H1>          <TABLE BORDER="2">              <TR>                  <TD>Name</TD>                  <TD>Mass</TD>                  <TD>Radius</TD>                  <TD>Day</TD>              </TR>              <TR>                  <TD>Mercury</TD>                  <TD>.0553 (Earth = 1)</TD>                  <TD>1516 miles</TD>                  <TD>58.65 days</TD>              </TR>              <TR>                  <TD>Venus</TD>                  <TD>.815 (Earth = 1)</TD>                  <TD>3716 miles</TD>                  <TD>116.75 days</TD>              </TR>          </TABLE>      </BODY>  </HTML> 


Inside XSLT
Inside Xslt
ISBN: B0031W8M4K
EAN: N/A
Year: 2005
Pages: 196

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net