【问题标题】:Pass XML fragments as stylesheet paramters with lxml?使用 lxml 将 XML 片段作为样式表参数传递?
【发布时间】:2009-11-18 14:54:38
【问题描述】:

我开始在 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 实现这一目标?

【问题讨论】:

    标签: python xml xslt lxml


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢。您能否编辑您的帖子并使用自定义解析器更改指向该页面的链接?发帖后我注意到了自定义的xpath函数,得出了同样的结论,但是document()方法可能更有用。
    • 这个答案很特别,因为它是从@Steven 的点数很少他无法发布多个链接的时候开始的。他现在有大约 12k 点。漫长的道路。
    【解决方案2】:

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

    hmm,看来我将不得不在这段代码中放入 html 实体来表示 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()
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-02
        • 1970-01-01
        • 2021-12-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多