xsl:copy-of


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 :

  • If the item is an atomic value, it is copied directly to the result sequence. So the instruction <xsl:copy-of select="1 to 5"/> has exactly the same effect as the instruction <xsl:sequence select="1 to 5"/> .

  • If the item is a text node, comment, processing instruction, or namespace node, then it is copied in exactly the same way as the <xsl:copy> instruction. The new node has the same name and string value as the original, but it has a new identity. For example, generate-id () applied to the new node will give a different result from generate-id() applied to the original.

  • If the item is an attribute node, then it is copied to create a new attribute node. The new attribute node has the same name and string value as the original, but has a new identity. The type annotation on the new attribute node depends on the values of the type and validation attributes, in the same way as for <xsl:attribute> as described on page 201.

  • If the item is an element node, then it is copied to create a new element node. This is a deep copy: All the attributes and children of the element node are also copied. The namespace nodes of this element, and of any descendant elements, are copied unless the copy-namespaces attribute is present with the value «no » . The base URIs of copied element nodes are unchanged (which means that any relative URIs in the content of these nodes retain their original meaning).

    The type annotation of the new element node depends on the values of the type and validation attributes. If the type attribute is specified, or if validation is set to «strip » , «strict » , or «lax » , then the effect is exactly as if new content were being constructed from scratch: Existing type annotations are discarded, and the copied content is revalidated to construct type annotations. In the case of «validation="preserve" » , the existing type annotations are copied over unchanged type annotations.

  • If the item is a document node, then it is copied to create a new document node. This is a deep copy: All the children of the document node are also copied. All copied nodes below this document node retain the name, string value, base URIs, and type annotations of their respective originals . If «validation="preserve" » is specified, then existing type annotations are copied unchanged; in other cases, document-level validation may occur to create new type annotations. This follows the rules for the <xsl:document> instruction, which means that it includes checks on uniqueness and referential constraints such as <xs:unique> , <xs:key> , and <xs:keyref> .

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
start example

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.

click to expand
Figure 5-2
end example
 

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:

  • The «strip » option removes all type annotations from the element and attribute nodes being copied, leaving them only with the generic type annotations xdt:untyped and xdt:untypedAtomic respectively. The main advantage of doing this is that you know exactly where you stand. This is the default, unless overridden using the default-validation attribute of the <xsl:stylesheet> element, and it means that the behavior will be the same whether or not the processor is schema-aware.

    Sometimes the «strip » option is needed because the existing type annotations do not make sense in a new context. For example, you might be copying a price-range attribute from an element in which the name is constrained to be a sequence of two numbers , to an element in which any string is allowed. Retaining the type annotation would cause spurious effects, or errors, if the attribute in its new context is then used for comparisons or sorting.

  • The «preserve » option leaves all the type annotations intact. One might expect that this would be the default, but the value «strip » was chosen for consistency with other instructions. Generally speaking, if the source nodes have been validated and annotated, this will often be the option that makes most sense on <xsl:copy-of> .

    This option works because the validity of an element or attribute depends only on its content (that is, on its attributes, its descendant elements, and their attributes). Cross-validation constraints that might be defined in the schema, such as id/ idref or key/keyref constraints, are not taken into account by the XPath type system. This means that if the source data has a particular type annotation, you can take it on trust that the data is valid against that type, and if you copy the whole subtree, then the new nodes will still be valid against these types.

  • The «strict » and «lax » options discard all existing type annotations, and then invoke the schema processor to validate the copied nodes. The same happens when you use the type attribute instead of the validation attribute. The way that validation works is exactly as described for the <xsl:element> instruction in the case of element nodes (see page 267), or the <xsl:attribute> instruction in the case of attribute nodes (see page 207), or the <xsl:document> instruction in the case of document nodes (see page 259). For other nodes and atomic values the validation and type attributes are ignored.

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




XSLT 2.0 Programmer's Reference
NetBeansв„ў IDE Field Guide: Developing Desktop, Web, Enterprise, and Mobile Applications (2nd Edition)
ISBN: 764569090
EAN: 2147483647
Year: 2003
Pages: 324

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net