You can create new elements with the <xsl:element> element, which is very useful if you need to determine a new elements name at run time.
This element has three attributes:
name (mandatory). Name of the element you want to create. Set to an attribute value template that returns a QName.
namespace (optional). The namespace URI of the new element. Set to an attribute value template returning a URI.
use-attribute-sets (optional). Specifies the attribute sets containing the attributes for this element. Set to a whitespace-separated list of QNames.
The <xsl:element> element contains a template body.
For example, say that I want to store the names of the planets in NAME attributes rather than in a <NAME> element in planets.xml, like this:
<?xml version="1.0"?> <?xml-stylesheet type="text/xml" href="planets.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> . . .
Suppose now that I want to use the value of that attribute to create new element names in the result document such as <Mercury> , <Venus> , and <Earth> :
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xml" href="planets.xsl"?> <PLANETS> <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--> </Mercury> . . .
In this case, I dont know the name of the output element until run time, so I cant just use a literal result element. I could cobble together a new element, treating it as text this way, where Im using the <xsl:text> elements disable-output-escaping attribute to output characters such as <:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml"/> <xsl:template match="@*node()"> <xsl:copy> <xsl:apply-templates select="@*node()"/> </xsl:copy> </xsl:template> <xsl:template match="PLANET"> <xsl:text disable-output-escaping="yes"><</xsl:text> <xsl:value-of select="@NAME"/> <xsl:text disable-output-escaping="yes">></xsl:text> <xsl:apply-templates/> <xsl:text disable-output-escaping="yes"></</xsl:text> <xsl:value-of select="@NAME"/> <xsl:text disable-output-escaping="yes">></xsl:text> </xsl:template> </xsl:stylesheet>
But this way is clumsy and it treats markup as simple text. On the other hand, I could create a new element using the name of a planet with <xsl:element> , getting the name of the new planet from the name attribute this way:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml"/> <xsl:template match="@*node()"> <xsl:copy> <xsl:apply-templates select="@*node()"/> </xsl:copy> </xsl:template> <xsl:template match="PLANET"> <xsl:element name="{@NAME}"> <xsl:apply-templates/> </xsl:element> </xsl:template> </xsl:stylesheet>
This is a lot cleaner and simpler. Here is the result, where Ive created the new elements, each with the name of a different planet and created at run time:
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xml" href="planets.xsl"?> <PLANETS> <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--> </Mercury> <Venus> <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--> </Venus> <Earth> <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--> </Earth> </PLANETS>
In this way, you can create new elements and name them when the XSLT transformation takes place.