[xslt] The nature of xsltApplyOneTemplate() needs to be modified



Hi,

I noticed a problem with the semantics of xsltApplyOneTemplate() and
it's actual usage in Libxslt/Libexslt. This function is currently
used to handle 3 alternative scenarios, but fails to do so, since
it it is designed for only 1 scenario.

I'll try to explain the issue and will present a potential solution.

xsltApplyOneTemplate(xsltTransformContextPtr ctxt,
  xmlNodePtr node,
  xmlNodePtr list,
  xsltTemplatePtr templ,
  xsltStackElemPtr params);

1) The usage in exsltFuncFunctionFunction() (libexslt/function.c):

  Here the number of xsl:param instructions, which are set by the
  invoking function call are processed with
  xsltParseStylesheetCallerParam() and handed over to
  xsltApplyOneTemplate() via @params; remaining xsl:param(s) in
  @list are expected to be processed by xsltApplyOneTemplate().

  Example: the following function is called with "my:func('zoo')".

   <func:function name="my:func">
    <xsl:param name="foo"/>
    <xsl:param name="bar"/>
   </func:function>
  
   <xsl:param name="foo"/> is processed by exsltFuncFunctionFunction(),
   and the remaining <xsl:param name="bar"/> is expected to be processed
   by xsltApplyOneTemplate().

  @templ is not given, since there's no xsl:template.

  Side note: Using xsltParseStylesheetCallerParam(), which is intended
  for xsl:with-param, to process xsl:param is actually a hack,
  since there's no appropriate function to process xsl:param(s) in
Libxslt
  for this scenario.
  
2) The usage in Libxslt:

  a) It is called to process a template (or sequence constructor in
    XSLT 2.0). This means *no* xsl:param instructions are expected in
    @list, and @params and @templ are both NULL.

  b) It is called to process an xsl:template. This means xsl:param(s)
*are*
    expected in @list, and caller-params (xsl:with-param) are handed
over
    via @params; @templ is the compiled xsl:template struct.

The clashes are easier to spot in the following table:

    @params                 @list                          @templ

1)  reflects xsl:param(s)   can contain more xsl:param(s)  always NULL
2a) refl. xsl:with-param(s) can contain xsl:param(s)       refl.
xsl:template
2b) always NULL             must not contain xsl:param(s)  always NULL


Proposed solution:
  
1) Change xsltApplyOneTemplate():
  - *reject* xsl:param(s) in @list (raise an error if one is found)
  - @params are any xsl:param(s) already processed by the caller
  - @templ is *not* used (ATTRIBUTE_UNUSED)
  - do *not* initiate a new variable scope (it did so previously
    when @templ was given)

  So, if @params is NULL, xsltApplyOneTemplate() will actually become
  a function for processing of a normal template (in constrast to
  xsl:template); e.g. for the content of an xsl:for-each instruction.

  If @params is given, then those are pushed on the variable stack;
  This, for example, reflects the content model of an exslt:function,
  which is (xsl:param*, template) - *without* the possibility
  to override xsl:param(s) with xsl:with-param.

  Note that due to this change 4 calling functions (see below)
  need to be adjusted in Libxslt; all other calls are already OK for
  the modified nature of xsltApplyOneTemplate().
    
2) Add xsltApplyXSLTTemplate() for processing of xsl:template.
  This function will expect:
  - @templ
  - optional @withParams, reflecting xsl:with-param instructions;
    those will override xsl:param(s) in @list
  - xsl:param(s) in @list still to be processed

  This function will then be used if a xsl:template needs to be
  processed - namely in:
  - xsltApplyImports()
  - xsltCallTemplate()
  - xsltDefaultProcessOneNode()
  - xsltProcessOneNode()

3) Change exsltFuncFunctionFunction() in Libexslt to
  process *all* xsl:param(s) and to hand over *all* processed
  xsl:param(s) to xsltApplyOneTemplate().
  This is a fix, since the current way of calling
  xsltApplyOneTemplate() was simply incorrect.
  
I think this is the most trouble-free solution for users, as the
changes will only have impact on scenarios where an xsl:template
needs to be processed; normally xsl:template should only be
processed internally by Libxslt - not in user-code.

Immediate comments are appreciated. I already refactored
the code in the proposed way on my side and would like to commit
as soon as possible if accepted.

Regards,

Kasimier



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]