需求
在實際應用中,需要對xml配置文件進行實時修改,
1.增加、刪除 某些節點
2.增加,刪除,修改某個節點下的某些屬性
3.增加,刪除,修改某些節點的文本
使用xml文檔
<?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")