2009-11-18 102 views
0

我開始在Python中使用lxml來處理XML/XSL文檔,並且通常它看起來非常簡單。但是,我無法在翻譯時找到將XML片段作爲樣式表參數傳遞的方法。將XML片段作爲樣式表參數傳遞給lxml?

例如,在PHP也能夠通過DOMDocument XML片段作爲樣式表的參數,使得一個可以具有在樣式表中可用的複雜PARAMS:

$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完成此操作?

回答

1

據我所知,您只能在lxml中使用xpath表達式(或帶有引號的字符串的etree.XSLT.strparam()方法的結果)(現在無論如何)。

但是,因爲您可以使用xpath表達式,這意味着您可以通過使用返回元素的custom xpath extension function「解決方法」。另一種方法可以是使用標準的xpath文檔()函數,並使用custom resolver

+0

謝謝。你可以編輯你的文章,並使用自定義解析器更改鏈接到頁面?我在發佈後注意到了自定義xpath函數,並得出了相同的結論,但'document()'方法可能更有用。 – 2009-11-19 08:05:29

+0

這個答案很特別,因爲從@Steven有這麼幾點他不能發佈多個鏈接的時候開始。他現在有大約12k點。長路。 – mlissner 2015-04-05 05:44:35

+0

@mlissner:感謝提醒我;-),我修復了這些鏈接。 – Steven 2015-04-14 14:37:25

0

您可以使用python擴展函數將etree.XML文檔返回給xslt。這是最基本的例子。它註冊一個全局名稱空間(uri:params),在該名稱空間中將函數與「params」方法關聯起來。樣式表使用這個來實現擴展功能。不要忘記樣式表中的xmlns:ptest聲明。

嗯,看起來像我將不得不在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()