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

求助:递归打印xmltodict解析后的复杂字典为树形结构

解析UML XMI为树形结构的递归打印方案

问题说明

我已经用xmltodict把UML XMI格式的XML文件解析成字典了,代码如下:

with open(xml_file, "r") as f:
    xml_content = f.read()
dct = xmltodict.parse(xml_content)

自己写递归函数打印树形结构时,卡在了层级计数器重置和列表处理上,现有代码逻辑有问题:

def p(d, counter = 0, c = 0):
    for k, v in d.items():
        print("|___"*counter, k)
        if isinstance(v, dict):
            c = len(v)
            if(c > counter):
                counter += 1
            else:
                counter = 0
            p(v, counter, c)
        elif isinstance(v, list):
            for i, v2 in enumerate(v):
                print("|___" * counter, k)
                p(v2, counter)

想要的输出是类似这样的树形结构:

xmi
|_Model
   |_packagedElement (Root 2)
       | _ packagedElement (Package1)
       | - packagedElement (Package2)
             | _ packagedElement (Package2.1)
             | _ packagedElement (Package2.2)
                   | _ ownedComment (Note)
                   | _ ...

要求通用,不能用XPATH。

修正后的解决方案

原函数的问题在于用字典长度判断层级完全不合理,而且列表处理时会重复打印键值。下面是修正后的递归函数,核心是传递当前层级深度,针对列表元素做区分标记,还能自动提取UML元素的名称作为后缀:

def print_tree(data, depth=0, indent=""):
    if isinstance(data, dict):
        for key, value in data.items():
            # 打印当前节点的键,若值是列表则显示列表长度
            print(f"{indent}{'|_ ' if depth > 0 else ''}{key}", end="")
            print(f" (Root {len(value)})\n" if isinstance(value, list) else "\n")
            
            # 计算下一层的基础缩进
            new_indent = indent + ("|   " if depth > 0 else "")
            
            if isinstance(value, dict):
                # 递归处理子字典
                print_tree(value, depth + 1, new_indent)
            elif isinstance(value, list):
                # 遍历列表中的每个元素
                for idx, item in enumerate(value):
                    is_last = idx == len(value) - 1
                    # 用不同符号区分最后一个列表项
                    symbol = "- " if is_last else "_ "
                    
                    # 尝试提取元素的name属性作为后缀(符合UML XMI结构)
                    item_label = ""
                    if isinstance(item, dict) and "@name" in item:
                        item_label = f" ({item['@name']})"
                    
                    # 打印列表项
                    print(f"{new_indent}| {symbol}{key}{item_label}")
                    
                    # 计算列表项子节点的缩进
                    item_indent = new_indent + ("    " if is_last else "|   ")
                    # 递归处理列表项的内容
                    print_tree(item, depth + 2, item_indent)
            else:
                # 处理字符串等基础类型值
                print(f"{new_indent}|_ {value}")

使用方法

直接把解析得到的字典传进去就行:

print_tree(dct)

关键优化点

  1. 用层级深度替代原函数的错误计数器逻辑,缩进更准确
  2. 列表节点自动显示长度(比如packagedElement (Root 2))
  3. 列表项区分最后一个元素,用-和_标记,结构更清晰
  4. 自动提取UML元素的@name属性作为后缀,贴合XMI格式特点
  5. 缩进用| 和 区分是否有后续节点,树形结构更直观

内容的提问来源于stack exchange,提问作者brian k.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:05:24