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

如何重命名XML中带xsi:type属性的嵌套同名节点(含首尾标签)

解决基于xsi:type重命名XML嵌套节点的问题

针对你需要根据xsi:type属性重命名XML节点(包括对应的结束标签),同时处理嵌套结构中同名不同类型节点的需求,这里有两个实用的方案:


方案1:使用XSLT(XML原生转换方式)

XSLT是专门为XML转换设计的工具,非常适合这类规则明确的节点重命名场景,而且天然支持嵌套结构处理。

创建以下XSLT转换文件(比如rename_xsi_type.xsl):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <!-- 默认模板:复制所有未匹配的节点和属性,保证原有结构不变 -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 匹配所有带有xsi:type属性的元素 -->
    <xsl:template match="*[@xsi:type]">
        <!-- 生成新节点名:原节点本地名称 + xsi:type属性值 -->
        <xsl:element name="{local-name()}{@xsi:type}">
            <!-- 复制除xsi:type之外的所有属性 -->
            <xsl:apply-templates select="@*[not(namespace-uri() = 'http://www.w3.org/2001/XMLSchema-instance' and local-name() = 'type')]"/>
            <!-- 复制所有子节点 -->
            <xsl:apply-templates select="node()"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

如何使用

你可以通过多种工具执行这个转换:

  • 用支持XSLT的XML编辑器(比如Oxygen XML)直接转换
  • 用Python的lxml库执行:
from lxml import etree

xslt = etree.parse("rename_xsi_type.xsl")
transformer = etree.XSLT(xslt)
xml_input = etree.parse("your_input.xml")
xml_output = transformer(xml_input)
print(xml_output)
  • 用Java的javax.xml.transform包执行转换

这个方案会自动处理所有层级的嵌套节点,结束标签也会同步更新,同时移除不再需要的xsi:type属性(如果需要保留该属性,删除第二个模板里过滤xsi:type属性的代码即可)。


方案2:使用Python的lxml库(代码自定义处理)

如果你需要用代码逻辑灵活控制转换过程,Python的lxml库是个很好的选择,它支持XPath查询和节点修改。

以下是完整的处理代码:

from lxml import etree

def rename_nodes_by_xsi_type(xml_content):
    # 解析XML内容
    root = etree.fromstring(xml_content)
    xsi_namespace = "http://www.w3.org/2001/XMLSchema-instance"
    
    # 先查询所有带有xsi:type属性的节点(避免遍历过程中节点结构变化导致遗漏)
    target_nodes = root.xpath('//*[@xsi:type]', namespaces={'xsi': xsi_namespace})
    
    for node in target_nodes:
        # 提取节点的本地名称(处理带命名空间的标签)
        original_tag = node.tag.split('}')[-1]
        # 获取xsi:type属性的值
        xsi_type_value = node.attrib[f'{{{xsi_namespace}}}type']
        # 生成新的标签名
        new_tag = f"{original_tag}{xsi_type_value}"
        
        # 修改节点标签
        node.tag = new_tag
        # 删除xsi:type属性(可选:如果需要保留可以注释这行)
        del node.attrib[f'{{{xsi_namespace}}}type']
    
    # 返回格式化后的XML字符串
    return etree.tostring(root, encoding='utf-8', pretty_print=True).decode('utf-8')

# 示例使用
if __name__ == "__main__":
    # 你的示例XML内容
    sample_xml = """<?xml version="1.0"?>
<Project xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <Children>
 <ProjectChild xsi:type="Group">
 <Number>1</Number>
 <Name>Malerarbeiten</Name>
 <children>
 <ProjectChild xsi:type="Position">
 <Number>1</Number>
 <Name>Wand Bestand</Name>
 <CalculationItems>
 <CalculationItem xsi:type="PointCalculationItem">
 <Name>Bestand mit Tapete</Name>
 <Comment />
 <Count>1</Count>
 <Area>98.8487577533343</Area>
 <AreaFormula>plo * h = (5,81+19,68+5,435+0,08+0,375) * 3,15</AreaFormula>
 <Sign>1</Sign>
 </CalculationItem>
 </CalculationItems>
 <Value>185.713</Value>
 <ValueFormula>185,713</ValueFormula>
 <Unit>m²</Unit>
 </ProjectChild>
 <ProjectChild xsi:type="Position">
 <Number>2</Number>
 <Name>Ziegelwand</Name>
 </ProjectChild>
 </children>
 </ProjectChild>
 <ProjectChild xsi:type="Group">
 </ProjectChild>
 </Children>
 <Name>SG H5-1.OG</Name>
 </Project>"""
    transformed_result = rename_nodes_by_xsi_type(sample_xml)
    print(transformed_result)

关键说明

  • 先一次性查询所有目标节点:因为如果边遍历边修改,可能会因为节点结构变化导致嵌套的节点被遗漏,先收集所有节点再处理就不会有这个问题
  • 处理命名空间:代码中通过拆分标签字符串提取本地名称,兼容带有命名空间的XML节点
  • 灵活可控:你可以根据需求修改新标签名的生成规则,或者调整是否保留xsi:type属性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:32:43