我正在使用lxml python lib。
假设我们有产品xml,例如:
<product id='123' />
想要应用xsl模板:
<xsl:template match="product">
<ssi:include virtual="/ssi/reviews/{@id}"/>
</xsl:template>
ssi:include是一个简单的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'))
答案 0 :(得分: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>
答案 1 :(得分: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()
似乎无效。