需求
在实际应用中,需要对xml配置文件进行实时修改,
1.增加、删除 某些节点
2.增加,删除,修改某个节点下的某些属性
3.增加,删除,修改某些节点的文本
使用xml文档
<?xml version="1.0" encoding="UTF-8"?>
实现思想
使用ElementTree,先将文件读入,解析成树,之后,根据路径,可以定位到树的每个节点,再对节点进行修改,最后直接将其输出
实现代码
1 #!/usr/bin/python2 # -*- coding=utf-8 -*-
3 # author : wklken@yeah.net4 # date: 2012-05-25
5 # version: 0.1
6
7 fromxml.etree.ElementTree import ElementTree,Element8
9 def read_xml(in_path):10 '''读取并解析xml文件
11 in_path: xml路径12 return: ElementTree'''13 tree =ElementTree()14 tree.parse(in_path)15 returntree16
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 inkv_map:28 if node.get(key) != kv_map.get(key):29 returnFalse30 returnTrue31
32 #---------------search -----
33 def find_nodes(tree, path):34 '''查找某个路径匹配的所有节点
35 tree: xml树36 path: 节点路径'''37 returntree.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 innodelist:45 ifif_match(node, kv_map):46 result_nodes.append(node)47 returnresult_nodes48
49 #---------------change -----
50 def change_node_properties(nodelist, kv_map, is_delete=False):51 '''修改/增加 /删除 节点的属性及属性值
52 nodelist: 节点列表53 kv_map:属性及属性值map'''54 for node innodelist:55 for key inkv_map:56 ifis_delete:57 if key innode.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 innodelist:67 ifis_add:68 node.text +=text69 elif is_delete:70 node.text = ""
71 else:72 node.text =text73
74 def create_node(tag, property_map, content):75 '''新造一个节点
76 tag:节点标签77 property_map:属性及属性值map78 content: 节点闭合标签里的文本内容79 return 新节点'''80 element =Element(tag, property_map)81 element.text =content82 returnelement83
84 def add_child_node(nodelist, element):85 '''给一个节点添加子节点
86 nodelist: 节点列表87 element: 子节点'''88 for node innodelist: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 innodelist:97 children =parent_node.getchildren()98 for child inchildren: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")