You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在本地上下文中评估XSLT处理器传入的路径参数?

问题与解决方案

问题背景

源XML:

<A>
   <B>something</B>
   <B>something else</B>
</A>

目标XML:

<C>
   <D>something</D>
   <D>something else</D>
</C>

常规XSLT可实现上述转换,但使用Python的lxml处理器传入参数化路径时,参数始终在全局上下文(current()节点为根节点)中评估,无法得到预期结果。尝试过嵌套模板传参、字符串参数后评估等方法均无效,目前通过预处理XSL文件解决,希望找到纯XSLT+lxml的解决方案。

解决方案

方法一:使用XSLT 3.0的xsl:evaluate(灵活度高)

利用XSLT 3.0的xsl:evaluate特性,指定路径评估的上下文节点,避免参数在全局上下文执行。

XSLT样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- 可参数化的路径和目标元素名 -->
    <xsl:param name="source-path" select="'A/B'"/>
    <xsl:param name="root-target" select="'C'"/>
    <xsl:param name="item-target" select="'D'"/>

    <xsl:template match="/">
        <!-- 生成根目标元素 -->
        <xsl:element name="{$root-target}">
            <!-- 在当前上下文(根节点)评估传入的路径 -->
            <xsl:evaluate xpath="$source-path" context-item=".">
                <!-- 匹配路径选中的节点,生成目标子元素 -->
                <xsl:template match="*">
                    <xsl:element name="{$item-target}">
                        <xsl:value-of select="."/>
                    </xsl:element>
                </xsl:template>
            </xsl:evaluate>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Python调用代码

from lxml import etree

# 加载源XML
source_xml = """<A>
   <B>something</B>
   <B>something else</B>
</A>"""
source_tree = etree.fromstring(source_xml)

# 加载XSLT样式表
xslt_content = """<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="source-path" select="'A/B'"/>
    <xsl:param name="root-target" select="'C'"/>
    <xsl:param name="item-target" select="'D'"/>

    <xsl:template match="/">
        <xsl:element name="{$root-target}">
            <xsl:evaluate xpath="$source-path" context-item=".">
                <xsl:template match="*">
                    <xsl:element name="{$item-target}">
                        <xsl:value-of select="."/>
                    </xsl:element>
                </xsl:template>
            </xsl:evaluate>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>"""
xslt_tree = etree.fromstring(xslt_content)

# 创建转换器并传递参数
transformer = etree.XSLT(xslt_tree)
result = transformer(
    source_tree,
    source_path="'A/B'",
    root_target="'C'",
    item_target="'D'"
)

# 输出结果
print(str(result))

方法二:XSLT 1.0兼容方案(无版本依赖)

如果环境不支持XSLT 3.0,可通过传递节点名称参数,结合local-name()在当前上下文匹配节点。

XSLT样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="source-root-name" select="'A'"/>
    <xsl:param name="source-item-name" select="'B'"/>
    <xsl:param name="target-root-name" select="'C'"/>
    <xsl:param name="target-item-name" select="'D'"/>

    <xsl:template match="/">
        <xsl:element name="{$target-root-name}">
            <!-- 在当前上下文匹配指定名称的节点 -->
            <xsl:apply-templates 
                select="*[local-name()=$source-root-name]/*[local-name()=$source-item-name]"
            />
        </xsl:element>
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{$target-item-name}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Python调用代码

from lxml import etree

source_xml = """<A>
   <B>something</B>
   <B>something else</B>
</A>"""
source_tree = etree.fromstring(source_xml)

xslt_content = """<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="source-root-name" select="'A'"/>
    <xsl:param name="source-item-name" select="'B'"/>
    <xsl:param name="target-root-name" select="'C'"/>
    <xsl:param name="target-item-name" select="'D'"/>

    <xsl:template match="/">
        <xsl:element name="{$target-root-name}">
            <xsl:apply-templates 
                select="*[local-name()=$source-root-name]/*[local-name()=$source-item-name]"
            />
        </xsl:element>
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{$target-item-name}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>"""
xslt_tree = etree.fromstring(xslt_content)

transformer = etree.XSLT(xslt_tree)
result = transformer(
    source_tree,
    source_root_name="'A'",
    source_item_name="'B'",
    target_root_name="'C'",
    target_item_name="'D'"
)

print(str(result))

关键说明

  • 避免直接将参数化路径写在select属性中(如select="$source-path"),这种写法会让参数在全局上下文评估,而非当前模板的上下文,这是之前遇到问题的核心原因。
  • xsl:evaluate需要lxml版本支持XSLT 3.0,确保环境中的lxml版本足够新。
  • 第二种方法基于XSLT 1.0,兼容性更强,适合无法升级lxml的场景。

内容的提问来源于stack exchange,提问作者Stefanos Tsaousis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:24:33