Re: Namespace API for extension functions (was: Doctest for Namespace class)
Stefan Behnel <behnel_ml <at> gkec.informatik.tu-darmstadt.de>
2006-01-20 13:05:55 GMT
Responding to myself to continue this discussion from last year...
Stefan Behnel wrote:
> Martijn Faassen wrote:
>> Yes, I'd like to keep support for XPath as per spec. We could consider
>> an alternative API that supports this pattern too, though, as long as
>> it's clear that this is not (exactly) XPath. Perhaps we can introduce a
>> little helper function called 'clarke()' or something, that transforms
>> clark notation into an xpath expression + namespace dictionary.
>>
>> I don't really like globally defined prefixes, but when namespace
>> classes are used it isn't that bad. I guess functions would be in their
>> own namespace typically, so it might be we want to define a special
>> namespace class just for this purpose?
>
> Or a subclass of XPath, like ClarkXPath, that accepts Clark's notation. A
> helper function would then do the trick internally.
I think that's a good solution. If people want to use Clark's notation in
XPath expressions, they can use a subclass of the XPath class. This also
reduces the performance penalty of having to parse the XPath expression for
namespaces: it's only done at XPath object creation time.
> What you're proposing would be something like 'FunctionNamespace'. Nothing
> wrong with that. Actually, it's even (more or less) handled that way
> internally. Don't know if it's worth a separate API, though. Also, note that
> sometimes functions do not have a separate namespace, look at XSLT, for example.
I started writing a module function called 'ExtensionNamespace' that can be
used for extensions. It has a prefix associated with it, so that you can do
what I proposed before:
.>>> ns = ExtensionNamespace('myns')
.>>> ns.prefix = 'f'
.>>> ns['func'] = my_function
.>>> element.xpath('f:func(//honk)')
or call an XSLT that uses this function like in
...
<xsl:value-of select="f:func(.)"/>
...
It becomes somewhat problematic, however, when different namespaces become
associated with the same prefix, like this:
.>>> ns1 = ExtensionNamespace('myns1')
.>>> ns1.prefix = 'f'
.>>> ns2 = ExtensionNamespace('myns2')
.>>> ns2.prefix = 'f'
I don't like putting this in the hands of the user. We could use a dictionary
internally, but that would still be a global one, so if some module happens to
register a prefix that is already used by a different module - bad luck. And I
guess this is much more likely to happen with prefixes than with namespaces.
So, I don't know. Maybe the best solution is still to simply register all
namespace functions internally on each XPath/XSLT evaluation. It is rather
unlikely that use cases will deploy more than, say, 20 extension functions and
those could be registered pretty quickly, without a big performance hit.
Another point of discussion: Should the current support for extension
functions be dropped? This would obviously break current code, but it would
make both the internal implementation and the API cleaner by removing the
'extensions' argument from the respective method calls and by removing the
need for merging dictionaries of functions. I'm especially looking at lxml
V1.0, which should have a clean and stable API.
Any comments?
Stefan