详解在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 从远程服务器下载日志文件的程序
Feb 10 Python
pymongo给mongodb创建索引的简单实现方法
May 06 Python
Python入门学习之字符串与比较运算符
Oct 12 Python
Python中的复制操作及copy模块中的浅拷贝与深拷贝方法
Jul 02 Python
python中常用的九种预处理方法分享
Sep 11 Python
Python 函数返回值的示例代码
Mar 11 Python
windows安装TensorFlow和Keras遇到的问题及其解决方法
Jul 10 Python
django用户登录验证的完整示例代码
Jul 21 Python
Python Django 页面上展示固定的页码数实现代码
Aug 21 Python
python绘制彩虹图
Dec 16 Python
win10下opencv-python特定版本手动安装与pip自动安装教程
Mar 05 Python
Python描述符descriptor使用原理解析
Mar 21 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和mysql中uft-8中文编码乱码的几种解决办法
2012/04/19 PHP
WordPress主题制作之模板文件的引入方法
2015/12/28 PHP
详解PHP的Yii框架中的Controller控制器
2016/03/29 PHP
php 计算两个时间相差的天数、小时数、分钟数、秒数详解及实例代码
2016/11/09 PHP
CI框架(CodeIgniter)操作redis的方法详解
2018/01/25 PHP
laravel框架学习笔记之组件化开发实现方法
2020/02/01 PHP
指定js可访问其它域名的cookie的方法
2007/09/18 Javascript
用js遍历 table的脚本
2008/07/23 Javascript
javascript GUID生成器实现代码
2009/10/31 Javascript
UI Events 用户界面事件
2012/06/27 Javascript
Extjs4.0设置Ext.data.Store传参的请求方式(默认为GET)
2013/04/02 Javascript
Jquery:ajax实现翻页无刷新功能代码
2013/08/05 Javascript
JS实现从表格中动态删除指定行的方法
2015/03/31 Javascript
三种Node.js写文件的方式
2016/03/08 Javascript
JS编写函数实现对身份证号码最后一位的验证功能
2016/12/29 Javascript
thinkphp标签实现bootsrtap轮播carousel实例代码
2017/02/19 Javascript
利用vue+elementUI实现部分引入组件的方法详解
2017/11/22 Javascript
Nodejs中crypto模块的安全知识讲解
2018/01/03 NodeJs
JavaScript求一个数组中重复出现次数最多的元素及其下标位置示例
2018/07/23 Javascript
bootstrap自定义样式之bootstrap实现侧边导航栏功能
2018/09/10 Javascript
Vue axios设置访问基础路径方法
2018/09/19 Javascript
es6数组的flat(),flatMap()函数用法实例分析
2020/04/18 Javascript
js实现滑动进度条效果
2020/08/21 Javascript
Vue 简单实现前端权限控制的示例
2020/12/25 Vue.js
Python实现提取谷歌音乐搜索结果的方法
2015/07/10 Python
python浪漫表白源码
2019/04/05 Python
DJango的创建和使用详解(默认数据库sqlite3)
2019/11/18 Python
Python3实现个位数字和十位数字对调, 其乘积不变
2020/05/03 Python
详解如何在登录过期后跳出Ifram框架
2020/09/10 HTML / CSS
iHerb俄罗斯:维生素、补品和天然产品
2020/07/09 全球购物
学员自我鉴定
2014/03/19 职场文书
竞争上岗实施方案
2014/03/21 职场文书
公务员考察材料
2014/12/23 职场文书
学校食堂食品安全承诺书
2015/04/29 职场文书
信仰观后感
2015/06/03 职场文书
傲慢与偏见读书笔记
2015/06/29 职场文书