13.2 Importing Stylesheets

Like include, the import element is also a top-level element with one required attribute, href. Importing is similar to inclusion except that template rules from imported stylesheets have a lower precedence than template rules in the stylesheet that is doing the importing. Imported stylesheets allow you, when required, to override one template rule with another.

You can see import at work in the stylesheet import.xsl (Example 13-6), where imported.xsl is imported.

Example 13-6. A stylesheet using an import element
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="imported.xsl"/> <xsl:output method="text"/>     <xsl:template match="PopulationChange">  <xsl:text>Population Change: July 1, 2001 to July 1, 2002</xsl:text>  <xsl:call-template name="n1"/>  <xsl:text>Source: US Census Bureau</xsl:text>  <xsl:call-template name="n2"/>  <xsl:apply-templates select="State"/> </xsl:template>     <xsl:template match="State">  <xsl:text>Rank:</xsl:text>  <xsl:call-template name="sp1"/>  <xsl:value-of select="Rank"/>  <xsl:call-template name="n1"/>  <xsl:text>State:</xsl:text>  <xsl:call-template name="sp1"/>  <xsl:value-of select="Name"/>  <xsl:call-template name="n2"/> </xsl:template>     </xsl:stylesheet>

Notice that the import element is the first child of stylesheet. This is a special requirement that is, one or more import elements must immediately follow the stylesheet element.

The stylesheet, imported.xsl, is shown in Example 13-7.

Example 13-7. The imported stylesheet, which itself imports another stylesheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="wspace.xsl"/> <xsl:template match="State">  <xsl:text>State:</xsl:text>  <xsl:call-template name="sp1"/>  <xsl:value-of select="Name"/>  <xsl:call-template name="n1"/>  <xsl:text>Rank:</xsl:text>  <xsl:call-template name="sp1"/>  <xsl:value-of select="Rank"/>  <xsl:call-template name="n2"/> </xsl:template>     </xsl:stylesheet>

In turn, this stylesheet imports wspace.xsl, which you saw earlier in Example 13-3. When applied to top.xml:

xalan top.xml import.xsl

you get the following result:

Population Change: July 1, 2001 to July 1, 2002 Source: US Census Bureau     Rank: 1 State: California     Rank: 2 State: Texas     Rank: 3 State: New York

The outcome is identical to what you would expect from stylesheets included with include elements. The main difference, however, between include and import is that import establishes something called import precedence. Import precedence simply means that template rules in an importing stylesheet have precedence over any rules from a stylesheet that it imports, and that the order in which stylesheets are imported affects their import precedence in succession.

13.2.1 Import Tree

When you include a stylesheet using include, the top-level elements all but stylesheet elements are merged in with the top-level elements of the stylesheet that included it. When you import a stylesheet with import, that stylesheet is represented internally in something called an import tree. An import tree stores stylesheets in the order in which they were imported and includes the stylesheet element from each. If you import more than one stylesheet, each imported stylesheet is added to the import tree.

Just as a stylesheet can't include itself, a stylesheet can't import itself, either. You can import a stylesheet more than once, however, in which case any conflicts are worked out using the normal rules of template priority the last of two or more conflicting templates wins.

The following stylesheets, Examples 13-8 through 13-10, will show you import precedence in action. The precedence.xsl stylesheet (Example 13-8) imports two stylesheets, first.xsl (Example 13-9) and second.xsl (Example 13-10).

Example 13-8. A stylesheet importing two other stylesheets
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="second.xsl"/> <xsl:import href="first.xsl"/> <xsl:output method="text"/>     <xsl:template match="PopulationChange">  <xsl:text>Population Change: July 1, 2001 to July 1, 2002</xsl:text>  <xsl:call-template name="n1"/>  <xsl:text>Source: US Census Bureau</xsl:text>  <xsl:call-template name="n2"/>  <xsl:apply-templates select="State"/> </xsl:template>     </xsl:stylesheet>

This stylesheet also attempts to apply a template that matches the State element; however, no such template exists in precedence.xsl. One such template, however, does exist in the imported stylesheet first.xsl.

Example 13-9. A stylesheet containing a template for processing the State element
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="wspace.xsl"/>     <xsl:template match="State">  <xsl:text>Rank:</xsl:text>  <xsl:call-template name="sp1"/>  <xsl:value-of select="Rank"/>  <xsl:call-template name="n1"/>  <xsl:text>State:</xsl:text>  <xsl:call-template name="sp1"/>  <xsl:value-of select="Name"/>  <xsl:call-template name="n2"/> </xsl:template>     </xsl:stylesheet>

Another template exists in second.xsl, also imported into precedence.xsl (the differences between first.xsl and second.xsl are emphasized in bold).

Example 13-10. Another stylesheet containing a template for processing the State element
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="wspace.xsl"/>     <xsl:template match="State">  <xsl:text>State:</xsl:text>  <xsl:call-template name="sp1"/>  <xsl:value-of select="Name"/>  <xsl:call-template name="n1"/>  <xsl:text>Rank:</xsl:text>  <xsl:call-template name="sp1"/>  <xsl:value-of select="Rank"/>  <xsl:call-template name="n2"/> </xsl:template>     </xsl:stylesheet>

In first.xsl, rank is displayed first, followed by the state; in second.xsl, the state is displayed first, followed by rank. Because first.xsl is the last stylesheet that is imported, its template, which matches State, is invoked first, rather than the template in second.xsl. The rank comes before state in the output. When applied to top.xml with:

xalan top.xml precedence.xsl

the processor yields the following output:

Population Change: July 1, 2001 to July 1, 2002 Source: US Census Bureau     Rank: 1 State: California     Rank: 2 State: Texas     Rank: 3 State: New York

If you were to change the order in which the stylesheets were imported, that is, to this order:

<xsl:import href="first.xsl"/> <xsl:import href="second.xsl"/>

The import precedence would favor second.xsl and a transformation against that stylesheet would give you the states first, then the ranks:

Population Change: July 1, 2001 to July 1, 2002 Source: US Census Bureau     State: California Rank: 1     State: Texas Rank: 2     State: New York Rank: 3

Now, I'll show you how to manipulate import precedence with apply-imports.

13.2.2 Applying Imports

The apply-imports instruction element has no attributes and is always empty, that is, it has no children. (In XSLT 2.0, however, apply-imports can have one or more with-param children.) It applies templates from imported stylesheets that normally would not be used (it's somewhat like calling a method with super in Java). Example 13-11, the stylesheet apply-imports.xsl which produces XML output imports add.xsl and uses the apply-imports element.

Example 13-11. A stylesheet using apply-imports
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="add.xsl"/> <xsl:output method="xml" indent="yes"/>     <xsl:template match="PopulationChange">  <xsl:element name="topStates">   <xsl:apply-templates select="State"/>  </xsl:element> </xsl:template>     <xsl:template match="State">  <xsl:element name="stateData">   <xsl:element name="stateRank">    <xsl:value-of select="Rank"/>   </xsl:element>   <xsl:element name="stateName">    <xsl:value-of select="Name"/>   </xsl:element>   <xsl:apply-imports/>  </xsl:element> </xsl:template>     </xsl:stylesheet>

The add.xsl stylesheet, Example 13-12, also has a template that matches State elements.

Example 13-12. A stylesheet that will be applied through apply-imports
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <xsl:template match="State">  <xsl:element name="dataAdvice">   <xsl:text>July 2002 estimated population was </xsl:text>   <xsl:value-of select="Population"/>   <xsl:text>.</xsl:text>  </xsl:element> </xsl:template>     </xsl:stylesheet>

Usually the template in add.xsl would be disregarded because the template matching State in apply-imports.xsl has precedence over the one in add.xsl. The inclusion of apply-imports, however, tells the XSLT processor to invoke the template matching State in add.xsl, in addition to the one in apply-imports.xsl. Processing top.xml with apply-imports.xsl with this command:

xalan -i 1 top.xml apply-imports.xsl

produces the following output:

<?xml version="1.0" encoding="UTF-8"?> <topStates>  <stateData>   <stateRank>1</stateRank>   <stateName>California</stateName>   <dataAdvice>July 2002 estimated population was 35116033.</dataAdvice>  </stateData>  <stateData>   <stateRank>2</stateRank>   <stateName>Texas</stateName>   <dataAdvice>July 2002 estimated population was 21779893.</dataAdvice>  </stateData>  <stateData>   <stateRank>3</stateRank>   <stateName>New York</stateName>   <dataAdvice>July 2002 estimated population was 19157532.</dataAdvice>  </stateData> </topStates>

So apply-imports provides a way to apply more than one template to the same node, perhaps one for a general purpose and another for a special purpose. Now, we'll leave processing multiple stylesheets behind and move on to processing multiple XML documents with the document( ) function.



Learning XSLT
Learning XSLT
ISBN: 0596003277
EAN: 2147483647
Year: 2003
Pages: 164

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