This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Template Matching


Hi Jeff,

> I have XML coming from a SQL database. The XSLT checks to see if the
> "IsActive" attribute in the z:row node is true. If it is, then a
> checkbox is ticked. I am having a little trouble understanding
> matching. What is the most efficent template match for the
> processor? I can't find a definitive answer on what the first
> template match should be compared to the second template. I am using
> template match="/" for the first and template match="rs:data" for
> the second. Is there a better way?

The ordering of templates has (almost) no significance within a
stylesheet. The general activity of an XSLT processor is that you tell
it to process a set of nodes and it works through them one by one,
trying to find a template to match each of them and adding the result
of applying that template to the result tree.

When an XSLT processor starts processing an XML document, the first
node that it needs to find a template for is the root node (/). If you
use xsl:apply-templates (without a select attribute) then you are
telling the processor to find and apply templates to the children of
the node that it's currently processing. So if you have
<xsl:apply-templates /> in the template that matches the root node,
the processor will try to process the document element ('xml' in your
case).

If you don't include a template that matches a particular node, then
the XSLT processor uses the built-in templates. Basically these tell
the processor to keep working down the tree. So in your case, if you
don't provide a template for the 'xml' element, then the processor
will try to find a template to process the 'rs:data' element; if you
don't provide a template that matches the 'rs:data' element then the
processor will try to find a template to use on the 'z:row' elements
and so on.

One way to work out what templates you should have is to try to
work out correspondences between the document you're processing and
the output that you want. In your example, the mapping seems to be:

  xml     -> table
  rs:data -> tr
  z:row   -> td

[Note that I've mapped the document element (xml) to the table
element, rather than mapping the root node to the table element.
Either one will have the same effect, but I usually reserve the
template that matches the root node for higher-level control, such as
if I want to have a multi-stage transformation or merge two
stylesheets together.]

So I would organise the stylesheet with a template for each of the
types of nodes with something along the lines of:

<xsl:template match="xml">
  <table width="400" cellpadding="0" cellspacing="0" border="0">
    <!-- this applies templates to the rs:data element(s), which are
         matched by the following template -->
    <xsl:apply-templates />
  </table>
</xsl:template>

<xsl:template match="rs:data">
  <tr>
    <!-- this applies templates to the z:row elements, which are
         matched by the following template -->
    <xsl:apply-templates />
  </tr>
</xsl:template>

<xsl:template match="z:row">
  <xsl:variable name="lowercase-name"
                select="translate(@DayOfTheWeek, 'SMTWF', 'smtwf')" />
  <td width="100">
    <input type="checkbox"
           name="{$lowercase-name}" id="{$lowercase-name}">
      <xsl:if test="@IsActive = 'True'">
        <xsl:attribute name="checked">checked</xsl:attribute>
        <xsl:attribute name="onclick">
          <xsl:text>scheduleDay_click('</xsl:text>
          <xsl:value-of select="@DayOfTheWeek" />')<xsl:text />
        </xsl:attribute>
      </xsl:if>
      <xsl:value-of select="@DayOfTheWeek" />
    </input>
  </td>
</xsl:template>

[Note that to add a boolean attribute like checked to an element in
XHTML, you need to give it the value equal to its name, so you need
<xsl:attribute name="checked">checked</xsl:attribute> rather than just
<xsl:attribute name="checked" />.]

In terms of efficiency, if you don't need to process document-oriented
data, you might save a tiny amount of time by using xsl:for-each
rather than xsl:apply-templates to manage the element processing,
because the XSLT processor doesn't have to search for the template to
use, but it's rarely worth it. In terms of the positioning of
different templates, I suppose that you might save something by
putting the more frequently-required templates near the top of the
stylesheet, but it might have absolutely no effect (it probably
depends on the implementation). In terms of the patterns that you use,
it's generally best to keep the match patterns of templates as simple
as possible so that it's easy for an XSLT processor to test a node
against it.

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]