使用lxml将XML片段作为样式表参数传递?

时间:2009-11-18 14:54:39

标签: python xml xslt lxml

我开始在Python中使用lxml来处理XML / XSL文档,而且一般来说它看起来非常简单。但是,在进行翻译时,我无法找到将XML片段作为样式表参数传递的方法。

例如,在PHP中,可以将DOMDocument XML片段作为样式表参数传递,以便在样式表中可以使用复杂的参数:

$xml = new DOMDocument();
$xml->loadXML('<root><node/></root>');

$xsl = new DOMDocument();
$xsl->loadXML('<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="html" omit-xml-declaration="yes" 
    indent="yes" media-type="text/html" />
<xsl:param name="a" />

<xsl:template match="/">
<html>
  <body>
    <xsl:value-of select="$a/foo/bar/text()" />
  </body>
</html>
</xsl:template>

</xsl:stylesheet>');

$fragment = new DOMDocument();
$fragment->loadXML('<foo><bar>baz</bar></foo>');

$proc = new XSLTProcessor;
$proc->registerPHPFunctions();
$proc->importStyleSheet($xsl);

$param_ns = '';
$param_name = 'a';
$proc->setParameter($param_ns, $param_name, $fragment->documentElement);

这将导致:

<html>
  <body>
  baz
  </body>
</html>

如何使用lxml完成此操作?

3 个答案:

答案 0 :(得分:1)

据我所知,你只能在lxml中使用xpath表达式(或带引号的字符串的etree.XSLT.strparam()方法的结果)(目前无论如何)。

但是,因为您可以使用xpath表达式,这意味着您可以使用返回相关元素的custom xpath extension function来“解决”。另一种方法是使用标准的xpath document()函数,并使用custom resolver

答案 1 :(得分:0)

我相信您所寻找的内容可以使用lxml.etree.XSLT来执行。可以在记录XSLT section的页面上的XPath and XSLT with lxml找到好的示例。

答案 2 :(得分:0)

您可以使用python扩展函数将etree.XML文档返回给xslt。这是最基本的例子。它注册一个全局命名空间(uri:params),将一个函数与该命名空间中的“params”方法相关联。样式表使用它来达到扩展功能。不要忘记样式表中的xmlns:ptest声明。

嗯,看起来我将不得不放入html实体来表示&lt;此代码中的符号。我也把它放在http://bkc.pastebin.com/f67461ccc


from lxml import etree

stylesheet = etree.XML("""
    <xsl:stylesheet version="1.0"
         xmlns:ptest="uri:params"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:variable name="params" select="ptest:params()" />
         <xsl:template match="/">
             <name_is><xsl:value-of select="$params/name" /></name_is>
         </xsl:template>
     </xsl:stylesheet>
""")

def params(context):
    # this is the extension function, it returns
    # a etree.XML document
    return etree.XML(
        """<params>
                <name>fred
        </params>"""
        )


def test():
    """test passing document to xslt via python extension function

    >>> test()
    <?xml version="1.0"?>
    <name_is xmlns:ptest="uri:params">fred
    <BLANKLINE>
    """    
    ns = etree.FunctionNamespace('uri:params') # register global namespace
    ns['params'] = params # define function in new global namespace
    transform = etree.XSLT(stylesheet)
    print str(transform(etree.XML("""<source />""")))

if __name__ == "__main__":
    import doctest
    doctest.testmod()