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 TemplatesSay 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 ElementsYou 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. |