【问题标题】:How to use python functions and variables inside XSLT?如何在 XSLT 中使用 python 函数和变量?
【发布时间】:2015-08-06 16:54:51
【问题描述】:

在 PHP 中,您可以使用 registerPHPFunctions 在 XSLT 文件中使用 PHP 函数,如下所示:

 <?php
$xml = <<<EOB
<allusers>
 <user>
  <uid>bob</uid>
  <id>1</id>
 </user>
 <user>
  <uid>joe</uid>
  <id>2</id>
 </user>
</allusers>
EOB;

$xsl = <<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:php="http://php.net/xsl">
<xsl:output method="html" encoding="utf-8" indent="yes"/>
 <xsl:template match="allusers">
  <html><body>
    <h2>Users</h2>
    <table>
    <xsl:for-each select="user">
      <tr><td>
        <xsl:value-of
             select="php:function('ucfirst',concat(string(uid), string(id)))"/>
      </td></tr>
    </xsl:for-each>
    </table>
  </body></html>
 </xsl:template>
</xsl:stylesheet>
EOB;
$xmldoc = DOMDocument::loadXML($xml);
$xsldoc = DOMDocument::loadXML($xsl);

$proc = new XSLTProcessor();
$proc->registerPHPFunctions('ucfirst');
$proc->importStyleSheet($xsldoc);
echo $proc->transformToXML($xmldoc);
?> 

什么是 Python 等价物?这是我尝试过的

from lxml import etree 

xml = etree.XML('''
<allusers>
 <user>
  <uid>bob</uid>
  <id>1</id>
 </user>
 <user>
  <uid>joe</uid>
  <id>2</id>
 </user>
</allusers>''')

xsl = etree.XML('''
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:f="mynamespace"
     extension-element-prefixes="f">

<xsl:output method="html" encoding="utf-8" indent="yes"/>
 <xsl:template match="allusers">
  <html><body>
    <h2>Users</h2>
    <table>
    <xsl:for-each select="user">
      <tr><td>
        <f:ucfirst>
        <xsl:value-of select="concat(string(uid), string(id))"/>
        </f:ucfirst>
      </td></tr>
    </xsl:for-each>
    </table>
  </body></html>
 </xsl:template>
</xsl:stylesheet>
''')
extension = Ucase()
extensions = { ('mynamespace', 'ucfirst') : extension }
proc = etree.XSLT(xsl, extensions=extensions)
str(proc(xml))

class Ucase(etree.XSLTExtension):
  def execute(self, context, self_node, input_node, output_parent):
    title = self_node[0].text.capitalize()
    output_parent.text(title)

这是我的 XSLT 的简化版本。

【问题讨论】:

  • 您的 PHP 示例实现了扩展功能,但您的 Python 示例似乎尝试添加扩展元素。这就是你打算在 Python 中做的,实现一个扩展元素吗?
  • 不,我只想在 XSLT 文件中使用自定义函数。只要能完成工作,任何一种方法都可以。

标签: python xml xslt lxml


【解决方案1】:

以下是扩展函数(不是元素)如何给出我认为你想要的结果:

from lxml import etree

def ucfirst(context, s):
    return s.capitalize()

ns = etree.FunctionNamespace("mynamespace")
ns['ucfirst'] = ucfirst

xml = etree.XML('''
<allusers>
 <user>
  <uid>bob</uid>
  <id>1</id>
 </user>
 <user>
  <uid>joe</uid>
  <id>2</id>
 </user>
</allusers>''')

xsl = etree.XML('''\
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:f="mynamespace" exclude-result-prefixes="f">
<xsl:output method="html" encoding="utf-8" indent="yes"/>
 <xsl:template match="allusers">
  <html><body>
    <h2>Users</h2>
    <table>
    <xsl:for-each select="user">
      <tr><td>
        <xsl:value-of select="f:ucfirst(concat(string(uid), string(id)))"/>
      </td></tr>
    </xsl:for-each>
    </table>
  </body></html>
 </xsl:template>
</xsl:stylesheet>
''')

transform = etree.XSLT(xsl)
result = transform(xml)
print result

输出:

<html><body>
<h2>Users</h2>
<table>
<tr><td>Bob1</td></tr>
<tr><td>Joe2</td></tr>
</table>
</body></html>

http://lxml.de/extensions.html#xpath-extension-functions

【讨论】:

  • 考虑在xsl:stylesheet 上添加exclude-result-prefixes="f" 以避免在HTML 结果中添加前缀。
【解决方案2】:

变量和函数有不同的答案。我只对变量 half 很熟悉。


对于变量,您可以将它们作为xsl:param 传递,方法是将它们作为关键字参数传递给调用。例如:

transform = etree.XSLT(xslt_tree)
result = transform(doc_root, a="5")

注意,参数是一个 XPath 表达式,所以字符串需要被引用。有一个函数可以不透明地执行此操作:

result = transform(doc_root, a=etree.XSLT.strparam(""" It's "Monty Python" """))

如果你想传递一个 XML 片段,你可以使用 exslt:node-set() 函数。


对于函数,您可以将它们公开为 xpath 函数或元素。种类繁多,我自己没有这样做,因此请阅读下面的文档和/或编辑此答案。


Docs for basic use and variables.

Docs for adding functions.

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-21
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多