是否可以在 xslt 样式表的 xpath 谓词中使用 lxml 扩展函数?

Is it possible to use lxml extension functions in xpath predicates in xslt stylesheet?

扩展函数适用于 xpath 评估,但不适用于 xslt 转换。是完全不支持这种使用还是我错过了什么?

root = etree.XML('<a><b class="true">Haegar</b><b class="false">Baegar</b></a>')
doc = etree.ElementTree(root)

def match_class(context, arg):
    return 'class' in context.context_node.attrib and context.context_node.attrib['class'] == arg

ns = etree.FunctionNamespace('http://example.com/myother/functions')
ns.prefix = 'css'
ns['class'] = match_class

result = root.xpath("//*[css:class('true')]")
assert result[0].text == "Haegar"

xslt = etree.XSLT(etree.XML('''
   <stylesheet version="1.0"
          xmlns="http://www.w3.org/1999/XSL/Transform"
          xmlns:css="http://example.com/functions">
     <output method="text" encoding="ASCII"/>
     <template match="/">
        <apply-templates select="//*[css:class('true')]"/>
     </template>
   </stylesheet>
'''))

result = xslt(doc)
assert str(result) == "Haegar"

第一个断言通过。

但是对 xslt(doc) 的调用结果为 lxml.etree.XSLTApplyError: Failed to evaluate the 'select' expression.,或者 lxml.etree.XSLTApplyError: Error applying stylesheet 如果将 xpath 放入某个模板匹配中。

我认为你使用了错误的命名空间声明:

xmlns:es="http://example.com/functions"

您应该更改:

xmlns:css="http://example.com/myother/functions"

编辑

以下示例完美运行:

from lxml import etree

root = etree.XML(u'<a><b class="true">Haegar</b><b class="false">Baegar</b></a>')
doc = etree.ElementTree(root)


def match_class(context, arg):
    return 'class' in context.context_node.attrib and context.context_node.attrib['class'] == arg


ns = etree.FunctionNamespace('http://example.com/myother/functions')
ns.prefix = 'css'
ns['class'] = match_class

result = root.xpath("//*[css:class('true')]")
assert result[0].text == "Haegar"

xslt = etree.XSLT(etree.XML(u'''\
   <stylesheet version="1.0"
          xmlns="http://www.w3.org/1999/XSL/Transform"
          xmlns:css="http://example.com/myother/functions">
     <output method="text" encoding="ASCII"/>
     <template match="/">
        <apply-templates select="//*[css:class('true')]"/>
     </template>
   </stylesheet>
'''))

result = xslt(doc)
assert str(result) == "Haegar"

使用 Python 2.7 和 lxml == 3.8.0 测试