Altering Document Structure Based on Input

So far, the templates in this chapter have been fairly rigid skeletons, specifying exactly what should go into the output document, in what order. But you can use XSLT elements such as <xsl:element> , <xsl:attribute> , <xsl:text> , and so on to create new nodes on the fly, based on what you find in the input document. I'll take a look at how this works now.

Creating Attribute Templates

Say that you wanted to convert the text in some elements to attributes in other elements; how could you do it? Attribute values must be quoted in XML, but you can't just use expressions like these, where I'm taking the values of < NAME > , <MASS> , and <DAY> elements and trying to make them into attribute values:

 <xsl:template match="PLANET">      <PLANET NAME="<xsl:value-of select="NAME"/>"         MASS="<xsl:value-of select="MASS"/>"         DAY="<xsl:value-of select="DAY"/>"     /> 

This won't work because you can't use < inside attribute values as I have here. Instead, you must use an expression such as {NAME} . Here's the proper XSLT:

Listing ch13_16.xsl
 <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="PLANETS">     <HTML>         <HEAD>             <TITLE>                 Planets             </TITLE>         </HEAD>         <BODY>             <xsl:apply-templates select="PLANET"/>         </BODY>     </HTML> </xsl:template> <xsl:template match="PLANET">  <PLANET NAME="{NAME}"   MASS="{MASS}"   DAY="{DAY}"   />  </xsl:template> </xsl:stylesheet> 

Here's the resulting document. Note that I've been able to convert the values in various elements to attributes:

 <HTML>  <HEAD> <TITLE>                 Planets             </TITLE> </HEAD> <BODY> <PLANET DAY="58.65" MASS=".0553" NAME="Mercury"> </PLANET> <PLANET DAY="116.75" MASS=".815" NAME="Venus"> </PLANET> <PLANET DAY="1" MASS="1" NAME="Earth"> </PLANET> </BODY> </HTML> 

You can even include multiple expressions in curly braces, like this, where I'm adding the units for mass and day measurements from the UNITS attribute in the original elements:

Listing ch13_17.xsl
 <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="PLANETS">     <HTML>         <HEAD>             <TITLE>                 Planets             </TITLE>         </HEAD>         <BODY>             <xsl:apply-templates select="PLANET"/>         </BODY>     </HTML> </xsl:template> <xsl:template match="PLANET">     <PLANET NAME="{NAME}"  MASS="{MASS} {@UNITS}"   DAY="{DAY} {@UNITS}"  /> </xsl:template> </xsl:stylesheet> 

Creating New Elements

You can create new elements with the <xsl:element> element. For example, say that I store the name of planets in a NAME attribute instead of a <NAME> element in ch13_01.xml, like this:

 <?xml version="1.0"?>  <?xml-stylesheet type="text/xml" href="ch13_02.xsl"?> <PLANETS>  <PLANET NAME="Mercury">  <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>     .     .     . 

I could create a new element using the name of the planet with <xsl:element> , supplying the name of the new planet with the name attribute and enclosing a <MASS> element this way:

Listing ch13_18.xsl
 <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="PLANETS">     <HTML>         <HEAD>             <TITLE>                 Planets             </TITLE>         </HEAD>         <BODY>             <xsl:apply-templates select="PLANET"/>         </BODY>     </HTML> </xsl:template> <xsl:template match="PLANET">  <xsl:element name="{@NAME}">   <MASS><xsl:value-of select="MASS"/></MASS>   </xsl:element>  </xsl:template> </xsl:stylesheet> 

Here is the result, where I've created a new <mercury> element:

 <HTML>  <HEAD> <TITLE>                 Planets             </TITLE> </HEAD> <BODY> <Mercury> <MASS>.0553</MASS> </Mercury>     .     .     . 

In this way, you can create new elements and name them when the XSLT transformation takes place.



Real World XML
Real World XML (2nd Edition)
ISBN: 0735712867
EAN: 2147483647
Year: 2005
Pages: 440
Authors: Steve Holzner

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