首页 > 编程 > Python > 正文

详解在Python程序中解析并修改XML内容的方法

2020-01-04 17:57:30
字体:
来源:转载
供稿:网友

这篇文章主要介绍了在Python程序中解析并修改XML内容的方法,依赖于解析成树状结构后的节点进行修改,需要的朋友可以参考下

需求

在实际应用中,需要对xml配置文件进行实时修改,

1.增加、删除 某些节点

2.增加,删除,修改某个节点下的某些属性

3.增加,删除,修改某些节点的文本

使用xml文档

 

 
  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <framework> 
  3. <processers> 
  4. <processer name="AProcesser" file="lib64/A.so" 
  5. path="/tmp"
  6. </processer> 
  7. <processer name="BProcesser" file="lib64/B.so" value="fordelete"
  8. </processer> 
  9. <processer name="BProcesser" file="lib64/B.so2222222"/> 
  10.  
  11. <services> 
  12. <service name="search" prefix="/bin/search?" 
  13. output_formatter="OutPutFormatter:service_inc"
  14.  
  15. <chain sequency="chain1"/> 
  16. <chain sequency="chain2"></chain> 
  17. </service> 
  18. <service name="update" prefix="/bin/update?"
  19. <chain sequency="chain3" value="fordelete"/> 
  20. </service> 
  21. </services> 
  22. </processers> 
  23. </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"

修改后的结果

 

 
  1. <?xml version='1.0' encoding='utf-8'?> 
  2. <framework> 
  3. <processers> 
  4. <processer file="lib64/A.so" name="AProcesser" path="/tmp"
  5. </processer> 
  6. <processer age="1" file="lib64/B.so" name="BProcesser"
  7. <person age="15" money="200000">this is the firest content</person> 
  8. </processer> 
  9. <processer age="1" file="lib64/B.so2222222" name="BProcesser"
  10. <person age="15" money="200000">this is the firest content</person> 
  11. </processer> 
  12.  
  13. <services> 
  14. <service name="search" output_formatter="OutPutFormatter:service_inc" 
  15. prefix="/bin/search?"
  16.  
  17. <chain sequency="chain2" /> 
  18. </service> 
  19. <service name="update" prefix="/bin/update?"
  20. <chain sequency="chain3" value="fordelete">new text</chain> 
  21. </service> 
  22. </services> 
  23. </processers> 
  24. </framework> 

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表