xsl:import


<xsl:import> is a top-level element used to import the contents of one stylesheet module into another. The declarations in the importing stylesheet module have a higher import precedence than those in the imported module, which usually means that they will be used in preference, but the detailed rules vary for each type of declaration.

Changes in 2.0

There are no changes to the syntax of this instruction in XSLT 2.0. The rules for the href attribute have been reformulated: In effect, the way in which the URI is dereferenced to obtain a stylesheet module is now largely implementation defined. This allows for options such as catalogs or user -specified URI resolvers , as well as implementations that cache or precompile stylesheet modules.

Format

 <xsl:import   href = uri-reference /> 

Position

<xsl:import> is a top-level element, which means that it must appear as a child of the <xsl:stylesheet> element. Within an <xsl:stylesheet> element, the <xsl:import> child elements must come before any other children.

Attributes

Name

Value

Meaning

href

mandatory

URI

The URI of the stylesheet to be imported

Like all other XSLT elements, the <xsl:import> declaration may also have a «use-when » attribute. This is described in Chapter 3 (see page 122).

Content

None; the element is always empty.

Effect

The <xsl:import> declaration loads the stylesheet module identified in its href attribute. First we'll look at how this module is located, and then at the question of import precedence, which determines how the declarations in the imported module are used.

Locating the Stylesheet Module

The URI contained in the href attribute may be an absolute URI or a relative URI. If relative, it is interpreted relative to the base URI of the XML document or external entity containing the <xsl:import> element. For example, if a file main.xsl contains the element <xsl:import href="date.xsl"/> then the system will, by default, look for date.xsl in the same directory as main.xsl . You can change this behavior by using the xml:base attribute, as described in Chapter 2 on page 53. This allows you to specify a different base URI for resolving the relative URI.

The URI must identify an XML document that is a valid XSLT stylesheet module. The declarations in the imported stylesheet are logically inserted into the importing stylesheet at the point where the <xsl:import> element appears. However:

  • Imported declarations have lower import precedence than the declarations that appear directly in the importing stylesheet, or are incorporated into it using <xsl:include> . This is explained in more detail below.

  • Imported elements retain their base URI, so anything that involves referencing a relative URI is done relative to the original URI of the imported stylesheet. This includes, for example, expansion of further <xsl:import> elements, or use of URIs as arguments to the document() function.

  • When a namespace prefix is used (typically within a QName , but it also applies to freestanding prefixes such as those in the xsl:exclude-result-prefixes attribute of a literal result element), it is interpreted using only the namespace declarations in the original stylesheet module in which the QName occurred. An imported stylesheet module does not inherit namespace declarations from the module that imports it. This includes QNames constructed at execution time as the result of evaluating an expression, for example an expression used within an attribute value template for the name or namespace attribute of <xsl:element> .

  • The values of the version , extension-element-prefixes , exclude-result-prefixes , and xpath-default-namespace attributes that apply to an element in the imported stylesheet, as well as xml:lang and xml:space , are those that were defined in the <xsl:stylesheet> element of their own stylesheet module, not those on the <xsl:stylesheet> element of the importing module.

The imported stylesheet module may use the simplified stylesheet syntax described in Chapter 3. This allows an entire module to be defined as the content of an element such as <HTML> . It is then treated as if it were a stylesheet module containing a single template, whose match pattern is «/ » and whose content is the literal result element.

The imported stylesheet module may contain <xsl:include> statements to include further stylesheet modules, or <xsl:import> statements to import them. A stylesheet module must not directly or indirectly import itself.

It is not an error to import the same stylesheet module more than once, either directly or indirectly, but it is not usually a useful thing to do. The effect is that the same definitions or templates will be present with several different import precedences. The situation is exactly the same as if two stylesheet modules with different names but identical contents had been imported.

The href attribute must be a fixed value-it isn't possible to compute its value at runtime. This is because the first thing an XSLT processor does, long before any source document is available, is assemble the stylesheet from all its constituent modules and compile it into some internal representation. As with every other modern programming language, a program cannot change its own source code while executing. However, there is a new facility in XSLT 2.0 that allows stylesheets to be tailored to different environments. The «use-when » attribute is allowed on <xsl:import> (and indeed on any other XSLT element) to define a compile-time condition defining whether this element should be included or ignored. For example, you can write:

  <xsl:import href="xalan-rules.xsl"   use-when="system-property('xsl:product-name') = 'Xalan'"/>   <xsl:import href="saxon-rules.xsl"   use-when="system-property('xsl:product-name') = 'SAXON'"/>  

to import different modules depending on whether you are running Saxon or Xalan.

Determining the Import Precedence

Each stylesheet module that is imported has an import precedence. The rules are:

  • The precedence of a module that is imported is always lower than the precedence of the module importing it.

  • If one module imports several others, then the one it imports first has lower precedence than the next , and so on.

This means that in the structure shown in Figure 5-3, the highest precedence module is A followed by C, F, B, E, and finally D.

click to expand
Figure 5-3

If one stylesheet module incorporates another using <xsl:include> rather than <xsl:import> , it has the same import precedence as the module that includes it (Figure 5-4).

click to expand
Figure 5-4

Here J is included in E, so it has the same import precedence as E, and similarly E has the same import precedence as C. If you attach numeric values to the import precedence to indicate the ordering (the absolute values don't matter, the only significance is that a higher number indicates higher precedence), you could do so as follows :

A

B

C

D

E

F

G

H

J

6

3

5

2

5

1

2

4

5

The import precedence of a stylesheet module applies to all the declarations in that module, so for example the <xsl:template> elements in module E have a higher import precedence than those in G.

As <xsl:import> statements must occur before any other declarations in a stylesheet module, the effect of these rules is that if each <xsl:import> statement were to be replaced by the content of the module it imports, the declarations in the resulting combined stylesheet would be in increasing order of import precedence. This makes life rather easier for implementors. However, it does not mean that <xsl:import> is a straightforward textual substitution process, because there is still a need to distinguish cases where two objects (for example template rules) have the same import precedence because they came originally from the same stylesheet or from stylesheets that were included rather than imported.

The XSLT 2.0 specification introduces the concept of a stylesheet layer, which is a group of stylesheet modules that have the same import precedence because they refer to each other using <xsl:include> rather than <xsl:import> . In the example above modules D and G are in the same layer; C, E, and J are in the same layer; and each of the other modules is in a layer of its own. Within a stylesheet layer the specification describes the concept of declaration order, which is the order that the declarations (top-level elements) would appear in if included stylesheets were expanded at the point of the <xsl:include> statement. The stylesheet layers (rather than modules) are considered to form a tree, with <xsl:import> elements acting as the links from a parent to a child in the tree.

The stylesheet tree for the example above is shown in Figure 5-5.

click to expand
Figure 5-5

The concepts of stylesheet levels, declaration order, and the stylesheet tree have been used to tighten up the specification of how instructions such as <xsl: apply-imports > work. For example, an <xsl:apply-imports> instruction in module J can invoke a template in module H, because H is in a stylesheet layer that is a descendant of the layer that J is in.

Effect of Import Precedence

The import precedence of a declaration affects its standing relative to other declarations of the same type, and may be used to resolve conflicts. The effect is as shown in the table below for each kind of declaration.

Element type

Rules

<xsl:attribute-set>

If there are two attribute sets with the same expanded name, they are merged. If there is an attribute that is present in both, then the one from the attribute set with higher import precedence wins. It is a runtime error if there is no clear winner from this process (that is, if there are two or more values for an attribute that have the same precedence, and this is the highest precedence). The XSLT processor has the choice of reporting the error or choosing the one that was specified last (for a more precise definition of what "last" means, see <xsl:attribute-set> on page 214)

<xsl: character-map >

If there are several <xsl:character-map> declarations with the same name, then the one with highest import precedence wins. It is a compile-time error if this leaves no clear winner

<xsl:decimal-format>

All the <xsl:decimal-format> elements in the stylesheet that share the same name are effectively merged. For each attribute, if the value is explicitly present on more than one <xsl:decimal-format> element, then the one with highest import precedence wins. It is an error if there is no clear winner. The XSLT processor has the choice of reporting the error or choosing the one that was specified last

<xsl:function>

If there are several <xsl:function> declarations with the same name and arity (number of arguments), then the one with highest import precedence wins. It is a compile-time error if this leaves no clear winner

<xsl:import> and <xsl:include>

No conflicts arise; the import precedence of these elements is immaterial, except in determining the import precedence of the referenced stylesheet module

<xsl:import-schema>

If there are several <xsl:import-schema> declarations for the same target namespace (or for no target namespace) then the one with highest import precedence wins. If this leaves more than one, then the rules are defined by reference to the XML Schema specifications, which give implementations a great deal of latitude

<xsl:key>

All the key definitions are used, regardless of their import precedence. See <xsl:key> on page 332 for details

<xsl: namespace-alias >

If several aliases for the same stylesheet prefix are defined, the one with the highest import precedence is used. It is a compile-time error if there is no clear winner

<xsl:output>

All the <xsl:output> elements in the stylesheet that share the same name are effectively merged. In the case of the cdata-section-elements and use-character-maps attributes, the values from all the <xsl:output> elements are merged. For all the other attributes, if the value is explicitly present on more than one <xsl:output> element, then the one with highest import precedence wins. It is an error if there is no clear winner. The XSLT processor has the choice of reporting the error or choosing the one that was specified last

<xsl: strip-space > and <xsl: preserve-space >

If there is more than one <xsl:strip-space> or <xsl:preserve-space> element that matches a particular element name in the source document, then the one with highest import precedence is used. If this still leaves several that match, each one is assigned a priority, using the same rules as for the match pattern in <xsl:template> . Specifically, an explicit QName has higher priority than the form «prefix:* » , which in turn has higher priority than «* » . The one with highest priority is then used

It is an error if this leaves more than one match (even if they all give the same answer). The XSLT processor has the choice of reporting this as a runtime error or choosing the one that was specified last

If there are no matches for an element, whitespace nodes are preserved

<xsl:template>

When selecting a template rule for use with <xsl:apply-templates> , firstly all the template rules with a matching mode are taken. Of these, all those with a match pattern that matches the selected node are considered. If this leaves more than one, only those with the highest import precedence are considered. If this still leaves more than one, the one with highest priority is chosen : The rules for deciding the priority are given under <xsl:template> on page 450. It is an error if this still doesn't identify a clear winner. The XSLT processor has the choice of reporting the error or choosing the template rule that was specified last. (In practice, several processors output a warning message) In the case of named templates, if there are several <xsl:template> declarations with the same name attribute, then the one with highest import precedence wins. It is a compile-time error if this leaves no clear winner

<xsl:variable> and <xsl:param>

If there are several global <xsl:variable> or <xsl:param> declarations with the same name, then the one with highest import precedence wins. It is a compile-time error if this leaves no clear winner

Usage

The rules for <xsl:import> are so pervasive that one would imagine the facility is central to the use of XSLT, rather in the way inheritance is central to writing in Java. In practice, many stylesheets never need to use <xsl:import> , but you will almost certainly need it once you start to develop a family of stylesheets to handle a wide range of source document types.

Like inheritance in object-oriented languages, <xsl:import> is designed to allow the creation of a library or reusable components, only in this case, the components are modules of stylesheets. And the mechanism works in a very similar way to inheritance. For example, you might have a stylesheet that simply defines your corporate color scheme, as a set of global variables defining color names. Another stylesheet might be defined to produce the basic framesets for your site, referring to these color names to supply the background detail. Now if you want to use this general structure but to vary some detail, for example to modify one of the colors because it clashes with an image you are displaying on a particular page, you can define a stylesheet for this particular page that does nothing apart from redefining that one color. This is illustrated in Figure 5-6.

click to expand
Figure 5-6

Suppose the stylesheet module for corporate color definitions looks like this:

  <xsl:stylesheet xmlns:xsl="http    :    //www.w3.org/1999/XSL/Transform"   xmlns:color="http://acme.co.nz/colors"   version="1.0">   <xsl:variable name="color:blue" select="'#0088ff'"/>   <xsl:variable name="color:pink" select="'#ff0088'"/>   <xsl:variable name="color:lilac" select="'#ff00ff'"/>   </xsl:stylesheet>  

Now all the general-purpose stylesheets could <xsl:include> these definitions (without the need to <xsl:import> them unless they are being modified). This makes it easier to maintain the corporate brand image, because things are defined in one place only.

However, there are cases where you would want to depart from the general rule, and you can do so quite easily. If a particular document needs to use stylesheet C, but needs to vary the colors used, you can define stylesheet Z for it, as follows:

  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   xmlns:color="http://acme.co.nz/colors"   version="1.0">   <xsl:import href="general-stylesheet-C.xsl"/>   <xsl:variable name="color:lilac" select="'#cc00cc '"/>   </xsl:stylesheet>  

In fact, this might be the entire stylesheet. In common English, style Z is the same as style C but with a different shade of lilac. Note that all the references to variable «color:lilac » are interpreted as references to the definition in Z, even if the references occur in the same stylesheet module as a different definition of «color:lilac » .

As a general principle, to incorporate standard content into a stylesheet without change, use <xsl:include> . If there are definitions you want to override, use <xsl:import> .

Examples

The first example is designed to show the effect of <xsl:import> on variables.

Example 1: Precedenec of Variables
start example

This example demonstrates the precedence of global variables when the principal stylesheet module and an imported module declare variables with the same name.

Source

This example can be run with any source XML file.

Stylesheet

The principal stylesheet module is variables.xsl .

  <?xml version="1.0" encoding="iso-8859-1"?>   <xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   xmlns:acme="http://acme.com/xslt"   exclude-result-prefixes="acme">   <xsl:import href="boilerplate.xsl"/>   <xsl:output encoding="iso-8859-1" indent="yes"/>   <xsl:variable name="acme:company-name" select="'Acme Widgets Limited'"/>   <xsl:template match="/">   <c><xsl:value-of select="$acme:copyright"/></c>   </xsl:template>   </xsl:stylesheet>  

The imported stylesheet module is boilerplate.xsl .

  <?xml version="1.0" encoding="iso-8859-1"?>   <xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   xmlns:co="http://acme.com/xslt">   <xsl:variable name="co:company-name"   select="'Acme Widgets Incorporated'"/>   <xsl:variable name="co:copyright"   select="concat ('Copyright ', $co:company-name)    "/>    </xsl:stylesheet>  

Output

The output of this stylesheet will be:

  <?xml version="1.0" encoding="iso-8859-1" ?>   <c>Copyright  Acme Widgets Limited</c>  

This is because in the variable declaration of «$co:copyright » , the reference to variable «$co:company-name » matches the declaration of this variable in the principal stylesheet, because this has higher import precedence than the declaration in boilerplate.xsl .

The fact that different namespace prefixes are used in the two stylesheets is, of course, irrelevant: The prefix «acme » in the principal stylesheet maps to the same namespace URI as the prefix «co » in boilerplate.xsl , so the names are considered equivalent.

This example explicitly specifies encoding="iso-8859-1" for both the stylesheet modules and the output. Most of my examples only use ASCII characters , and since the default character encoding UTF-8 is a superset of ASCII, this works fine. This time, though, I've used the copyright symbol « » , which is not an ASCII character, so it's important to specify the character encoding that my text editor uses, which is iso-8859-1 (actually it's the Microsoft variant of it known as Windows ANSI, but this is close enough not to make a difference).

end example
 

The second example shows the effect of <xsl:import> on template rules.

Example 2: Precedence of Template Rules
start example

In this example I shall define a complete stylesheet standard-style.xsl to display poems in HTML, and then override one of its rules in an importing stylesheet. The files required are all in the subdirectory import in the download file for this chapter.

Source

This example works with the poem that we used in Chapter 1. In the download file it's available as poem.xml . It starts like this:

  <?xml version="1.0"?>   <poem>   <author>Rupert Brooke</author>   <date>1912</date>   <title>Song</title>   <stanza>   <line>And suddenly the wind comes soft,</line>   <line>And Spring is here again;</line>   <line>And the hawthorn quickens with buds of green</line>   <line>And my heart with buds of pain.</line>   </stanza>     etc.     </poem>  

Stylesheet A

Here is standard-style.xsl :

  <xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">   <xsl:template match="/">   <html>   <head>   <title><xsl:value-of select="//title"/></title>   </head>   <body>   <xsl:apply-templates/>   </body>   </html>   </xsl:template>   <xsl:template match="title">   <h1><xsl:apply-templates /></h1>   </xsl:template>   <xsl:template match="author">   <div align="right"><i>by </i>   <xsl:apply-templates/>   </div>   </xsl:template>   <xsl:template match="stanza">   <p><xsl:apply-templates/></p>   </xsl:template>   <xsl:template match="line">   <xsl:apply-templates/><br/>   </xsl:template>   <xsl:template match="date"/>   </xsl:stylesheet>  

Output A

When you run this stylesheet, the output starts like this (the actual layout may vary, of course, depending on which XSLT processor you use):

  <html>   <head>   <title>Song</title>   </head>   <body>   <div align="right"><i>by </i>Rupert Brooke</div>   <h1>Song</h1>   <p>   And suddenly the wind comes soft,<br>   And Spring is here again;<br>   And the hawthorn quickens with buds of green<br>   And my heart with buds of pain.<br>   </p>  

Stylesheet B

Now we want to create a variant of this in which the lines of the poem are numbered. This will act as the principal stylesheet when you want this form of output. Here it is in numbered-style.xsl :

  <xsl:stylesheet version="l.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">   <xsl:import href="standard-style.xsl"/>   <xsl:template match="line">   <xsl:number level="any" format="001"/>&#xa0; &#xa0;   <xsl:apply-imports/>   </xsl:template>   </xsl:stylesheet>  

Note the use of the character reference «&#xa0; » to output a nonbreaking space. In HTML this is normally done by writing «&nbsp; » . You can use this entity reference in the stylesheet if you like (it's simply a symbolic name for the Unicode character #xa0 ), but only if you declare it as an entity in the DTD. It's usually simpler just to use the numeric character reference.

Output B

This time the output starts like this. Again, the precise format depends on the processor (for example, some processors may output «&#xa0 » , or «&#160; » instead of «&nbsp; » ) but it should look the same when displayed in the browser:

  <html>   <head>   <title>Song</title>   </head>   <body>   <div align="right"><i>by </i>Rupert Brooke</div>   <h1>Song</h1>   <p>   001&nbsp;&nbsp:   And suddenly the wind comes soft,<br>   002&nbsp;&nbsp;   And Spring is here again;<br>   003&nbsp;&nbsp;   And the hawthorn quickens with buds of green<br>   004&nbsp;&nbsp;   And my heart with buds of pain.<br>   </p>  

All the template rules defined in standard-style.xsl are used as normal, except where the current node matches the pattern «line » . In this situation there are two possible templates that match the node, so the one with higher import precedence is chosen. This is the one in the importing stylesheet module, namely numbered-style.xsl . As a result, the lines of the poem are output with a preceding line number, calculated using the <xsl:number> instruction, which is described on page 359. The use of <xsl:apply-imports> means that once the line number has been output, the line is displayed in the normal way, using the template rule from the standard-style.xsl stylesheet.

end example
 

This use of <xsl:import> to customize the presentation produced by a stylesheet is very common. The rules in the importing stylesheet, which vary the standard presentation, are sometimes referred to as a customization layer. Sometimes the customization layer corresponds directly to an additional module in the schema or DTD: For example if the schema that you use for press releases is an extended version of the schema used for general company documents, then you will want to write a customization layer over the general-purpose stylesheet to handle the additional features found in press releases.

See Also

  • <xsl:include> on page 328

  • <xsl:apply-imports> on page 184




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