2013-04-29 68 views
1

我正在使用lxml python lib。將評估後的xpath傳遞給擴展

假設我們有產品XML如:

<product id='123' /> 

而且要應用XSL模板:

<xsl:template match="product"> 
    <ssi:include virtual="/ssi/reviews/{@id}"/> 
</xsl:template> 

SSI:包括是一個簡單的lxml的擴展,插入nginx的SSI指令在HTML註釋碼。問題是評估@id並將屬性傳遞爲virtual =「/ ssi/include/123」。有沒有辦法? 我已經找到了解決辦法,並用它現在:

import lxml.etree 
import re 
from copy import deepcopy 

ns = '{ssi}' 

# ssi extensions 
class SsiExtElement(lxml.etree.XSLTExtension): 
    def execute(self, context, self_node, input_node, output_parent): 
     _, tag = self_node.tag.split('}') 
     tmp = lxml.etree.Element('tmp') 
     for k, v in self_node.attrib.items(): 
      if re.search('\{(.*)\}', v): #here we search {xpath} values to evaluate 
       elem = deepcopy(input_node) 
       matches = re.findall('\{(.*)\}', v) 
       for match in matches: 
        v = v.replace('{%s}' % match, elem.xpath(match)[0]) 
      tmp.set(k, v) 
     self.process_children(context, output_parent=tmp) 
     attrs = ' '.join(u'%s="%s"' % (k, v) for k, v in tmp.attrib.items()) 
     ssi = lxml.etree.Comment(u'#%s %s' % (tag, attrs)) 
     output_parent.append(ssi) 
     for node in tmp: 
     output_parent.append(node) 
     if (self_node.tag.replace(ns,'') in ('if', 'else', 'elif') 
      and self_node.getnext().tag.replace(ns, '') not in ('else', 'elif')): 
     output_parent.append(lxml.etree.Comment(u'#endif')) 

回答

1

嘗試以xsl:屬性

<xsl:template match="product"> 
    <ssi:include> 
     <xsl:attribute name="virtual"> 
      <xsl:value-of select="concat('/ssi/reviews/',@id)"/> 
     <xsl:attibute> 
    </ssi:include> 
</xsl:template> 
+0

是的,thanx。因此解決方案有效,但並不像我需要實施的那麼簡潔。在這種情況下,我們不需要擴展,編寫自定義xsl:comment – 2013-04-29 14:10:05

0

我在同樣的情況,並從我所看到的,我可以遵循兩條路徑是:

  • 使用context.context_node:這是一個普通的etree.Element並具有xpath()。從邏輯上講,它與input_node相同。這樣您可以評估源文檔中的任何XPath。
  • 通過子元素傳遞參數並使用process_children()來評估它們。

例子:

<ssi:include> 
    <virtual value="/ssi/reviews/{@id}" /> 
</ssi:include> 

第二個方法可以讓您在評估XSLT變量爲好,即在我的情況:

<path:make-directory> 
    <target value="{$target}" /> 
</path:make-directory> 

所有其他地區,尤其是apply_templates()似乎並不上班。