NetBeansв„ў IDE Field Guide: Developing Desktop, Web, Enterprise, and Mobile Applications (2nd Edition)

The main purpose of the <xsl:copy-of> instruction is to copy a sequence of nodes to the result sequence. This is a deep copy-when a node is copied, its descendants are also copied .

Changes in 2.0

A new copy-namespaces attribute is introduced: This gives you control over whether or not the unused namespaces of an element should be copied.

Two new attributes validation and type are available, to control whether and how the copied nodes are validated against a schema.

Format

<xsl:copy-of select = expression copy-namespaces? = "yes" "no" validation? = "strict" "lax" "preserve" "strip" type? = qname />

Position

<xsl:copy-of> is an instruction. It is always used within a sequence constructor.

Attributes

Name

Value

Meaning

select

mandatory

Expression

The sequence of nodes or atomic values to be copied to the output destination

copy-namespaces

optional

«yes » or «no »

Indicates whether the namespace nodes of an element should be copied; default is «yes »

validation

optional

«strict » , «lax » , «preserve » , or «skip »

Indicates whether and how the copied nodes should be subjected to schema validation, or whether existing type annotations should be retained or removed

type

optional

Lexical QName

Identifies a type declaration (either a built-in type, or a user -defined type imported from a schema) against which copied nodes are to be validated

The type and validation attributes are mutually exclusive: if one is present, the other must be absent.

Content

None; the element is always empty.

Effect

The result of evaluating the select expression can be any sequence, containing nodes, atomic values, or a mixture of the two. Each of the items is copied to the result sequence, as follows :

Usage and Examples

There are two principal uses for <xsl:copy-of> : It can be used when copying data to and from a temporary tree, and it can be used for copying a subtree unchanged from the input document to the output.

Copying Nodes to and From Temporary Trees

One use of <xsl:copy-of> in conjunction with temporary trees arises when you want to write the same collection of nodes to the output in more than one place. This might arise, for example, with page headers and footers. The construct allows you to assemble the required output fragment as the value of a variable, and then copy it to the final output destination as often as required.

Example: Using <xsl:copy-of> for Repeated Output

Source

The source file soccer.xml holds details of a number of soccer matches played during the World Cup finals in 1998.

<?xml version="1.0"?> <results group="A"> <match> <date>10-Jun-98</date> <team score="2">Brazil</team> <team score="1">Scotland</team> </match> <match> <date>10-Jun-98</date> <team score="2">Morocco</team> <team score="2">Norway</team> </match> <match> <date>16-Jun-98</date> <team score="1">Scotland</team> <team score="1">Norway</team> </match> <match> <date>16-Jun-98</date> <team score="3">Brazil</team> <team score="0">Morocco</team> </match> <match> <date>23-Jun-98</date> <team score="1">Brazil</team> <team score="2">Norway</team> </match> <match> <date>23-Jun-98</date> <team score="0">Scotland</team> <team score="3">Morocco</team> </match> </results>

Stylesheet

The stylesheet is in the file soccer.xsl .

It constructs an HTML table heading as a global tree-valued variable, and then uses <xsl:copy-of> every time it wants to output this heading. In this particular case the heading is fixed, but it could contain data from the source document, so long as the heading is the same each time it is output. If it contained calculated values, there would be a possible performance benefit by coding it this way rather than regenerating the heading each time.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="table-heading"> <tr> <td><b>Date</b></td> <td><b>Home Team</b></td> <td><b>Away Team</b></td> <td><b>Result</b></td> </tr> </xsl:variable> <xsl:template match="/"> <html><body> <h1>Matches in Group <xsl:value-of select="/*/@group"/></h1> <xsl:for each select="//match"> <h2><xsl:value-of select="concat(team[1], 'versus', team[2])"/> </h2> <table bgcolor="#cccccc" border="1" cellpadding="5"> <xsl:copy-of select="$table-heading"/> <tr> <td><xsl:value-of select="date"/>&#xa0;</td> <td><xsl:value-of select="team[1]"/>&#xa0;</td> <td><xsl:value-of select="team[2]"/>&#xa0;</td> <td><xsl:value-of select= "concat(team[1]/@score, '-', team[2]/@score)"/>&#xa0;</td> </tr> </table> </xsl:for-each> </body></html> </xsl:template> </xsl:stylesheet>

Output

(Apologies to soccer fans who know fully well that all these matches were played in France, on neither team's home territory. It's only an example!) See Figure 5-2.

Figure 5-2

 

In XSLT 1.0, temporary trees (then known as result tree fragments ; the term has been dropped in XSLT 2.0) were very limited in functionality. There were only two things you could do with them: You could copy them to another tree using <xsl:copy-of> , and you could convert them to a string. Most XSLT 1.0 implementations provide an extension function to convert a result tree fragment to a node set (containing the document node at the root of the tree), which greatly increases the usefulness of result tree fragments because it allows them to be used as working data structures. In XSLT 2.0, this capability has become part of the standard, so a temporary tree can be used in exactly the same way as a source document. In fact, in XSLT 2.0 a temporary tree is a node, so there is no need for a special conversion function.

Deep Copy

The other use for <xsl:copy-of> is that it provides a simple way of copying an entire subtree of the input document directly to the output. As <xsl:copy-of> does a deep copy, this is simpler than using <xsl:copy> , although it can only be used when the whole subtree is to be copied without change. For example, an XML document defining a product description might have an element called <overview> whose content is pure XHTML. You could copy this to the output HTML document with a template rule such as:

<xsl:template match="overview"> <div> <xsl:copy-of select="node()"/> </div> </xsl:template>

Unlike the examples using <xsl:copy> , there is no recursive application of template rules here: each child node of the <overview> element is copied to the output destination in a single operation, along with all its children.

The most common example of this technique is using <xsl:copy-of select="@*"/> to copy all the attributes of the current element. You can also use this selectively. To copy specific attributes use the following code:

<xsl:copy-of select="@name @height @width"/>

Copying all the attributes with specific exceptions is also straightforward using the new «except » operator in XPath 2.0:

<xsl:copy-of select="@* except @note"/>

Copying Namespace Nodes

The copy-namespaces attribute provides a choice as to whether the namespace nodes in a tree are copied or not. By default, all the namespaces are copied.

If namespaces are used only in the names of elements and attributes, then there is no need to copy namespace nodes. In the new tree, all the necessary namespace nodes will be created by virtue of the namespace fixup process, which is described under <xsl:element> on page 265 but applies equally to elements constructed using <xsl:copy> or <xsl:copy-of> . Copying unwanted namespace nodes generally does no harm, but they are unnecessary and can clutter the result document, and in some cases they can cause DTD-based validation to fail.

The real problem arises when namespace prefixes are used in the values of attributes or text nodes. This happens, for example, if the document is an XSLT stylesheet containing XPath expressions, if it is an XML Schema, if it uses «xsi:type » attributes that identify schema-defined types (the value of this attribute is a QName, and therefore contains a namespace prefix), or if it uses any other XML vocabulary that contains references to the names of elements or attributes within the document content. Since the XSLT processor cannot know that these references exist, and since the references depend on the existence of namespace nodes to resolve namespace prefixes to a URI, it is unsafe to shed the namespace nodes.

There are some cases where losing namespace nodes is very desirable. For example, if an XML document is wrapped in a SOAP envelope, and then subsequently removed from the envelope, the round trip can easily cause the SOAP namespaces defined for use in the envelope to stick to the content when it is extracted using <xsl:copy-of> . Under these circumstances, using «copy-namespaces="no" » can be useful to remove unwanted namespaces from the result. But it is only safe to use this option if you know that there are no namespace prefixes in the content of text nodes and attribute nodes.

Copying Type Annotations

The validation attribute of the <xsl:copy-of> instruction gives you four options on how to handle type annotations:

There may be cases where the existing nodes had a specific type annotation, but where revalidating the copied subtree either fails, or produces a different type annotation from the original. This is because the validation context may be different. If the subtree was originally validated as part of some larger tree, then it is possible that local element and attribute declarations were used on that occasion, whereas top-level element and attribute declarations are used this time. The top-level declarations may be either more or less permissive than the local declarations.

See Also

<xsl:copy> on page 240

<xsl:variable> on page 471

Категории