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

Python中从多层嵌套XML子节点提取标签与文本——递归调用问题

问题描述

需要提取XML块中所有嵌套子节点的标签与文本,编写的Python代码如下,但get_tag_and_text函数的keys_and_values字典无法收集所有内容,仅保留最后一个有效条目:

import xml.etree.ElementTree as ET

class MyParser:
    def __init__(self, xml_block):
        self.xml_block = xml_block

def main(self):
        tree = ET.ElementTree(ET.fromstring(self.xml_block))
        root = tree.getroot()
        self.get_tag_and_text(root)

def get_tag_and_text(self, root):
    keys_and_values = {}
    for child in root:
        if child.text is not None:
            keys_and_values[child.tag] = child.text
        self.get_tag_and_text(child)

示例XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<abc:random xmlns:abc="http://www.mywebsite.com" schemaVersion="1.2">
<abc:header>
<abc:number>8</abc:number>
<abc:type>text/xml</abc:type>
</abc:header>
<abc:body>
<abc:d>
<abc:purpose>start</abc:purpose>
</abc:d>
</abc:body>
</abc:random>
问题原因
  1. 每次递归调用get_tag_and_text时都会新建局部字典keys_and_values,递归完成后该字典不会传递回上层调用,导致只有当前层的临时数据无法累积
  2. 方法未返回收集到的字典,也未将子节点递归得到的结果合并到当前字典中
  3. 类方法缩进错误,main和get_tag_and_text未正确归属到MyParser类内部
修正后的代码
import xml.etree.ElementTree as ET

class MyParser:
    def __init__(self, xml_block):
        self.xml_block = xml_block

    def main(self):
        root = ET.fromstring(self.xml_block)
        return self.get_tag_and_text(root)

    def get_tag_and_text(self, element):
        keys_and_values = {}
        # 处理当前节点的文本(过滤纯空白内容)
        if element.text and element.text.strip():
            keys_and_values[element.tag] = element.text.strip()
        # 递归处理子节点并合并结果
        for child in element:
            child_data = self.get_tag_and_text(child)
            keys_and_values.update(child_data)
        return keys_and_values
关键修改说明
  • 修正类方法缩进,确保main和get_tag_and_text属于MyParser类
  • get_tag_and_text返回收集到的字典,每次递归时用update方法将子节点的结果合并到当前字典
  • 添加纯空白文本过滤逻辑,避免收集无效空值
  • main方法直接返回最终收集结果,方便外部调用
测试结果

使用示例XML运行修正后的代码:

xml_content = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<abc:random xmlns:abc="http://www.mywebsite.com" schemaVersion="1.2">
<abc:header>
<abc:number>8</abc:number>
<abc:type>text/xml</abc:type>
</abc:header>
<abc:body>
<abc:d>
<abc:purpose>start</abc:purpose>
</abc:d>
</abc:body>
</abc:random>"""

parser = MyParser(xml_content)
result = parser.main()
print(result)

输出结果:

{
    '{http://www.mywebsite.com}number': '8',
    '{http://www.mywebsite.com}type': 'text/xml',
    '{http://www.mywebsite.com}purpose': 'start'
}

如果需要去掉命名空间前缀,可添加辅助函数处理:

def strip_namespace(tag):
    return tag.split('}')[1] if '}' in tag else tag

# 在get_tag_and_text中替换tag赋值逻辑:
keys_and_values[strip_namespace(element.tag)] = element.text.strip()

处理后输出的键会变成number、type、purpose,更简洁。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 04:50:00