xsl:call-template Recommendation

I think it would be useful if you could call a named template and give it an XPath expression.  In my example I have an element Address which contains children that I wish to use the SearchElement template on.  SearchElement is a named template that works only on the current node (.) and expects it to contain PCDATA.  Since I wish to search the Name, PostalAddress/Street, etc... children of Address I must use a default template (<xsl:template match="*">) so that I don't have to replicate my xsl:with-param everywhere (I sent another email about this, subject line "xsl:number Recommendation").  It would be useful if users could call a named template as <xsl:call-template name="SearchElement" select="PostalAddress/City"/>.  Here's my example:

<!--
    template for how to present Address
 -->
<xsl:template match="Address">
   <p>
   <xsl:apply-templates select="Name"/>
   </p>
   <xsl:for-each select="PostalAddress/Street">
      <p>
      <xsl:apply-templates select="."/>
      </p>
   </xsl:for-each>
   <p>
   <xsl:apply-templates select="PostalAddress/City"/>
   <xsl:text>, </xsl:text>
   <xsl:apply-templates select="PostalAddress/State"/>
   <xsl:text> </xsl:text>
   <xsl:apply-templates select="PostalAddress/PostalCode"/>
   </p>
</xsl:template>

<!--
    template for how to present any element that we
    allow searches on... Number, Quantity, Description, Date
 -->
<xsl:template match="*">
   <xsl:call-template name="SearchElement">
      <xsl:with-param name="AnchorNumber">
         <xsl:number level="any" count="*" grouping-separator=" " grouping-size="10000"/>
      </xsl:with-param>
   </xsl:call-template>
</xsl:template>



<!--
    template for how to present any element that we
    allow searches on... Number, Quantity, Description, Date
 -->
<xsl:template name="SearchElement">
   <xsl:variable name="LowerDot">
      <xsl:value-of select="translate(.
                                    , 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                                    , 'abcdefghijklmnopqrstuvwxyz')"/>
   </xsl:variable>

   <xsl:choose>
   <xsl:when test="contains($LowerDot
                          , $SearchText) ='true'
                   and $SearchText != ''
                   and $LowerDot != ''">
      <xsl:variable name="StartPosition">
         <xsl:value-of select="string-length(substring-before($LowerDot
                                                      , $SearchText)) + 1"/>
      </xsl:variable>

      <xsl:variable name="AfterLen">
         <xsl:value-of select="string-length(substring-after($LowerDot
                                                     , $SearchText))"/>
      </xsl:variable>

      <xsl:value-of select="substring(., 0, $StartPosition)"/>
      <A name="M{$AnchorNumber}">
      <B style="color:#000000;background-color:#ffff66">
      <xsl:value-of select="substring(., $StartPosition
                                    , string-length($SearchText))"/>
      </B>
      </A>
      <xsl:value-of select="substring(.
                                    , $StartPosition + string-length($SearchText)
                                    , $AfterLen)"/>
   </xsl:when>
   <xsl:otherwise>
      <xsl:value-of select="."/>
   </xsl:otherwise>
   </xsl:choose>

</xsl:template>

Of course, I read that "Unlike xsl:apply-templates, xsl:call-template does not change the current node or the current node list." in http://www.w3.org/TR/1999/REC-xslt-19991116 so I'm not sure if you really want to allow this.  It is a bit like allowing <xsl:apply-templates name="SearchElement" select="PostalAddress/City"/>.  It certainly could be a subject for debate.  I guess if xsl:apply-templates causes you to move around the node tree then xsl:call-template must always apply to the current node or possibly children of the current node, is this not so?

I hope this idea is useful even if it is not in keeping with the philosophy of how xsl:call-template is used.

- Mike

Received on Sunday, 25 June 2000 21:46:49 UTC