【问题标题】:passing evaluated xpath to extension将评估的 xpath 传递给扩展
【发布时间】:2013-04-29 13:42:40
【问题描述】:

我正在使用 lxml python 库。

假设我们有产品 xml,例如:

<product id='123' />

又想申请xsl模板:

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

ssi:include 是一个简单的 lxml 扩展,它将 nginx ssi 指令作为 cmets 插入 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'))

【问题讨论】:

    标签: python xslt xpath lxml


    【解决方案1】:

    试试 xsl:attribute

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

    【讨论】:

    • 是的,谢谢。因此解决方案有效,但没有我需要实施的那么整洁。在这种情况下,我们根本不需要扩展,编写自定义 xsl:comment
    【解决方案2】:

    我处于同样的情况,据我所知,我可以走两条路:

    • 使用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() 似乎都不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      相关资源
      最近更新 更多