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

使用ElementTree与BeautifulSoup按标签层级解析XML并转字典的方法

解答你的XML解析问题

一、完善XML转字典的代码

先帮你补全并优化现有代码——你提到的val函数应该是用来处理DrugBank XML的命名空间,我把这部分逻辑整合进去,同时实现完整的XML转字典功能:

import xml.etree.ElementTree as ET
import glob
import pprint

# 定义DrugBank XML的命名空间常量
DRUGBANK_NS = "{http://www.drugbank.ca}"

def xml_to_dict(element):
    """递归将XML元素转换为嵌套字典结构"""
    result = {}
    
    # 处理元素的属性
    if element.attrib:
        result["@attributes"] = element.attrib
    
    # 处理子元素
    children = list(element)
    if children:
        child_map = {}
        for child in children:
            # 去掉命名空间前缀,让键名更简洁
            child_key = child.tag.replace(DRUGBANK_NS, "")
            child_value = xml_to_dict(child)
            
            # 处理重复标签(比如多个<synonym>),自动转为列表
            if child_key in child_map:
                if not isinstance(child_map[child_key], list):
                    child_map[child_key] = [child_map[child_key]]
                child_map[child_key].append(child_value)
            else:
                child_map[child_key] = child_value
        result.update(child_map)
    # 处理元素的文本内容(无子元素时)
    elif element.text and element.text.strip():
        result = element.text.strip()
    
    return result

# 遍历所有output开头的本地文件(存储的XML内容)
for file_path in glob.glob('output*txt'):
    tree = ET.parse(file_path)
    root = tree.getroot()
    drug_data_dict = xml_to_dict(root)
    # 打印格式化后的字典结果
    pprint.pprint(drug_data_dict)

这段代码的核心逻辑:

  • 统一处理DrugBank的命名空间,避免字典键名带冗长前缀
  • 递归遍历XML节点,自动处理属性、子元素和文本内容
  • 针对重复标签(如药物别名、靶点)自动转为列表,保证数据结构合理

二、按标签层级数量解析的实现

不管是ElementTree还是BeautifulSoup,都可以轻松实现按层级解析,核心思路是跟踪当前节点的层级深度,当达到目标层级时提取节点。下面分别给出两种库的实现方式:

用ElementTree按层级解析

可以通过递归遍历+层级计数,或者迭代式队列跟踪的方式实现:

# 递归方式:提取指定层级的所有元素
def get_elements_by_level(element, target_level, current_level=0):
    if current_level == target_level:
        yield element
    for child in element:
        yield from get_elements_by_level(child, target_level, current_level + 1)

# 示例:提取第2层级的元素(根节点为第0层)
root = tree.getroot()
for elem in get_elements_by_level(root, 2):
    print(f"标签名:{elem.tag.replace(DRUGBANK_NS, '')},内容:{elem.text.strip()}")

用BeautifulSoup按层级解析

可以结合递归调用或自定义过滤器来实现层级提取:

from bs4 import BeautifulSoup

# 递归方式:按层级提取标签
def bs_get_elements_by_level(soup_node, target_level, current_level=0):
    if current_level == target_level:
        yield soup_node
    else:
        for child in soup_node.children:
            # 跳过文本节点,只处理标签元素
            if hasattr(child, 'name'):
                yield from bs_get_elements_by_level(child, target_level, current_level + 1)

# 示例:加载本地XML文件并提取第2层级元素
with open('output.txt', 'r') as f:
    soup = BeautifulSoup(f.read(), 'xml')

for tag in bs_get_elements_by_level(soup, 2):
    print(f"标签名:{tag.name},内容:{tag.text.strip()}")

总结来说,两种库都支持按层级解析,只需要在遍历过程中记录当前节点的深度,匹配目标层级时即可提取对应内容。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:51:19