python修改xml文件标签的属性值
需求
在实际应用中,需要对xml配置文件进行实时修改,
1.增加、删除 某些节点
2.增加,删除,修改某个节点下的某些属性
3.增加,删除,修改某些节点的文本
参考官网:xml.etree.ElementTree --- ElementTree XML API — Python 3.12.0a1 文档
使用xml文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?xml version= "1.0" encoding= "UTF-8" ?> <framework> <processers> <processer name= "AProcesser" file= "lib64/A.so" path= "/tmp" /> <processer name= "BProcesser" file= "lib64/B.so" value= "fordelete" /> <processer name= "BProcesser" file= "lib64/B.so2222222" /> <services> <service name= "search" prefix= "/bin/search?" output_formatter= "OutPutFormatter:service_inc" > <chain sequency= "chain1" /> <chain sequency= "chain2" /> </service> <service name= "update" prefix= "/bin/update?" > <chain sequency= "chain3" value= "fordelete" /> </service> </services> </processers> </framework> |
实现思想
使用ElementTree,先将文件读入,解析成树,之后,根据路径,可以定位到树的每个节点,再对节点进行修改,最后直接将其输出
实现代码
1 #!/usr/bin/python 2 # -*- coding=utf-8 -*- 3 # author : wklken@yeah.net 4 # date: 2012-05-25 5 # version: 0.1 6 7 from xml.etree.ElementTree import ElementTree,Element 8 9 def read_xml(in_path): 10 '''读取并解析xml文件 11 in_path: xml路径 12 return: ElementTree''' 13 tree = ElementTree() 14 tree.parse(in_path) 15 return tree 16 17 def write_xml(tree, out_path): 18 '''将xml文件写出 19 tree: xml树 20 out_path: 写出路径''' 21 tree.write(out_path, encoding="utf-8",xml_declaration=True) 22 23 def if_match(node, kv_map): 24 '''判断某个节点是否包含所有传入参数属性 25 node: 节点 26 kv_map: 属性及属性值组成的map''' 27 for key in kv_map: 28 if node.get(key) != kv_map.get(key): 29 return False 30 return True 31 32 #---------------search ----- 33 def find_nodes(tree, path): 34 '''查找某个路径匹配的所有节点 35 tree: xml树 36 path: 节点路径''' 37 return tree.findall(path) 38 39 def get_node_by_keyvalue(nodelist, kv_map): 40 '''根据属性及属性值定位符合的节点,返回节点 41 nodelist: 节点列表 42 kv_map: 匹配属性及属性值map''' 43 result_nodes = [] 44 for node in nodelist: 45 if if_match(node, kv_map): 46 result_nodes.append(node) 47 return result_nodes 48 49 #---------------change ----- 50 def change_node_properties(nodelist, kv_map, is_delete=False): 51 '''修改/增加 /删除 节点的属性及属性值 52 nodelist: 节点列表 53 kv_map:属性及属性值map''' 54 for node in nodelist: 55 for key in kv_map: 56 if is_delete: 57 if key in node.attrib: 58 del node.attrib[key] 59 else: 60 node.set(key, kv_map.get(key)) 61 62 def change_node_text(nodelist, text, is_add=False, is_delete=False): 63 '''改变/增加/删除一个节点的文本 64 nodelist:节点列表 65 text : 更新后的文本''' 66 for node in nodelist: 67 if is_add: 68 node.text += text 69 elif is_delete: 70 node.text = "" 71 else: 72 node.text = text 73 74 def create_node(tag, property_map, content): 75 '''新造一个节点 76 tag:节点标签 77 property_map:属性及属性值map 78 content: 节点闭合标签里的文本内容 79 return 新节点''' 80 element = Element(tag, property_map) 81 element.text = content 82 return element 83 84 def add_child_node(nodelist, element): 85 '''给一个节点添加子节点 86 nodelist: 节点列表 87 element: 子节点''' 88 for node in nodelist: 89 node.append(element) 90 91 def del_node_by_tagkeyvalue(nodelist, tag, kv_map): 92 '''同过属性及属性值定位一个节点,并删除之 93 nodelist: 父节点列表 94 tag:子节点标签 95 kv_map: 属性及属性值列表''' 96 for parent_node in nodelist: 97 children = parent_node.getchildren() 98 for child in children: 99 if child.tag == tag and if_match(child, kv_map): 100 parent_node.remove(child) 101 102 if __name__ == "__main__": 103 #1. 读取xml文件 104 tree = read_xml("./test.xml") 105 106 #2. 属性修改 107 #A. 找到父节点 108 nodes = find_nodes(tree, "processers/processer") 109 #B. 通过属性准确定位子节点 110 result_nodes = get_node_by_keyvalue(nodes, {"name":"BProcesser"}) 111 #C. 修改节点属性 112 change_node_properties(result_nodes, {"age": "1"}) 113 #D. 删除节点属性 114 change_node_properties(result_nodes, {"value":""}, True) 115 116 #3. 节点修改 117 #A.新建节点 118 a = create_node("person", {"age":"15","money":"200000"}, "this is the firest content") 119 #B.插入到父节点之下 120 add_child_node(result_nodes, a) 121 122 #4. 删除节点 123 #定位父节点 124 del_parent_nodes = find_nodes(tree, "processers/services/service") 125 #准确定位子节点并删除之 126 target_del_node = del_node_by_tagkeyvalue(del_parent_nodes, "chain", {"sequency" : "chain1"}) 127 128 #5. 修改节点文本 129 #定位节点 130 text_nodes = get_node_by_keyvalue(find_nodes(tree, "processers/services/service/chain"), {"sequency":"chain3"}) 131 change_node_text(text_nodes, "new text") 132 133 #6. 输出到结果文件 134 write_xml(tree, "./out.xml")