9.2. The <xsl:copy> Instruction Element

The <xsl:copy> element creates a copy of the current node's markup. If the current node is an element, the element's tags, including the element-type name and its associated namespace, are copied. However, <xsl:copy> does not copy the attribute or children nodes of the element. The optional attribute, use-attribute-sets, can be used to include a set of attributes that was defined using the <xsl:attribute-set> element (see Section 6.6.1 for more information on the <xsl:attribute-set> element).The <xsl:copy> element is an instruction element that contains a template, as shown in the following element model definition:

<!-- Category: instruction -->

<xsl:copy

  use-attribute-sets = qnames>

  <!-- Content: template -->

</xsl:copy>

Working with <xsl:copy> is distinctively different from working with <xsl:copy-of> in two primary ways. On the one hand, the <xsl:copy> instruction element can contain children instruction elements, where the <xsl:copy-of> element cannot. Far more significantly, <xsl:copy-of> copies an entire node branch or RTF, where <xsl:copy> only copies the current node's markup. The children of the matched node are ignored, as are any attribute nodes. The <xsl:copy> effectively erases all the matched element's attributes in the output.

Using <xsl:copy> without any content in the template simply copies the element's tags from the input to the output. Because the <xsl:copy> element ignores children of the current node, this output will be an empty element, as shown in Example 9-2.

Example 9-2. Simple demonstration of <xsl:copy>.
<xsl:template match="block">
      <xsl:copy></xsl:copy>
</xsl:template>

This produces <block/>, an empty block element, for each block matched in the input. However, because <xsl:copy> contains a template, it is possible to use additional instruction elements and LREs to process and/or modify the content of the current node when it is copied. As shown in Example 9-3, adding content to the template causes the instantiation of the template to be applied to the current node within the context of the copied tag.

Example 9-3. Using <xsl:copy> to add content to the current node.
<xsl:template match="block">
      <xsl:copy>
            <name>
            <xsl:apply-templates/>
            </name>
      </xsl:copy>
</xsl:template>

In this example, the <xsl:copy> element sends the <block> and </block> tags to the output result tree for each <block> element. The <name> LRE appears in the output exactly as-is, and the children of the original input <block> element are sent through using the <xsl:apply-templates> element. The resulting XML structure, using the first <block>, is as follows:

<block><name>1st Street</name></block>

When <xsl:copy> is used to copy a namespaced node, the local name of the element is copied to the output as well as the prefix for that namespace.

If the element that was used to declare the namespace is not copied to the output with a template rule, the first element that uses the prefix for the namespace will be used to declare the namespace in the output result tree. The processor automatically handles the namespace declaration if it is not copied with a template rule.

Using <xsl:copy> and <xsl:copy-of> together, it is possible to create combinations of otherwise fairly unaltered node-sets from the XML data instance. As Example 9-4 shows, our obsessive city planners in the municipal division of Markup City are rearranging the streets, this time to have all <block>s in just one area, that of the <boulevard>.

Example 9-4. Using <xsl:copy> together with <xsl:copy-of>.
					STYLESHEET:

<?xml version="1.0">
<xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="1.0">
<xsl:template match="boulevard">
      <xsl:copy>
            <xsl:copy-of select="//block" />
      </xsl:copy>
</xsl:template>
<xsl:template match="parkway"/>
</xsl:stylesheet>

RESULT:

<boulevard>
<block>1st Street</block>
<block>2nd Street</block>
<block>3rd Street</block>
<block>First Street</block>
<block>Second Street</block>
<block>Third Street</block>
<block>Panorama Street</block>
<block>Highland Plaza</block>
<block>Hutchens Avenue</block>
<block>Wildwood Drive</block>
<block>Old Chimney Road</block>
<block>Carrol Circle</block>
</boulevard>

The template rule matching on the <boulevard> element contains an <xsl:copy> element used to copy the <boulevard> tags into the output result tree. We then take each <block> element from the input source document, regardless of its original location, and copy it with the <xsl:copy-of select="//block"/> instruction element. Finally, to remove the contents of the old <parkway>, we add an empty template rule, <xsl:template match="parkway"/>.

While it may not seem very useful to copy just the element's tags to the output, <xsl:copy> becomes very useful when the name of the current node is not known. As shown in Example 9-5, using <xsl:copy> inside a template that employs the wildcard * to match all the elements, each element's tags, will be copied into the output.

Example 9-5. Using <xsl:copy> to copy all elements.
<xsl:template match="*">
      <xsl:copy>
            <xsl:apply-templates />
      </xsl:copy>
</xsl:template>

This template will effectively copy the structure of the document, removing all the attributes. New attributes can then be added using <xsl:attribute> or the use-attribute-sets attribute. You can also copy the original attributes from an element using a combination of <xsl:for-each> (discussed in Section 9.3) and <xsl:copy>, as shown in Example 9-6.

Example 9-6. Using <xsl:copy> and <xsl:for-each> to copy attributes.
<xsl:template match="*">
      <xsl:copy>
            <xsl:for-each select="@*">
                  <xsl:copy/>
            </xsl:for-each>
            <xsl:apply-templates />
      </xsl:copy>
</xsl:template>

The <xsl:for-each> element selects all attributes, using the "@*" abbreviation, and the <xsl:copy> element inside the <xsl:for-each> copies the attribute name and its original value into the output result tree. The content of each element is processed with <xsl:apply-templates>. Note that the text nodes are still sent to the output because of built-in template rules, discussed in Chapter 3. To suppress text output, it would be necessary to add an empty template rule, <xsl:template match="text()"/>.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset