Re: [xsl] Selectively applying Identity transform to multiple inputs (Multiplexer Style Sheet)

Subject: Re: [xsl] Selectively applying Identity transform to multiple inputs (Multiplexer Style Sheet)
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Fri, 05 Jan 2007 22:20:21 +0100
Hi Farrukh,

There is no such thing as "null" for a parameter, unless you mean the string "null". There is a notion of empty, which is slightly different than an empty string. However, if I read you closely, you probably mean the latter: test for an empty string. Depending on your XSLT version, this can be done in several ways.

Since you talk of "identity transform", I am under the impression that, besides copying, you want to change several nodes before they are being output. It depends a bit whether the different sources are in the same namespace or not, but I usually find it easiest to work with modes in that case. Perhaps the following can be helpful:

<!-- without modes, in XSLT 2, just a copy -->
<xsl:template match="/">
<xsl:copy-of select="if($input2 != '') then document($input2)/* else ." />
</xsl:template>


<!-- without modes, in XSLT 1 just a copy -->
<xsl:template match="/">
   <xsl:choose>
      <xsl:when test="$input2 != '' ">
          <xsl:copy-of select="document($input2)/*" />
      </xsl:when>
      <xsl:otherwise>
         <xsl:copy-of select="." />
      </xsl:otherwise>
   </xsl:choose>
</xsl:template>

<!-- with modes, in XSLT 1 using the identity transform idiom -->
<xsl:template match="/">
<xsl:choose>
<xsl:when test="$input2 != '' ">
<xsl:apply-templates select="document($input2)/*" mode="external" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="internal" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>


<!-- XSLT 1: internal document handling -->
<xsl:template match="node() | @*" mode="internal">
   <xsl:apply-templates select="node() | @*" mode="internal" />
</xsl:template>

<!-- XSLT 1: external (from $input2) document handling -->
<xsl:template match="node() | @*" mode="external">
   <xsl:apply-templates select="node() | @*" mode="external" />
</xsl:template>

<!-- with modes, in XSLT 2 using the identity transform idiom -->
<xsl:template match="/">
<xsl:apply-templates select="if($input2 != '') then document($input2)/* else ()" mode="external" />
<xsl:apply-templates select="if($input2 = '') then . else () mode="internal" />
</xsl:template>



<xsl:template match="node() | @*" mode="internal external"> <xsl:apply-templates select="node() | @*" mode="#current" /> </xsl:template>



<!--
   both XSLT 1 and 2: use normal templates for overriding.
   in XSLT 1: use one template per mode
   in XSLT 2: if overlap, you can use both modes in one template, or #all
-->

As you can see, XSLT 2 is slightly less verbose than XSLT 1. Of course, I have no idea if you need to distinguish during the transformation process between the two kinds of input, but well, when you do, this is one way to do it. Doing without the modes, you can just leave them out.

Note that modes are not necessary if you want to distinguish between the two kinds of input, but the structure and/or namespace is different.

Cheers,
-- Abel Braaksma
  http://www.nuntia.nl

Farrukh S. Najmi wrote:
Dear colleagues,

I have a newbie question.

In my XSLT, in addition to my main input, I am reading a second input in
my XSLT using the document() function.
The second input's URL is specified via an <xsl:param>:

<xsl:param name="input2" select="''"></xsl:param>

I need to produce output tree that is either the identity transform of
the main input or the second input depending upon whether the parameter
$input2 is null/empty or not. If it is null/empty then the main input
should be copied to output tree. If it is not null/empty then the second
input should be copied to output tree.

I have been unable to do this correctly after much trying.

Can someone provide some guidance on how to accomplish this seemingly
simple task?

Thanks for your help.

Current Thread