<xsl:copy> and <xsl:copy-of>
These two elements copy information from a source node
directly to the result tree. <xsl:copy>
performs what is
known as a shallow
copy. This means that it copies only the node and any namespace not its
descendants or attributes. <xsl:copy-of>
performs a deep
copy, copying not only the node and any namespace, but all its attributes and
descendants.
<xsl:copy-of> is useful for copying sections of
the XML source tree unchanged to the result tree, while <xsl:copy>
gives more control of what will be copied. For example, we might want to list
some key data from Hamlet.xml. We could do this with the following simple
stylesheet (Playkey.xsl):
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
indent="yes"/>
<xsl:template
match="text()"/>
<xsl:template match="PLAY">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="TITLE |
PERSONAE">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
The result of this is to copy the element <PLAY>
(but not its descendants) to the result tree as the document element, then list
the title of the play, the Dramatis Personae, and the title of each Act and
Scene. Note that we have used the line:
<xsl:template match="text()"
/>
to ensure that the built-in templates do not cause
extraneous text to be output. The result when this is applied to Hamlet.xml
looks like this:
<?xml version="1.0"
encoding="utf-8"?>
<PLAY>
<TITLE>The Tragedy of Hamlet, Prince
of Denmark</TITLE>
<PERSONAE>
<TITLE>Dramatis Personae</TITLE>
<PERSONA>CLAUDIUS, king of Denmark.
</PERSONA>
<PERSONA>HAMLET, son to the late, and
nephew to the present king.</PERSONA>
<PERSONA>POLONIUS, lord chamberlain.
</PERSONA>
<PERSONA>HORATIO, friend to
Hamlet.</PERSONA>
<PERSONA>LAERTES, son to
Polonius.</PERSONA>
<PERSONA>LUCIANUS, nephew to the
king.</PERSONA>
<PGROUP>
<PERSONA>VOLTIMAND</PERSONA>
<PERSONA>CORNELIUS</PERSONA>
<PERSONA>ROSENCRANTZ</PERSONA>
<PERSONA>GUILDENSTERN</PERSONA>
<PERSONA>OSRIC</PERSONA>
<GRPDESCR>courtiers.</GRPDESCR>
</PGROUP>
<PERSONA>A Gentleman</PERSONA>
<PERSONA>A Priest. </PERSONA>
<PGROUP>
<PERSONA>MARCELLUS</PERSONA>
<PERSONA>BERNARDO</PERSONA>
<GRPDESCR>officers.</GRPDESCR>
</PGROUP>
<PERSONA>FRANCISCO, a
soldier.</PERSONA>
<PERSONA>REYNALDO, servant to
Polonius.</PERSONA>
<PERSONA>Players.</PERSONA>
<PERSONA>Two
Clowns, grave-diggers.</PERSONA>
<PERSONA>FORTINBRAS,
prince of Norway. </PERSONA>
<PERSONA>A
Captain.</PERSONA>
<PERSONA>English
Ambassadors. </PERSONA>
<PERSONA>GERTRUDE,
queen of Denmark, and mother to Hamlet. </PERSONA>
<PERSONA>OPHELIA,
daughter to Polonius.</PERSONA>
<PERSONA>Lords,
Ladies, Officers, Soldiers, Sailors, Messengers, and other
Attendants.</PERSONA>
<PERSONA>Ghost
of Hamlet's Father. </PERSONA>
</PERSONAE>
<TITLE>ACT
I</TITLE>
<TITLE>SCENE
I. Elsinore. A platform before the
castle.</TITLE>
<TITLE>SCENE
II. A room of state in the
castle.</TITLE>
<TITLE>SCENE
III. A room in Polonius'
house.</TITLE>
<TITLE>SCENE
IV. The platform.</TITLE>
<TITLE>SCENE
V. Another part of the
platform.</TITLE>
<TITLE>ACT
II</TITLE>
<TITLE>SCENE
I. A room in POLONIUS'
house.</TITLE>
<TITLE>SCENE
II. A room in the castle.</TITLE>
<TITLE>ACT
III</TITLE>
<TITLE>SCENE
I. A room in the castle.</TITLE>
<TITLE>SCENE
II. A hall in the castle.</TITLE>
<TITLE>SCENE
III. A room in the
castle.</TITLE>
<TITLE>SCENE
IV. The Queen's closet.</TITLE>
<TITLE>ACT
IV</TITLE>
<TITLE>SCENE
I. A room in the castle.</TITLE>
<TITLE>SCENE
II. Another room in the
castle.</TITLE>
<TITLE>SCENE
III. Another room in the
castle.</TITLE>
<TITLE>SCENE
IV. A plain in Denmark.</TITLE>
<TITLE>SCENE
V. Elsinore. A room in the
castle.</TITLE>
<TITLE>SCENE
VI. Another room in the
castle.</TITLE>
<TITLE>SCENE
VII. Another room in the
castle.</TITLE>
<TITLE>ACT
V</TITLE>
<TITLE>SCENE
I. A churchyard.</TITLE>
<TITLE>SCENE
II. A hall in the castle.</TITLE>
</PLAY>
Of course, we could equally well use the same stylesheet for
other plays marked up in the same format.
This example shows a common use of <xsl:copy-of>,
but perhaps a rather contrived example for <xsl:copy>,
since we could
equally well have used a different template for the <PLAY>
element:
<xsl:template match="PLAY">
<PLAY>
<xsl:apply-templates/>
</PLAY>
</xsl:template>
This would also have allowed us to use a different element
name in the result tree from that in the source tree. So let's look at another
use of <xsl:copy>.
We said earlier that <xsl:copy>
gives us more
control over the copying operation than <xsl:copy-of>.
We used this
just now to control which descendants of the <PLAY>
element we would copy.
Another use is if we have a source tree that is mainly XHTML, but with some
additional elements from a different namespace. Much of the web site at http://www.alphaxml.com
is written in XHTML. However, there is a glossary application that is used to
explain technical terms. An example of the source code that might be used on
this site is:
<p>The <em>Extensible Markup
Language</em> provides a universal mechanism for marking up data on the
web. Unlike <g:term>HTML</g:term>, which is a language based around
displaying data in a web browser, <g:term>XML</g:term> puts no
constraints on the purpose for which the data will be used, but merely
describes the structure of the data. XML can therefore be used (and is used)
for any application that involves the transfer of data across the web for
either display or computation purposes.</p>
Here, the <p>
and <em>
elements are from the XHTML namespace, which is used as the default for the
document. The <term>
element is from a different namespace for the glossary, using the prefix g.
When we process this, we want to copy the XHTML elements
unchanged, but carry out some additional processing on the <g:term>
elements. <xsl:copy>
lets us do this. This is an extract from the template used on that site
(reformatted for display):
<xsl:template
match="*|@*|text()">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()" />
</xsl:copy>
</xsl:template>
<xsl:template
match="g:term">
<a target="_blank"
class="glossary">
<xsl:attribute name="href">
glossary/glossary.asp?glossary=AlphaGlossary.xml&term=
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:value-of select="."/>
</a>
</xsl:template>
In this example, the first template will be run for all
elements, attributes and text nodes apart from the <g:term>
element (for which the second template takes priority). This will copy the node
to the result tree and apply templates for its children. If one of those
children is a <g:term>
element, the second template will be run. This simply creates an anchor (<a>)
element in the result tree with an href
attribute whose value depends on
the enclosed text. For the term "HTML", the result will be:
<a
target="_blank"
class="glossary
href="glossary/glossary.asp?glossary=AlphaGlossary.xml&term=HTML">
HTML
</a>