Re: [xslt] extension modules



Le 22/07/01 18:16:28, Thomas Broyer a écrit :
> Le 22/07/01 16:54:36, Daniel Veillard a écrit :
> > > Here's a list of some of the changes:
> > >   · added function lookup framework to libxml/XPath and used it in
> > >     libxslt and modified the extension element lookup in the same way
> > >     (look for the element in the context, then in the global
> registry)
> > 
> >   Not sure I understand this one. can you give me the names of the
> > functions ?
> 
>  /*
>   * Function Lookup forwarding
>   */
> typedef xmlXPathFunction
>        (*xmlXPathFuncLookupFunc)       (void *ctxt,
>                                         const xmlChar *name,
>                                         const xmlChar *ns_uri);
>  
> void   xmlXPathRegisterFuncLookup      (xmlXPathContextPtr ctxt,
>                                         xmlXPathFuncLookupFunc f,
>                                         void *funcCtxt);
> 
> libxslt registers its own lookup function to also look for extension
> module
> functions in the global hash table.
> 
> >   Everything else sounds fine. 
> 
> Great ;o)
> 
> > > What's still needed:
> > >   · correct handling of extension-element-prefixes and
> > >     exclude-result-prefixes. extension-element-prefixes may need
> > >     binding data to the _private field of *every* element node (even
> > >     literal result elements)
> > 
> >    Hum, that part is complex. Tell exactly what you need and I will
> > check.
> > I took great care of not destroying performances to handle those and
> this
> > requires a lot of attention to get right.
> >    In general if you start adding data or processing for each node at
> > run time then thwin twice and ask first :-)
> 
> Well, I'm not sure what's really needed...
> Maybe extension-element-prefixes can be handled the same way
> exclude-result-prefixes are handled, since we'll precompute extension
> elements.
> I'll look at it in details...

According to http://lists.w3.org/Archives/Public/xsl-editors/1999JulSep/0091.html,
extension-element-prefixes isn't needed by element-available, and this was
the only place where precomputation wouldn't have been possible.

Extension element prefixes can be handled _totally_ at preprocessing, in a
way similar to how exclude-result-prefixes are handled.

This leads me to wonder where the data needed during precomputation of
these attributes (and maybe other things) should be stored.
Currently, exclude-result-prefixes precomputation uses xsltStylesheet, but
the data is only needed for precomputation and (seems) no longer used
afterwards.
Using a "precomp context" would be a solution but requires some more memory
allocation/freeing...

> Actually, I was thinking of making a stripped down version of
> xsltStylePreComp and adding 2 types: extension element and literal result
> element. Extension elements could then extend this struct with their own
> precomputed data, and -- most important -- associate a callback function
> to process the node.
> There are 3 things that can justify that:
>  · if extension-element-prefixes, and maybe exclude-result-prefixes,
>    handling needs some data bindings at node level
>  · extension elements have a way of adding precomputed data:
>    the stylesheet is a bit more homogeneous, and -- most important --
>    the struct can carry a free() function. This way, the _private
>    field can be used without memory leak or hackish "registration" of
>    computed data to be freed by the module's shutdown function (something
>    similar to the preComps field of xsltStylesheet, that any module
>    implementor would have to mimic) If I'm not clear enough, I can
>    provide a better, longer explaination ;o)
>  · the callback function for extension elements can be attached to the
>    node instead of being looked up for each transformation
> 
> If the first point isn't needed, literal result elements do not need
> precomputed data.
> 
> Processing of an element would then consist only in calling
> _private->func (or check whether its a literal result element --
> _private is NULL -- and then copy the node or call _private->func ; if
> the first point above is not needed)
> 
> This may improve performances of transformations (more things are
> computed during preprocessing)
> 
> Also, extension elements now consist only in a precomp function, and its
> up to this function to set the {precomp}->func => no need to look up the
> transform function in a hash table any more => better performances (maybe
> its peanut, I don't know...)
> 
> Just an idea...

The "first point" is not needed, so what should I do? Are we going for the
"extension element precomputed data framework"?

Here's an API proposal:
xsltPreComputeFunction returns an xsltStylePreCompPtr. If it returns NULL,
the processor puts xsltExtMarker in node->_private, otherwise it puts the
returned value.

  /* stripped down version, the "complete" one would be renamed */
  typedef xsltStylePreComp *xsltStylePreCompPtr;
  ...
  typedef void (*xsltStylePreCompFreeFunction) (xsltStylePreCompPtr comp);

  /* allocate and initialize */
  void xsltNewStylePreComp (xsltStylesheetPtr style, xsltStyleType type,
                            xmlNodePtr inst,
                            xsltTransformFunction function);
  /* initialize only, for "extended data struct" */
  void xsltInitStylePreComp (xsltStylePreCompPtr comp, ...same args...,
                             xsltStylePreCompFreeFunction freeFunc);

As an example, the func:result element would do something like this:
typedef struct {
  xsltStylePreComp comp; /* cast to StylePreComp possible */
  xmlXPathCompExprPtr select;
} exsltFuncResultPreComp, *exsltFuncResultPreCompPtr;
/* commes a free function */

xsltStylePreCompPtr
exsltFuncResultElemComp (... style, ... inst) {
  exsltFuncResultPreCompPtr ret;
  xmlChar *select;
  ...
  ret = /* malloc & memset + error handling */
  xsltInitStylePreComp (ret, style, XSLT_EXTENSION_ELEM, inst,
                        exsltFuncResultElem, exsltFreeFuncResultPreComp);
  ...
  /* parse the select attribute */
  select = xmlGetPropNs (inst, (const xmlChar *) "select", NULL);
  ret->select = xmlXPathCompile (select);
  ...
  return ((xsltStylePreCompPtr) ret);
}

void
exsltFuncResultElem (...ctxt, ...node, ...inst, ...comp) {
  ...
  if ((comp == NULL) || (comp == xsltExtMarker)) {
    /* ERROR: not initialized */
    return;
  }
  ...
  /* retrieve the compiled expression */
  select = ((exsltFuncResultPreCompPtr) comp)->select;
  ...
}

Tom.




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