详解在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自然语言编码转换模块codecs介绍
Apr 08 Python
Python中生成器和yield语句的用法详解
Apr 17 Python
Python中optparser库用法实例详解
Jan 26 Python
使用anaconda的pip安装第三方python包的操作步骤
Jun 11 Python
Python3多线程基础知识点
Feb 19 Python
django Admin文档生成器使用详解
Jul 22 Python
Python的赋值、深拷贝与浅拷贝的区别详解
Feb 12 Python
Python+OpenCV实现图像的全景拼接
Mar 05 Python
Python 如何查找特定类型文件
Aug 17 Python
python 5个顶级异步框架推荐
Sep 09 Python
python turtle绘制多边形和跳跃和改变速度特效
Mar 16 Python
python APScheduler执行定时任务介绍
Apr 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
PHP 图片上传代码
2011/09/13 PHP
eaglephp使用微信api接口开发微信框架
2014/01/09 PHP
php根据操作系统转换文件名大小写的方法
2014/02/24 PHP
再谈PHP中单双引号的区别详解
2016/06/12 PHP
php版微信公众平台入门教程之开发者认证的方法
2016/09/26 PHP
php实现将HTML页面转换成word并且保存的方法
2016/10/14 PHP
thinkPHP框架自动填充原理与用法分析
2018/04/03 PHP
php封装的page分页类完整实例代码
2020/02/01 PHP
jqPlot Option配置对象详解
2009/07/25 Javascript
JSQL 基于客户端的成绩统计实现方法
2010/05/05 Javascript
Jquery实现的tab效果可以指定默认显示第几页
2013/10/16 Javascript
一个简单的实现下拉框多选的插件可移植性比较好
2014/05/05 Javascript
详解Javascript 装载和执行
2014/11/17 Javascript
jquery捕捉回车键及获取checkbox值与异步请求的方法
2015/12/24 Javascript
JavaScript进阶练习及简单实例分析
2016/06/03 Javascript
jQuery实现页面点击后退弹出提示框的方法
2016/08/24 Javascript
js实现小窗口拖拽效果
2016/12/03 Javascript
实例教学如何写vue插件
2017/11/30 Javascript
Angular 数据请求的实现方法
2018/05/07 Javascript
微信小程序登录换取token的教程
2018/05/31 Javascript
webpack 开发和生产并行设置的方法
2018/11/08 Javascript
vuejs数据超出单行显示更多,点击展开剩余数据实例
2019/05/05 Javascript
在Django框架中伪造捕捉到的URLconf值的方法
2015/07/18 Python
python程序中的线程操作 concurrent模块使用详解
2019/09/23 Python
pytorch下大型数据集(大型图片)的导入方式
2020/01/08 Python
Python列表如何更新值
2020/05/27 Python
开发人员所需要知道的HTML5性能分析面面观
2012/07/05 HTML / CSS
经济实惠的豪华家具:My-Furniture
2019/03/12 全球购物
机关门卫制度
2014/02/01 职场文书
导游个人求职信
2014/04/25 职场文书
软环境建设心得体会
2014/09/09 职场文书
幼儿园小朋友毕业感言
2015/07/30 职场文书
小学生红领巾广播稿
2015/08/19 职场文书
2016春季小学开学寄语
2015/12/03 职场文书
数据结构课程设计心得体会
2016/01/15 职场文书
python实现三阶魔方还原的示例代码
2021/04/28 Python