Python使用ElementTree美化XML格式的操作


Posted in Python onMarch 06, 2020

Python中使用ElementTree可以很方便的处理XML,但是产生的XML文件内容会合并在一行,难以看清楚。

如下格式:

<root><aa>aatext<cc>cctext</cc></aa><bb>bbtext<dd>ddtext<ee>eetext</ee></dd></bb></root>

使用minidom模块中的toprettyxml和writexml方法都有参数可以优化XML,但是有两个问题:

a. 如果解析的XML已经是美化过的,那么执行该方法会多出很多空行

b. 产生的结果会将text也独立一行,如下:

<root> 
  <aa> 
    aatext 
  </aa> 
  <bb> 
    bbtext 
  </bb> 
</root>

而我想产生如下结果:

<root> 
  <aa>aatext</aa> 
  <bb>bbtext</bb> 
</root>

于是只能自己写一个美化XML的方法。

我们首先研究一下ElementTree模块中的Element类,使用getroot方法返回的便是Element类。

该类中有四个属性tag、attrib、text与tail, 对应在XML中如下图所示:

Python使用ElementTree美化XML格式的操作

整个XML就是一个Element,里面嵌套了很多子Element。

Element可以使用for循环迭代。

通过在text和tail中增加换行和制表符,就可以实现美化XML的目的。

美化代码如下:

def prettyXml(element, indent, newline, level = 0): # elemnt为传进来的Elment类,参数indent用于缩进,newline用于换行 
  if element: # 判断element是否有子元素 
    if element.text == None or element.text.isspace(): # 如果element的text没有内容 
      element.text = newline + indent * (level + 1)  
    else: 
      element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * (level + 1) 
  #else: # 此处两行如果把注释去掉,Element的text也会另起一行 
    #element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * level 
  temp = list(element) # 将elemnt转成list 
  for subelement in temp: 
    if temp.index(subelement) < (len(temp) - 1): # 如果不是list的最后一个元素,说明下一个行是同级别元素的起始,缩进应一致 
      subelement.tail = newline + indent * (level + 1) 
    else: # 如果是list的最后一个元素, 说明下一行是母元素的结束,缩进应该少一个 
      subelement.tail = newline + indent * level 
    prettyXml(subelement, indent, newline, level = level + 1) # 对子元素进行递归操作 
     
from xml.etree import ElementTree   #导入ElementTree模块 
tree = ElementTree.parse('test.xml')  #解析test.xml这个文件,该文件内容如上文 
root = tree.getroot()         #得到根元素,Element类 
prettyXml(root, '\t', '\n')      #执行美化方法 
ElementTree.dump(root)         #显示出美化后的XML内容

输出结果如下:

<root> 
  <aa> 
    aatext 
    <cc>cctext</cc> 
  </aa> 
  <bb> 
    bbtext 
    <dd> 
      ddtext 
      <ee>eetext</ee> 
    </dd> 
  </bb> 
</root>

残留问题点:

windows下的换行符是"\r\n",只需将prettyXml方法的第三个参数改为"\r\n",使用记事本打开生成的XML大部分OK。

但是XML说明与根元素开始符之间不知如何插入"\r\n".

Python使用ElementTree美化XML格式的操作

补充知识:python-xml 模块-代码生成xml 文档

一、XML 模块

什么是xml:可扩展的标记语言,标记翻译为标签,用标签来组织数据的语言,也是一种语言可以用来自定义文档结构。相比json 使用场景更加广泛,但是语法格式相比json 复杂很多

什么时候使用json:前后台交互数据时使用json

什么时候使用xml:当需要自定义文档结构时使用xml,比如java中经常用xml来作为配置文件,常见操作就是通过程序去读取配置信息,而修改增加删除,一般是交给用户来手动完成

标签的叫发:node(节点)、elment(元素)、tag(标签)

需求从conuntrys中获取所有的国家名称

==========================>countrys
<data>
  <country name="Liechtenstein">
    <rank updated="yes">2</rank>
    <year>2009</year>
    <gdppc>141100</gdppc>
    <neighbor direction="E" name="Austria" />
    <neighbor direction="W" name="Switzerland" />
  </country>
  <country name="Singapore">
    <rank updated="yes">5</rank>
    <year>2012</year>
    <gdppc>59900</gdppc>
    <neighbor direction="N" name="Malaysia" />
  </country>
  <country name="Panama">
    <rank updated="yes">69</rank>
    <year>2012</year>
    <gdppc>13600</gdppc>
    <neighbor direction="W" name="Costa Rica" />
    <neighbor direction="E" name="Colombia" />
  </country>
</data># 取别名可以用于简化书写
import xml.etree.ElementTree as ET
tree = ET.parse('countrys')
#获取根标签#第一种获取标签的方式
#全文查找
iter() 
# 获取迭代器 如果不指定参数 则迭代器迭代的是所有标签
print(root.iter())
# 获取迭代器 如果指定参数 则迭代器迭代的是所有名称匹配的标签
for e in root.iter("rank"):
  print(e)
 
#第二种获取标签的方式
#在当前标签下(所有子级标签)寻找第一个名称匹配的标签
print(root.find("rank")) #第一个名称不匹配所以返回None#第三种获取标签的方式
#在当前标签下(所有子级标签)寻找所有名称匹配的标签
print(root.findall("rank")) #[]

练习:找到新加坡中year 这个标签

#print(e.tag) #标签名称
#print(e.attrib) #属性 字典类型
#print(e.text) #文本内容import xml.etree.ElementTree as ETtree = ET.parse("countrys")
# 获取根标签
root = tree.getroot()
for e in root.iter("country"):
  if e.attrib["name"] == "Singapore":
    y = e.find("year")
    print(y.text) #2012

在程序中修改文档内容:把所有year标签的文本加1

import xml.etree.ElementTree as ETtree = ET.parse("countrys")
root = tree.getroot()
for e in root.iter("year"):
  e.text = str(int(e.text) + 1)
  
#做完修改后要将修改后的内容写入文件
tree.write('countrys')

把新加坡国家删除:

import xml.etree.ElementTree as ETtree = ET.parse("countrys")
root = tree.getroot()for e in root.findall("country"):
  print(e)
  if e.attrib["name"] == "Singapore":
    #删除时要通过被删除的父级标签来删除
    root.remove(e)tree.write('countrys')

用程序将中国信息写入文档中:

import xml.etree.ElementTree as ETtree = ET.parse("countrys")
root = tree.getroot()
#添加时也需要将要添加的数据做成一个Element
c = ET.Element("country",{"name":"china"})# 在国家下有一堆子标签
ranke = ET.Element("ranke",{"updated":"yes"})
c.append(ranke)year = ET.Element("year")
year.text = "2018"
c.append(year)#添加到root标签中
root.append(c)
tree.write("countrys")

总结:一般不会通过程序 去修改 删除 和添加

什么时候应该使用XML格式:

当你需要自定文档结构时(XML最强大的地方就是结构)

前后台交互不应该使用,前后台交互应该使用JSON格式

代码生成XML文档

import xml.etree.ElementTree as ET# 创建根标签
root = ET.Element("root")
root.text = "这是一个XML文档!"c = ET.Element("country",{"name":"china"})
root.append(c)tree = ET.ElementTree(root)
# 参数: 文件名称 编码方式 是否需要文档声明
tree.write("new.xml",encoding="utf-8",xml_declaration=True)=========================>new.xml 内容为
<?xml version='1.0' encoding='utf-8'?>
<root>这是一个XML文档!<country name="china" /></root>

以上这篇Python使用ElementTree美化XML格式的操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python多线程用法实例详解
Jan 15 Python
Python如何import文件夹下的文件(实现方法)
Jan 24 Python
初学python的操作难点总结(新手必看篇)
Aug 03 Python
使用Python+Splinter自动刷新抢12306火车票
Jan 03 Python
Win8下python3.5.1安装教程
Jul 29 Python
Python使用微信接入图灵机器人过程解析
Nov 04 Python
python去除删除数据中\u0000\u0001等unicode字符串的代码
Mar 06 Python
keras输出预测值和真实值方式
Jun 27 Python
Python pip使用超时问题解决方案
Aug 03 Python
基于python requests selenium爬取excel vba过程解析
Aug 12 Python
python开发一款翻译工具
Oct 10 Python
python 如何做一个识别率百分百的OCR
May 29 Python
Python使用requests xpath 并开启多线程爬取西刺代理ip实例
Mar 06 #Python
Python 批量读取文件中指定字符的实现
Mar 06 #Python
python GUI库图形界面开发之PyQt5布局控件QGridLayout详细使用方法与实例
Mar 06 #Python
python3 xpath和requests应用详解
Mar 06 #Python
python 装饰器功能与用法案例详解
Mar 06 #Python
python GUI库图形界面开发之PyQt5布局控件QVBoxLayout详细使用方法与实例
Mar 06 #Python
利用 Python ElementTree 生成 xml的实例
Mar 06 #Python
You might like
php通过前序遍历树实现无需递归的无限极分类
2015/07/10 PHP
PHP使用trim函数去除字符串左右空格及特殊字符实例
2016/01/07 PHP
Yii2 rbac权限控制之菜单menu实例教程
2016/04/28 PHP
js类 from qq
2006/11/13 Javascript
GWT中复制到剪贴板 js+flash实现复制 兼容性比较好
2010/03/07 Javascript
javaScript 动态访问JSon元素示例代码
2013/08/30 Javascript
JavaScript验证Email(3种方法)
2015/09/21 Javascript
JavaScript中eval函数的问题
2016/01/31 Javascript
JavaScript算法系列之快速排序(Quicksort)算法实例详解
2016/09/04 Javascript
详解vue-validator(vue验证器)
2017/01/16 Javascript
修改 bootstrap table 默认detailRow样式的实例代码
2017/07/21 Javascript
原生js封装添加class,删除class的实例
2017/11/06 Javascript
基于vue中css预加载使用sass的配置方式详解
2018/03/13 Javascript
react中fetch之cors跨域请求的实现方法
2018/03/14 Javascript
工作中常用到的ES6语法
2018/09/04 Javascript
浅谈发布订阅模式与观察者模式
2019/04/09 Javascript
关于vue.js中实现方法内某些代码延时执行
2019/11/14 Javascript
Element-UI+Vue模式使用总结
2020/01/02 Javascript
详解Vue3 Composition API中的提取和重用逻辑
2020/04/29 Javascript
Python开发常用的一些开源Package分享
2015/02/14 Python
Python的标准模块包json详解
2017/03/13 Python
python执行使用shell命令方法分享
2017/11/08 Python
Python各类图像库的图片读写方式总结(推荐)
2018/02/23 Python
python模块导入的方法
2019/10/24 Python
python不同版本的_new_不同点总结
2020/12/09 Python
深入理解css属性的选择对动画性能的影响
2016/04/20 HTML / CSS
Mankind美国/加拿大:英国领先的男士美容护发用品公司
2018/12/05 全球购物
Herschel美国官网:背包、手提袋及配件
2020/03/10 全球购物
如何清空Session
2015/02/23 面试题
高级销售员求职信
2013/10/25 职场文书
公司节能减排方案
2014/05/16 职场文书
2014年医药代表工作总结
2014/11/22 职场文书
2014年质检工作总结
2014/11/26 职场文书
中学生社会实践教育活动总结
2015/05/06 职场文书
工作调动申请报告
2015/05/18 职场文书
医务人员岗前培训心得体会
2016/01/08 职场文书