Re: [xslt] XSLT extension API



Le 16/05/01 09:50:42, Daniel Veillard a écrit :
> > The func:function element registers itself in an hash table whose keys
> > are the name and namespace URI of the function it defines. This is
> > where "module data" is needed.
> 
>   There is already something similar at the stylesheet level for
> extension prefix<->URI registration.

I may have been unclear.
Given this function declaration:
  <func:function name="my:if-then-else">
  <xsl:param name="if" />
  <xsl:param name="then" />
  <xsl:param name="else" />

    <xsl:choose>
    <xsl:when test="$if">
      <func:result select="$then"/>
    </xsl:when>
    <xsl:otherwise>
      <func:result select="$else"/>
    </xsl:otherwise>
    </xsl:choose>
  </func:function>
when it is processed, it registers itself (the func:function xmlElementPtr)
in a hash table with keys "if-then-else" and the namespace URI bound to the
prefix "my" (say "http://example.net/my").

A generic function is registered in the XPath context to catch calls to the
my:if-then-else function in an XPath expression.
This generic function retrieves the name ("if-then-else") and namespace URI
("http://example.net/my") from the XPath context (cf. the libxml list) and
use them to retrieve the corresponding func:function xmlElementPtr. Then it
can evaluate the content of this element, which stands for the function
body.

>   My take is that extension modules should be registered application
> wide in a global way. Then at evaluation startup, the list style->nsDefs
> is followed (and for all imported/included stylesheets too), then
> an initialization function gets called returning the specifically
> allocated data for this module (if any). At evaluation end a cleanup
> function is called in a similar way.

OK.

>   So there is 2 tables:
>   
>   one application wide which for each URI associates:
>     - void * xsltExtInitFunction(xsltTransformContextPtr ctxt,
>                                  const xmlChar *URI);
>     - void * xsltExtShutdownFunction(xsltTransformContextPtr ctxt,
>                                  const xmlChar *URI);
> 
>   one per transformation instance which for each URI associates:
>     - void *extData;
>     - a pointer to the application wide entry.

OK.

> > It also registers a generic function as the callback for the defined
> > function (calls xsltRegisterExtFunction with the name and namespace URI
> > of the defined function and the generic function).
> 
>   Okay, done in xsltExtInitFunction()

No, see above.
This is done when the func:function is evaluated and it's not a problem I
think (well, maybe it is, if someone uses a function before having declared
it with func:function, I didn't check how libxslt handles that -- it's
quite similar with variable declaration)

> > I didn't checked whether it's already possible but we also need a way
> > to stop evaluation of a template (without raising errors).
> > This is needed for the func:result element.

I re-read the func:result definition <http://exslt.org/func/elements/result/>
We actually don't need such a framework.

> > > An element may need (I don't know if it is really necessary) to do
> > > some computation at parsing (stylesheet compiling) time (as the XSLT
> > > decimal-format and key do for instance). The data structure is kept
> > > in an hash table in the stylesheet directly.
> > 
> > Above registrations should actually appear here. Checks of allowed /
> > forbidden attributes and attribute values should also be done when
> > compiling the stylesheet.

This may prevent problems exposed above for use of a function (e.g. in a
variable initialization) before it has been declared.

> What do you need there  ?

I don't know if it's really needed but I think there should be something
like what's done for variables, attribute sets, decimal formats, etc.
A function called while compiling the stylesheet and another when
processing it.
While compiling the stylesheet, the callback function for an element should
check for "validity" errors (top-level/instruction, attributes, children,
parent, etc.). For example, an xsl:choose element should complain if it has
children others than xsl:when and xsl:otherwise, xsl:when and xsl:otherwise
should complain if its parent isn't xsl:choose, xsl:otherwise should also
complain if it has following-siblings and all of them should complain if
they have unknown attributes with a null namespace URI or if they don't
have the required attributes (the test attribute of xsl:when).

Have a look to <http://users.iclway.co.uk/mhkay/saxon/saxon6.3/extensibility.html#Writing-extension-elements>
:
prepareAttributes()
    This is called while the stylesheet tree is still being built, so it
    should not attempt to navigate the tree. Its task is to validate the
    attributes of the stylesheet element and perform any preprocessing
    necessary. For example, if the attribute is an attribute value
    template, this includes creating an Expression that can subsequently
    be evaluated to get the AVT's value.
validate()
    This is called once the tree has been built, and its task is to check
    that the stylesheet element appears in the right context within the
    tree, e.g. that it is within a template
process()
    This is called to process a particular node in the source document,
    which can be accessed by reference to the Context supplied as a
    parameter.
isInstruction()
    This should return true, to ensure that the element is allowed to
    appear within a template body.

> >     <xsl:when test="root > 1">OK</xsl:when>
> What I really noticed was the WF error in the attribute :-)

There isn't, only < and & are forbidden in attribute values ;o)

Tom.





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