81

In

<xsl:template name="temp_name" mode="mode">

What is the meaning of mode? I searched many many resource, but i couldn't find example for that. So can anybody explain with an example?

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
Venkat
  • 20,802
  • 26
  • 75
  • 84

3 Answers3

98

It isn't too meaningful to give a template both a name and a mode.

The name attribute fully identifies a template and there cannot be two templates with the same name and different modes.

The mode attribute allows the same nodes to be processed more than once, using different modes.

Here is a short example:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="num[position() mod 3 = 1]">
  <tr>
    <xsl:apply-templates mode="copy" select=
     ". | following-sibling::*[not(position() >2)]"/>
  </tr>
 </xsl:template>

 <xsl:template match="*" mode="copy">
  <td><xsl:value-of select="."/></td>
 </xsl:template>

 <xsl:template match="num"/>
</xsl:stylesheet>

When this transformation is applied on the following XML document:

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

The result is that the numbers are displayed in three tr (rows), each containing three columns (with the possible exception of the last row):

<tr>
   <td>01</td>
   <td>02</td>
   <td>03</td>
</tr>
<tr>
   <td>04</td>
   <td>05</td>
   <td>06</td>
</tr>
<tr>
   <td>07</td>
   <td>08</td>
   <td>09</td>
</tr>
<tr>
   <td>10</td>
</tr>

In this transformation, any num element with position that cannot be represented in the form 3*k +1 (where k is an integer), is matched by a template with empty body and thus isn't processed.

However, we want to process all num elements that should form the cells of a row. For this purpuse, we are processing them using the xslt instruction:

<xsl:apply-templates mode="copy" select=
 ". | following-sibling::*[not(position() >2)]"/>

which means: "Do not apply to the selected nodes templates that would normally be applied (in no mode), but apply templates that are in copy mode"

Thus, we do not ignore the selected num elements, but are processing them in copy mode and are creating the td s of a row.

The template rule:

<xsl:template match="num"/>

is necessary to override the xslt builtin templates (default processing) that would otherwise cause the string values of the num nodes whose position cannot be represented as 3*k +1, to be output.

So, these nodes are processed by both templates:

<xsl:template match="num"/>

and

<xsl:apply-templates mode="copy" select=
 ". | following-sibling::*[not(position() >2)]"/>

and thus we get the wanted result.

It would be instructive to step through with a good XSLT debugger in order to see how these templates are applied.

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • So, to be clear about what you are saying, `mode` is like a filter as to which templates are available for use for processing nodes, rather than one of the alternatives for a specific template, which is what might be assumed from its name, and which type of usage would have benefited had `mode` been able to be dynamically defined. – Patanjali Feb 04 '20 at 02:15
  • @Patanjali, There are other, better ways for choosing processing dynamically. In XSLT 1.0 or 2.0 one may use the FXSL library for functional programming with XSLT (see http://fxsl.sf.net). In XPath 3 (XSLT 3.0) one can pass functions as parameters to other functions, that is a function item is a first class object, and higher-order functions are a standard feature of the language – Dimitre Novatchev Feb 04 '20 at 02:20
  • Unfortunately, I am confined to using XSLT 1.0 as it is all that PHP provides, and my target audience is predominately using cPanel and shared servers, so cannot add such extensions. However, PHP allows calling inbuilt and programmer-defined PHP functions from XSLT, and that probably provides a much richer environment than any extensions allow. There is always a way of getting the job done, and limitations just force us to be creative. – Patanjali Feb 04 '20 at 02:33
  • Dimitre, that you for clearing up my misconception about `mode`. – Patanjali Feb 04 '20 at 02:41
  • @Patanjali, FXSL is not an extension -- it is written in pure XSLT 1.0. There are separate versions -- for XSLT 1.0 and for XSLT 2.0. – Dimitre Novatchev Feb 04 '20 at 03:11
  • (@)Dimitre. BTW. The link is refused for me. One of my criteria is to minimise third-party inclusions as they introduce a vulnerability vector that my largely non-technical clients would have to individually keep up to date. I could include the library, but then I am tied to having to tie my update schedule, which I am trying to minimise, to include theirs. The exception is PHP of course, but it is effectively single source and, most importantly, host providers keep it up to date themselves, absolving users of the chore. – Patanjali Feb 04 '20 at 03:27
  • @Patanjali Yes, I see the logic in what you are doing. On the other hand a lot of good stuff is produced as Open Source -- even such great tools like Microsoft's Typescript. So, I believe one can easily miss a lot of good opportunities to use important components that make the development a lot easier. Certainly, this depends on the viewpoint, but the "truth" typically is somewhere between the extremes. The case with FXSL is that it makes possible to do a lot of things in XSLT that were considered almost "impossible". See https://dnovatchev.wordpress.com for examples :) – Dimitre Novatchev Feb 04 '20 at 14:36
  • @Patanjali, I checked the link -- it works with `http://fxsl.sf.net` or `http:fxsl.sourceforge.net` -- do note `http`, not `https`. I must move this page to my github account some day. I already have the FXSL code there -- at https://github.com/dnovatchev/FXSL-XSLT2 – Dimitre Novatchev Feb 04 '20 at 14:45
7
<xsl:apply-templates select="phone" />
<xsl:apply-templates select="phone" mode="accountNumber"/>
<xsl:template match="phone">
      <TD>A</TD>
</xsl:template>
<xsl:template match="phone" mode="accountNumber">
      <TD>B</TD>
</xsl:template>

Link a simple example here: https://msdn.microsoft.com/en-us/library/ms256045%28v=vs.110%29.aspx

Rob
  • 26,989
  • 16
  • 82
  • 98
Andrew
  • 784
  • 9
  • 15
  • 1
    This is an answer that is mostly copied and pasted information from the XSLT Pocket Guide. The OP asked for someone to explain it with examples... – Mark Townsend Oct 24 '16 at 11:00
  • 1
    The template as a function, the example here concisely demonstrate the OO like polymorphic function named as "phone". you can give different mode to call different phone. – Andrew Oct 25 '16 at 03:31
  • 1
    The problem with the example is that while it may demonstrate it, it requires the knowledge that questions like the OPs are seeking before being able to comprehend it. This is exactly why I found a lot of MS documentation unhelpful. However, because it doesn't discus how it uses `mode`, it shouldn't have been offered without explanation here. – Patanjali Feb 04 '20 at 03:42
6

The mode attribute allows multiple ways of processing the same XML elements.

A template must have a match attribute if wanting to use a mode attribute, so they are not meant for templates relying solely upon the name attribute for calling.

They apply to xsl:apply-templates to determine which xsl:templates will respond, so an apply using a mode will only invoke a template that uses the same mode. Templates with no mode will only respond to an apply without a mode.

For example, you may want to render an XML paragraph element as a HTML p element for viewing, but as a form for editing.

This can then be rendered for viewing by:

<xsl:template match="paragraph">
 <p>...</p>
</xsl:template>

which would match paragraph tags in an XML document when called through:

<xsl:apply-templates />

Conversely, to render for editing use:

<xsl:template match="paragraph" mode="edit">
 <form>...</form>
</xsl:template>

by calling through:

<xsl:apply-templates mode="edit" />

Note that in the example, if the rest of the page is to be rendered using the non-mode xsl:apply-templates, the xsl:template mode="edit" version would have to be explicitly invoked for the specific paragraph elements to be edited.

If you don't need to have a mode match for all XML elements, provide a null template, like:

<xsl:template match="*" mode="edit" />

to make sure that you don't get 'phantom' text from deep matches polluting the output.

As with any xsl catchall template, put it at the beginning of all xsl:templates for the same mode, as xsl only uses the last matching template, and putting it last would ensure nothing is ever seen!

Patanjali
  • 893
  • 13
  • 17