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


Posted in Python onNovember 16, 2015

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

1.增加、删除 某些节点

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

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

使用xml文档

<?xml version="1.0" encoding="UTF-8"?>
<framework>
  <processers>
    <processer name="AProcesser" file="lib64/A.so"
      path="/tmp">
    </processer>
    <processer name="BProcesser" file="lib64/B.so" value="fordelete">
    </processer>
    <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"></chain>
      </service>
      <service name="update" prefix="/bin/update?">
        <chain sequency="chain3" value="fordelete"/>
      </service>
    </services>
  </processers>
</framework>

实现思想
使用ElementTree,先将文件读入,解析成树,之后,根据路径,可以定位到树的每个节点,再对节点进行修改,最后直接将其输出

实现代码

#!/usr/bin/python
# -*- coding=utf-8 -*-
# author : wklken@yeah.net
# date: 2012-05-25
# version: 0.1

from xml.etree.ElementTree import ElementTree,Element

def read_xml(in_path):
  '''读取并解析xml文件
    in_path: xml路径
    return: ElementTree'''
  tree = ElementTree()
  tree.parse(in_path)
  return tree

def write_xml(tree, out_path):
  '''将xml文件写出
    tree: xml树
    out_path: 写出路径'''
  tree.write(out_path, encoding="utf-8",xml_declaration=True)

def if_match(node, kv_map):
  '''判断某个节点是否包含所有传入参数属性
    node: 节点
    kv_map: 属性及属性值组成的map'''
  for key in kv_map:
    if node.get(key) != kv_map.get(key):
      return False
  return True

#---------------search -----
def find_nodes(tree, path):
  '''查找某个路径匹配的所有节点
    tree: xml树
    path: 节点路径'''
  return tree.findall(path)

def get_node_by_keyvalue(nodelist, kv_map):
  '''根据属性及属性值定位符合的节点,返回节点
    nodelist: 节点列表
    kv_map: 匹配属性及属性值map'''
  result_nodes = []
  for node in nodelist:
    if if_match(node, kv_map):
      result_nodes.append(node)
  return result_nodes

#---------------change -----
def change_node_properties(nodelist, kv_map, is_delete=False):
  '''修改/增加 /删除 节点的属性及属性值
    nodelist: 节点列表
    kv_map:属性及属性值map'''
  for node in nodelist:
    for key in kv_map:
      if is_delete:
        if key in node.attrib:
          del node.attrib[key]
      else:
        node.set(key, kv_map.get(key))

def change_node_text(nodelist, text, is_add=False, is_delete=False):
  '''改变/增加/删除一个节点的文本
    nodelist:节点列表
    text : 更新后的文本'''
  for node in nodelist:
    if is_add:
      node.text += text
    elif is_delete:
      node.text = ""
    else:
      node.text = text

def create_node(tag, property_map, content):
  '''新造一个节点
    tag:节点标签
    property_map:属性及属性值map
    content: 节点闭合标签里的文本内容
    return 新节点'''
  element = Element(tag, property_map)
  element.text = content
  return element

def add_child_node(nodelist, element):
  '''给一个节点添加子节点
    nodelist: 节点列表
    element: 子节点'''
  for node in nodelist:
    node.append(element)

def del_node_by_tagkeyvalue(nodelist, tag, kv_map):
  '''同过属性及属性值定位一个节点,并删除之
    nodelist: 父节点列表
    tag:子节点标签
    kv_map: 属性及属性值列表'''
  for parent_node in nodelist:
    children = parent_node.getchildren()
    for child in children:
      if child.tag == tag and if_match(child, kv_map):
        parent_node.remove(child)

if __name__ == "__main__":
  #1. 读取xml文件
  tree = read_xml("./test.xml")

  #2. 属性修改
   #A. 找到父节点
  nodes = find_nodes(tree, "processers/processer")
   #B. 通过属性准确定位子节点
  result_nodes = get_node_by_keyvalue(nodes, {"name":"BProcesser"})
   #C. 修改节点属性
  change_node_properties(result_nodes, {"age": "1"})
   #D. 删除节点属性
  change_node_properties(result_nodes, {"value":""}, True)

  #3. 节点修改
   #A.新建节点
  a = create_node("person", {"age":"15","money":"200000"}, "this is the firest content")
   #B.插入到父节点之下
  add_child_node(result_nodes, a)

  #4. 删除节点
    #定位父节点
  del_parent_nodes = find_nodes(tree, "processers/services/service")
    #准确定位子节点并删除之
  target_del_node = del_node_by_tagkeyvalue(del_parent_nodes, "chain", {"sequency" : "chain1"})

  #5. 修改节点文本
    #定位节点
  text_nodes = get_node_by_keyvalue(find_nodes(tree, "processers/services/service/chain"), {"sequency":"chain3"})
  change_node_text(text_nodes, "new text")

  #6. 输出到结果文件
  write_xml(tree, "./out.xml")

修改后的结果

<?xml version='1.0' encoding='utf-8'?>
<framework>
  <processers>
    <processer file="lib64/A.so" name="AProcesser" path="/tmp">
    </processer>
    <processer age="1" file="lib64/B.so" name="BProcesser">
      <person age="15" money="200000">this is the firest content</person>
    </processer>
    <processer age="1" file="lib64/B.so2222222" name="BProcesser">
      <person age="15" money="200000">this is the firest content</person>
    </processer>

    <services>
      <service name="search" output_formatter="OutPutFormatter:service_inc"
        prefix="/bin/search?">

        <chain sequency="chain2" />
      </service>
      <service name="update" prefix="/bin/update?">
        <chain sequency="chain3" value="fordelete">new text</chain>
      </service>
    </services>
  </processers>
</framework>
Python 相关文章推荐
python cookielib 登录人人网的实现代码
Dec 19 Python
Python 字符串操作实现代码(截取/替换/查找/分割)
Jun 08 Python
利用Python实现网络测试的脚本分享
May 26 Python
详解tensorflow训练自己的数据集实现CNN图像分类
Feb 07 Python
python通过伪装头部数据抵抗反爬虫的实例
May 07 Python
Python 实现中值滤波、均值滤波的方法
Jan 09 Python
python实现五子棋小游戏
Mar 25 Python
Python3+PyInstall+Sciter解决报错缺少dll、html等文件问题
Jul 15 Python
python3使用GUI统计代码量
Sep 18 Python
Python 函数绘图及函数图像微分与积分
Nov 20 Python
python爬虫开发之selenium模块详细使用方法与实例全解
Mar 09 Python
sklearn和keras的数据切分与交叉验证的实例详解
Jun 19 Python
Python通过DOM和SAX方式解析XML的应用实例分享
Nov 16 #Python
Python的Flask开发框架简单上手笔记
Nov 16 #Python
python实现mysql的单引号字符串过滤方法
Nov 14 #Python
浅析Python中signal包的使用
Nov 13 #Python
Python下rrdtool模块的基本使用方法
Nov 13 #Python
简单了解Python下用于监视文件系统的pyinotify包
Nov 13 #Python
Python的pycurl包用法简介
Nov 13 #Python
You might like
PHP4实际应用经验篇(5)
2006/10/09 PHP
function.inc.php超越php
2006/12/09 PHP
学习php笔记 字符串处理
2010/10/19 PHP
解析php中获取url与物理路径的总结
2013/06/21 PHP
PHP查找与搜索数组元素方法总结
2015/06/12 PHP
PHP实现微信退款功能
2018/10/02 PHP
鼠标放在图片上显示大图的JS代码
2013/03/26 Javascript
form表单action提交的js部分与html部分
2014/01/07 Javascript
JavaScript数据库TaffyDB用法实例分析
2015/07/27 Javascript
js-FCC算法-No repeats please字符串的全排列(详解)
2017/05/02 Javascript
值得分享和收藏的xmlplus组件学习教程
2017/05/05 Javascript
Angular4.x通过路由守卫进行路由重定向实现根据条件跳转到相应的页面(推荐)
2018/05/10 Javascript
JavaScript实现封闭区域布尔运算的示例代码
2018/06/25 Javascript
微信小程序wx:for循环的实例详解
2018/10/07 Javascript
Vue + Elementui实现多标签页共存的方法
2019/06/12 Javascript
Jquery实现获取子元素的方法分析
2019/08/24 jQuery
JavaScript canvas绘制折线图
2020/02/18 Javascript
[02:20]2014DOTA2西雅图邀请赛 MVP外卡赛首胜采访
2014/07/09 DOTA
Python多项式回归的实现方法
2019/03/11 Python
Python爬虫使用代理IP的实现
2019/10/27 Python
浅谈css3中calc在less编译时被计算的解决办法
2017/12/04 HTML / CSS
html5的websockets全双工通信详解学习示例
2014/02/26 HTML / CSS
皮肤科医师岗位职责
2013/12/04 职场文书
财务工作个人求职的自我评价
2013/12/19 职场文书
鲜果饮品店创业计划书
2014/01/21 职场文书
模具毕业生推荐信
2014/02/15 职场文书
中学生国旗下讲话稿
2014/04/26 职场文书
我读书我快乐演讲稿
2014/05/07 职场文书
小区门卫岗位职责范本
2014/08/24 职场文书
乡镇群众路线专项整治方案
2014/11/03 职场文书
2015年度企业工作总结
2015/05/21 职场文书
2015年初中教师个人工作总结
2015/07/21 职场文书
学生会宣传部竞选稿
2015/11/21 职场文书
初二数学教学反思
2016/02/17 职场文书
springboot集成springCloud中gateway时启动报错的解决
2021/07/16 Java/Android
Ruby处理YAML和json数据
2022/04/18 Ruby