xsl: next-match


xsl: next -match

The <xsl:next-match> instruction allows more than one template rule to be applied to the same node in a source document. When <xsl:apply-templates> selects a node, it finds the best match template rule to process this node. Within this template rule, you can use the <xsl:next-match> instruction to invoke the next-best matching rule, and so on.

Changes in 2.0

This instruction is new in XSLT 2.0.

Format

 <xsl:next-match>  ( <xsl:with-param>  <xsl:fallback> ) * </xsl:next-match> 

Position

<xsl:next-match> is an instruction, and is always used within a sequence constructor.

Attributes

None.

Content

The element may be empty, or it may contain one or more <xsl:with-param> and <xsl:fallback> elements. An XSLT 2.0 processor will ignore the <xsl:fallback> instructions; they are allowed so that fallback behavior can be defined for use when the stylesheet is processed using an XSLT 1.0 processor. For details, see <xsl:fallback> on page 271.

Effect

The effect of the <xsl:next-match> instruction is very similar to <xsl: apply-imports > . The main difference is that with <xsl:apply-imports> , the only template rules that can be invoked are those in imported stylesheet modules. By contrast, <xsl:next-match> can invoke other template rules of lower priority in the same stylesheet module, and can also invoke template rules that have lower import precedence because they were imported into the parent stylesheet module earlier than the current template rule.

There is a clear analogy here with object-oriented programming. Writing a template rule that overrides another is like writing a method that overrides a method defined on the superclass. <xsl:next-match> behaves analogously to the super() function in object-oriented programming languages, allowing the new template rule to refine the behavior of the original template rule, rather than replacing it completely.

<xsl:next-match> , like <xsl:apply-imports> , relies on the concept of a current template rule. A template rule becomes the current template rule when it is invoked using <xsl:apply-templates> , <xsl:apply-imports> , or <xsl:next-match> . Using <xsl:call-template> does not change the current template rule. However, using <xsl:for-each> makes the current template rule null, until such time as the <xsl:for-each> terminates, when the previous value is reinstated. The current template rule is also null while global variables and attribute sets are being evaluated.

Within the stylesheet as a whole, there are potentially several template rules that match the context node. The rules for the <xsl:apply-templates> instruction define an ordering of these rules: They are considered first in decreasing order of import precedence, then within each import precedence in decreasing order of priority, and finally within each priority, by the order of the declarations in the stylesheet (it is actually an error to have two rules with the same priority, but the processor is allowed to ignore this error and select whichever comes last in the stylesheet). At the end of the list is the built-in template rule for the particular kind of node. What <xsl:next-match> does is choose the template rule that comes next in this pecking order, after the current template rule.

It is possible to specify parameters to be supplied to the called template, using <xsl:with-param> elements contained within the <xsl:next-match> element. These work in the same way as parameters for <xsl:call-template> and <xsl:apply-templates> ; if the name of the supplied parameter matches the name of an <xsl:param> element within the called template, the parameter will take this value, otherwise it will take the default value supplied in the <xsl:param> element. It is not an error to supply parameters that don't match any <xsl:param> element in the called template rule, they will simply be ignored. However, if the called template specifies a parameter with «required="yes" » , then a runtime error occurs if no value is supplied for this parameter.

Usage and Examples

The intended usage pattern behind <xsl:next-match> is illustrated by the following example.

One template rule might contain a general-purpose rule for formatting headings, as follows :

  <xsl:template match="heading" priority="1">   <xsl:number level="multiple" count="div1div2div3" format="1.1"/>   <a name="{generate-id()}">   <xsl:value-of select="."/>   </a>   </xsl:template>  

Another set of template rules contains specific rules for particular levels of heading:

  <xsl:template match="divl/heading" priority="2">   <h1><xsl:next-match/></h1>   </xsl:template>   <xsl:template match="div2/heading" priority="2">   <h2><xsl:next-match/></h2>   </xsl:template>   <xsl:template match="div3/heading" priority="2">   <h3><xsl:next-match/></h3>   </xsl:template>  

These template rules each invoke the first rule using <xsl:next-match> , which avoids duplicating the common code in the template rule for each level of heading, and makes it easier to define changes later.

In this example I have made the priorities explicit, but in fact the default priorities could have been used. I always prefer to use explicit priorities when several rules match the same nodes, because it makes it clear to someone reading the stylesheet what your intentions were when you wrote it.

On this occasion there are three specialized rules, each invoking one generalized rule. But there are other problems where the structure can be inverted, so that the general rule invokes the special rule. For example, suppose you want to use a special color to render any inline text element that has the attribute «highlight="yes" » . You might use a set of template rules like this:

  <xsl:template match="term" priority="1">   <i><xsl:apply-templates/></i>   </xsl:template>   <xsl:template match="emph" priority="1">   <b><xsl:apply-templates/></b>   </xsl:template>   <xsl:template match="formula" priority="1">   <code><xsl:apply-templates/></code>   </xsl:template>  

and then process the highlight attribute in a higher priority template rule:

  <xsl:template match="*[@highlight='yes']" priority="2">   <span class="highlight"><xsl:next-match/></span>   </xsl:template>  

Unlike <xsl:apply-imports> , where invoking multiple template rules is possible only by defining multiple stylesheet modules, <xsl:next-match> allows several rules to be defined within a single module, which is often preferable because it makes the logic more clear.

Note that both <xsl:next-match> and <xsl:apply-imports> impose the constraint that the two (or more) template rules that match a node in the source tree work on the source node completely independently of each other. Neither rule can see or modify the nodes that the other rule has written to the result tree. This also means that (as the examples above show) the second rule can only create nodes that are children or siblings of the nodes created by the first rule; it cannot create parent nodes.

In some situations, therefore, other solutions might work better. In particular, another design pattern is to use a multipass transformation whereby one template rule creates a temporary tree, which it then processes using a second template rule (perhaps in a different mode). The code tends to look like this:

  <xsl:template match="diagram">   <xsl:variable name="temp">   <div>   <title><xsl:value-of select="caption"/></title>   <body><xsl:copy-of select="content"/></body>   </div>   </xsl:variable>   <xsl:apply-templates select="$temp/div"/>   </xsl:template>  

This design pattern does not require use of <xsl:next-match> or <xsl:apply-imports> .

See Also

  • <xsl:apply-imports> on page 184

  • <xsl:fallback> on page 271

  • <xsl:param> on page 392

  • <xsl:with-param> on page 488




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