使用Python BeautifulSoup更新XML同标签下多组键值对属性值
场景说明
待匹配更新的列表数据如下:
Sorted_TestSpecID: [10860972, 10860972, 10860972, 10860972, 10860972] Sorted_TestCaseID: [16961435, 16961462, 16961739, 16961741, 16961745] Sorted_TestText : ['SIG1', 'SIG2', 'SIG3', 'SIG4', 'SIG5']
原始XML数据中,单个<tc>节点下包含<title>、<tcid>节点以及<attributes>节点,<attributes>下有多组<attr>子节点,每个<attr>分别存储<key>(属性名)和<value>(属性值),示例结构如下:
<tc> <title>SIG1</title> <tcid>2c758925-dc3d-4b1d-a5e2-e0ca54c52a47</tcid> <attributes> <attr> <key>TestSpec ID</key> <value>1</value> </attr> <attr> <key>TestCase ID</key> <value>2</value> </attr> </attributes> </tc>
实现需求
- 遍历XML中所有
<tc>节点,筛选出<title>文本存在于Sorted_TestText列表中的节点 - 对筛选出的节点,定位
<key>为TestCase ID的<attr>节点,将其对应的<value>更新为Sorted_TestCaseID列表中对应位置的值 - 定位
<key>为TestSpec ID的<attr>节点,将其对应的<value>更新为Sorted_TestSpecID列表中对应位置的值
原有代码问题
原有逻辑存在三个核心错误,导致全量<value>节点被误修改:
- 匹配到符合条件的tc节点后,调用
soup.select('value')是全局查找整个文档的所有value节点,没有限定在当前tc节点范围内查找 - 没有根据
<attr>下的<key>值做匹配判断,直接遍历所有value节点替换值,完全跳过了属性名校验逻辑 - 没有建立title和目标值的索引映射,直接zip全局value和TestCaseID列表,值和节点的对应关系完全错乱
- 变量名使用了Python内置类型
set作为循环变量,容易引发不可预期的运行错误
修正后代码
from bs4 import BeautifulSoup # 预定义待更新的列表数据 Sorted_TestSpecID = [10860972, 10860972, 10860972, 10860972, 10860972] Sorted_TestCaseID = [16961435, 16961462, 16961739, 16961741, 16961745] Sorted_TestText = ['SIG1', 'SIG2', 'SIG3', 'SIG4', 'SIG5'] # 先建立title到索引的映射,避免每次循环做列表查找,提升匹配效率 title_index_map = {title: idx for idx, title in enumerate(Sorted_TestText)} soup = BeautifulSoup(xml_data, 'xml') all_tc_nodes = soup.find_all('tc') for tc_node in all_tc_nodes: title_node = tc_node.find('title') # 跳过没有title节点的异常tc结构 if not title_node: continue current_title = title_node.text.strip() # 标题不在待更新列表直接跳过 if current_title not in title_index_map: continue # 获取当前title对应的目标值索引 match_idx = title_index_map[current_title] target_case_id = Sorted_TestCaseID[match_idx] target_spec_id = Sorted_TestSpecID[match_idx] # 仅遍历当前tc节点下的attr节点,不做全局查找 all_attr_nodes = tc_node.find_all('attr') for attr in all_attr_nodes: key_node = attr.find('key') value_node = attr.find('value') # 跳过key或value缺失的异常attr结构 if not key_node or not value_node: continue attr_key = key_node.text.strip() # 仅当key匹配目标属性名时才更新对应value,不会误改其他属性 if attr_key == 'TestCase ID': value_node.string = str(target_case_id) elif attr_key == 'TestSpec ID': value_node.string = str(target_spec_id) # 处理完成后通过soup.prettify()即可获取更新后的完整XML内容 updated_xml = soup.prettify()
逻辑说明
- 所有节点查找都限定在当前处理的tc节点范围内,从根源上避免跨节点误改内容
- 每个attr节点先校验key值,只有匹配到目标属性名时才修改对应的value节点,实现精准更新
- 增加了异常结构兼容逻辑,遇到结构不完整的tc/attr节点不会抛出报错中断执行
- 字典映射的匹配方式比循环列表查找的时间复杂度更低,处理大体积XML时性能更好
内容的提问来源于stack exchange,提问作者user7482089
相关产品推荐
相关产品推荐

