如何用Python重命名XSLT中的重复变量声明及引用
解决XSLT重复变量声明问题的Python脚本
问题背景
我有一段Altova MapForce生成的XSLT 2.0代码,其中变量var287___as_double被重复声明引发语法错误。需要通过Python修改该文件,可选两种处理方式:
- 将
AL506C标签下的重复变量var287___as_double重命名(如改为var287___as_double2),并同步修改该标签内的所有引用 - 直接对
AL506C标签下的所有变量进行重命名,彻底避免重复冲突
原代码示例
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="SDEV:SDEV_NCTS_down_fillUCRC547"/> <xsl:for-each select="($var292_CD___C)]"> <AL586B xmlns="AL586B" > <xsl:variable name="var288_cur" as="node()" select="."/> <xsl:variable name="var287___as_double" as="xs:double" select="xs:double('6')"/> </AL586B> </xsl:for-each> <xsl:for-each select="(./ns0:AL586B)"> <AL506C xmlns="AL506C"> <xsl:attribute name="xsi:schemaLocation" namespace="http://www.w3.org/2001/XMLSchema-instance"/> <xsl:variable name="var287___as_double" as="xs:double" select="xs:double('6')"/> <xsl:variable name="var1_preparationDateAndTi_as_string" as="xs:string" select="xs:string(xs:dateTime(fn:string($var287___as_double)))"/> </AL506C> </xsl:for-each> </xsl:stylesheet>
修改后代码示例(方式1)
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="SDEV:SDEV_NCTS_down_fillUCRC547"/> <xsl:for-each select="($var292_CD___C)]"> <AL586B xmlns="AL586B" > <xsl:variable name="var288_cur" as="node()" select="."/> <xsl:variable name="var287___as_double" as="xs:double" select="xs:double('6')"/> </AL586B> </xsl:for-each> <xsl:for-each select="(./ns0:AL586B)"> <AL506C xmlns="AL506C"> <xsl:attribute name="xsi:schemaLocation" namespace="http://www.w3.org/2001/XMLSchema-instance"/> <xsl:variable name="var287___as_double2" as="xs:double" select="xs:double('6')"/> <xsl:variable name="var1_preparationDateAndTi_as_string" as="xs:string" select="xs:string(xs:dateTime(fn:string($var287___as_double2)))"/> </AL506C> </xsl:for-each> </xsl:stylesheet>
Python解决方案
依赖准备
首先安装XML解析库:
pip install lxml
方式1:重命名指定重复变量
该脚本会定位AL506C标签下的var287___as_double变量,将其重命名为var287___as_double2,并同步替换该标签内的所有引用:
from lxml import etree # 定义命名空间 NS_MAP = { 'xsl': 'http://www.w3.org/1999/XSL/Transform', 'al506c': 'AL506C' } def fix_duplicate_variable(xslt_path, output_path): # 读取XSLT文件 tree = etree.parse(xslt_path) root = tree.getroot() # 找到所有AL506C节点 al506c_nodes = root.xpath('//al506c:AL506C', namespaces=NS_MAP) for node in al506c_nodes: # 找到目标变量声明 target_var = node.xpath('./xsl:variable[@name="var287___as_double"]', namespaces=NS_MAP) if not target_var: continue target_var = target_var[0] # 重命名变量 old_name = target_var.get('name') new_name = f"{old_name}2" target_var.set('name', new_name) # 替换当前AL506C节点内所有对该变量的引用($varxxx格式) for elem in node.xpath('.//*', namespaces=NS_MAP): # 处理select属性 if 'select' in elem.attrib: elem.attrib['select'] = elem.attrib['select'].replace(f"${old_name}", f"${new_name}") # 处理文本内容 if elem.text: elem.text = elem.text.replace(f"${old_name}", f"${new_name}") # 保存修改后的文件 tree.write(output_path, encoding='utf-8', xml_declaration=True, pretty_print=True) # 使用示例 fix_duplicate_variable('input.xsl', 'fixed_input.xsl')
方式2:重命名AL506C下所有变量
该脚本会给AL506C标签下的所有变量名添加后缀_al506c,彻底避免变量重复冲突:
from lxml import etree NS_MAP = { 'xsl': 'http://www.w3.org/1999/XSL/Transform', 'al506c': 'AL506C' } def rename_all_al506c_variables(xslt_path, output_path): tree = etree.parse(xslt_path) root = tree.getroot() al506c_nodes = root.xpath('//al506c:AL506C', namespaces=NS_MAP) for node in al506c_nodes: # 收集当前节点下的所有变量及其新名称 var_mapping = {} variables = node.xpath('./xsl:variable', namespaces=NS_MAP) for var in variables: old_name = var.get('name') new_name = f"{old_name}_al506c" var.set('name', new_name) var_mapping[old_name] = new_name # 替换所有变量引用 for elem in node.xpath('.//*', namespaces=NS_MAP): if 'select' in elem.attrib: select_val = elem.attrib['select'] for old, new in var_mapping.items(): select_val = select_val.replace(f"${old}", f"${new}") elem.attrib['select'] = select_val if elem.text: text_val = elem.text for old, new in var_mapping.items(): text_val = text_val.replace(f"${old}", f"${new}") elem.text = text_val tree.write(output_path, encoding='utf-8', xml_declaration=True, pretty_print=True) # 使用示例 rename_all_al506c_variables('input.xsl', 'fixed_input_all.xsl')
注意事项
- 脚本使用
lxml处理XML,相比正则表达式能更安全地处理XML结构,避免破坏XSLT语法 - 若XSLT中存在复杂的变量引用(如嵌套在字符串或其他表达式中),可根据实际情况调整替换逻辑
- 处理前建议备份原XSLT文件,避免数据丢失
内容的提问来源于stack exchange,提问作者RamAlx
相关产品推荐
相关产品推荐

