[lxml-dev] XSLT extensions!
Stefan Behnel
behnel_ml at gkec.informatik.tu-darmstadt.de
Sat Nov 12 15:02:54 CET 2005
First of all: I start hating libxml2/libxslt. It's increadibly badly
documented and the only way to implement something with it is to read the
documentation, try hard to figure out what it may well mean (and which
functions may get you where you want when applied in which order) and then
still go for trial-and-error. Great.
That said...
Stefan Behnel wrote:
> What about introducing a Namespace class at the module level that you can
> instantiate with a namespace URI as argument and then register different types
> of 'things' with it?
[...]
> -----------
> ns1 = etree.Namespace('http://mynamespace/somewhere')
> ns1.update(my_dict_with_subclasses_of_ElementBase)
> ns1['some_element'] = MyAdditionalElementImpl
> ...
>
> ns2 = etree.Namespace('my:extensions:to:xslt')
> ns2['func1'] = some_function
> ...
> -----------
I've created a new branch scoder2 (from scoder1) and taken this approach.
"Namespace" became a module level function that returns a dictionary-like
object, a _NamespaceRegistry. That object internally splits its values up by
inheritance/callable checking, so there currently is an internal dictionary
for subclasses of ElementBase (i.e. XML elements), for callables (i.e.
extension functions) and for superclasses of XSLTElement, i.e. XSLT element
extensions, but the latter are currently not implemented/used. Fits perfectly
into the interface, though.
The update() method is forgiving, i.e. if things don't match the requirements,
they are thrown away. This allows you to write implementation classes/modules
and then run
Namespace('http://something/else').update(vars(myclass()))
to register the methods of that object or module (names starting with '_' are
entirely ignored). I didn't test that yet, but it's intended. Kasimier (and
possibly others) may hate me for this, but I think it's a nice feature.
For compatibility, the XSLT and XPath classes still have the "extensions"
keyword argument, but these are mixed with the globally registered ones (they
take precedence, though). I'd personally argue for removing them since I
largely prefer the new interface, but that would break backward compatibility
(in case someone actually uses the old interface). Note that this is the only
reason why I left them in. They are not needed IMHO and make things a bit more
ugly. (I mean, really, why would you want to register extension functions for
each call? What are namespaces for, hu?)
Another problem is that XSLT doesn't currently check which namespaces are
actually used in the stylesheet, it just registers all extension functions it
finds. It *could* try to deduce the right namespace URIs from the
ElemenTree/Document it works on, but that's not currently implemented.
The current implementation is already ugly enough (although not toooooo bad)
and the accompanying refactoring of the existing code was again rather
extensive (the patch has some 900 lines against scoder1 - don't want to count
the trunk). I may have to rework some things, but I'll still check it in for
now, so that others can try it and comment on it. I will also start to use it
in MathDOM, so we will see how it works out.
Stefan
More information about the lxml-dev
mailing list