5

假设我有一个使用lxml(with libxmland libxslt) 从 XSL 转换调用的 XPath 函数,例如:

<xsl:template match="/">
  <xsl:variable name="result" select="myns:my-func(./*)" />
  ...
</xsl:template>

从这个函数中,我想返回一个 XML 片段,它包含以下内容:

some sample <em>text</em>

python 函数my_func已正确设置lxml为可通过 XSL 样式表使用,并用于lxml.html.fragments_fromstring获取以下格式的结果:

['some sample ', <Element em at 0x106c203b0>]

如何返回此列表,以便稍后在变量的 XSL 转换中使用它,就好像它是直接在 XSL 上下文中从 XPath 表达式中收集的一样?似乎每当我将字符串列表传递回 XSL 处理器时都会lxml引发异常。

4

1 回答 1

3

首先是定义你的功能。它需要将节点集作为项目列表返回。这些项目可能包括元素(也包括注释和处理指令)、字符串和元组。

硬编码示例可能如下所示:

from lxml import etree

def myFunc(context, parm):
  em = etree.Element('em')
  em.text = 'text'
  return ['some sample ', em]

请注意,在这种情况下, parm参数不是必需的,但我将其包含在此处以匹配您在调用中传递参数的示例代码myns:my-func

如果你想使用Fragments_fromstring来构建你的节点集,而不是手动构建它,函数定义会变得更加简单。

def myFunc(context, parm):           
  import lxml.html
  return lxml.html.fragments_fromstring('some sample <em>text</em>')

接下来,您需要设置命名空间并注册函数名称。

myns = etree.FunctionNamespace('http://example.org/myNamespace')
myns['my-func'] = myFunc

最后,您可以像这样在 XSLT 样式表中使用它:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:myns="http://example.org/myNamespace">
  <xsl:template match="/">                                   
    <xsl:variable name="result" select="myns:my-func(./*)" />
    <xsl:for-each select="$result">
      <xsl:copy-of select="." />
    </xsl:for-each>         
  </xsl:template>
</xsl:stylesheet>

请注意,样式表中使用的命名空间 URL 必须与在FunctionNamespace中注册的 URL 匹配。

现在假设您已将此样式表加载到名为xslt的字符串中,示例转换可能如下所示:

root = etree.XML('<root></root>')
doc = etree.ElementTree(root)
transform = etree.XSLT(etree.XML(xslt))
res = transform(doc)

有关完整的工作示例,请参阅此pastebin 链接

于 2013-07-23T16:06:15.023 回答