The <xsl:copy> element enables you to copy a node from the source tree to the output tree. Note that this is a shallow copy, however, which does not copy any of the nodes descendents or attributes. This element has one attribute:
use-attribute-sets . Specifies the names of attribute sets to be applied to a created element. Set to a whitespace-separated list of QNames . You can use the attribute only when the context node is an element; see Chapter 6 for the details on attribute sets.
This element can contain a template body, which is used only when the node to copy is a root node or an element. Note that using <xsl:copy> does nothing when used on the root node, because the root of the output document is created automatically.
Heres an example; this stylesheet first appeared in Chapter 2, and all it does is copy all elements from the source document to the result document:
<?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="*"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> </xsl:stylesheet>
However, <xsl:copy> does not copy attributes, so heres the result when this stylesheet is used on planets.xml:
<?xml version="1.0" encoding="UTF-8"?> <PLANETS> <PLANET> <NAME>Mercury</NAME> <MASS>.0553</MASS> <DAY>58.65</DAY> <RADIUS>1516</RADIUS> <DENSITY>.983</DENSITY> <DISTANCE>43.4</DISTANCE> </PLANET> <PLANET> <NAME>Venus</NAME> <MASS>.815</MASS> <DAY>116.75</DAY> <RADIUS>3716</RADIUS> <DENSITY>.943</DENSITY> <DISTANCE>66.8</DISTANCE> </PLANET> <PLANET> <NAME>Earth</NAME> <MASS>1</MASS> <DAY>1</DAY> <RADIUS>2107</RADIUS> <DENSITY>1</DENSITY> <DISTANCE>128.4</DISTANCE> </PLANET> </PLANETS>
Copying attributes, too, is a little more difficult, because you have to specifically find a way to apply <xsl:copy> to each elements attributes. That can be done, for example, with <xsl:for-each> , which is shown in Chapter 5:
<?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="*"> <xsl:copy> <xsl:for-each select="@*"> <xsl:copy/> </xsl:for-each> <xsl:apply-templates/> </xsl:copy> </xsl:template> </xsl:stylesheet>
Heres the resultnote that this time, the attributes are intact:
<?xml version="1.0" encoding="UTF-8"?> <PLANETS> <PLANET> <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> </PLANET> <PLANET> <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> </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> </PLANET> </PLANETS>
However, theres an easier way of making sure that you copy all the children, attributes, and other descendents of nodes: You can use <xsl:copy-of> rather than <xsl:copy> .
Making Deep CopiesYoull see a way of using <xsl:copy> to make a deep copy of a document in Chapter 4, which describes the node function and explains how to call the same template recursively. |