首页 > 解决方案 > 如何递归地查找 ElementTree 中的所有相似标签及其级别?

问题描述

我有多棵树,每棵树的结构看起来都不一样。

我想要实现的是找到所有带有“序列号”标签的孩子以及他们的“级别”是什么以及他们的父母“序列号”是谁。

例如使用以下 XML

  **<?xml version="1.0"?>
<data>
    <Product Name="Product A">
        <Country>US</Country>
        <Year>2009</year>
        <Serial Number>AB102</Serial Number>
        <Document>
            <Country>US</Country>
            <Serial Number>BB103</SerialNumber>
        </Document>
        <Document>
            <Country>IA</Country>
            <Serial Number>CC102</Serial Number>
                 <Document>
                     <Serial Number>DD102</Serial Number>
                 </Document>
        </Document>
   </Product Name>
</data> 

我想取

Serial Number | Parent Serial Number | Level
   AB102             root                0 
   BB103             AB102               1   
   CC102             AB102               1  
   DD102             CC102               2

我的第一个想法是尝试实现某种递归函数,但我很难理解我必须设置的逻辑才能使其工作。有没有其他人做过类似的事情或知道如何正确实现这个递归函数?

标签: pythonrecursionxml-parsingelementtree

解决方案


我不得不对提供的 XML 进行一些更改(由于它是无效的 xml),标签中有空格和一些不匹配的拼写;但如果没有其他内容,以下内容应该为您提供一个起点(更改后的 XML 如下):

XML(example.xml 内容)

<?xml version="1.0"?>
<data>
    <ProductName Name="Product A">
        <Country>US</Country>
        <Year>2009</Year>
        <SerialNumber>AB102</SerialNumber>
        <Document>
            <Country>US</Country>
            <SerialNumber>BB103</SerialNumber>
        </Document>
        <Document>
            <Country>IA</Country>
            <SerialNumber>CC102</SerialNumber>
                 <Document>
                     <SerialNumber>DD102</SerialNumber>
                 </Document>
        </Document>
   </ProductName>
</data> 

代码

import xml.etree.ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

def process_children(tree_in, parent_name, depth):
    next_depth = depth + 1
    for c in list(tree_in):
        if(c.tag == 'SerialNumber'):
            print('{0} | {1} | {2}'.format(c.text, parent_name, depth))
            parent_name = c.text
        process_children(c, parent_name, next_depth)

process_children(root, 'root', -1)

结果

AB102 | root  | 0
BB103 | AB102 | 1
CC102 | AB102 | 1
DD102 | CC102 | 2

推荐阅读