Python中XML的读写总结

近期项目有用到python处理较多的xml数据,在这里总结下pythonxml的读写方法。在python中,主要有三种方法读写xml:基于DOM,基于ELementTree,基于SAX,这里主要总结前两种方式。

基于DOM

导入: import xml.dom.minidom as minidom

写入

创建文档:
dom = minidom.getDOMImplementation().createDocument(None,'Root',None)
获得根节点:root = dom.documentElement
创建节点:element = dom.createElement('Name')
给这个节点添加文本:element.appendChild(dom.createTextNode('default'))
注意:这里的节点文本值是存成另外一个节点的,是createTextNode
设置属性:element.setAttribute('age', '20')
添加到节点:root.appendChild(element)
完整代码:

# -*- coding:utf-8 -*-
import xml.dom.minidom as minidom
dom = minidom.getDOMImplementation().createDocument(None,'Root',None)
root = dom.documentElement

for i in range(5):
    element = dom.createElement('Name')
    element.appendChild(dom.createTextNode('default'))
    element.setAttribute('age', str(i))
    root.appendChild(element)
# 保存文件
with open('default.xml', 'w', encoding='utf-8') as f:
    dom.writexml(f, addindent='\t', newl='\n',encoding='utf-8')

# 文档内容
<?xml version="1.0" encoding="utf-8"?>
<Root>
    <Name age="0">default</Name>
    <Name age="1">default</Name>
    <Name age="2">default</Name>
    <Name age="3">default</Name>
    <Name age="4">default</Name>
</Root>

读取

读取文档:dom = minidom.parse('default.xml')
获得根节点:root = dom.documentElement
按照名称查找子节点,注意这里会递归查找所有子节点:names = root.getElementsByTagName('Name')
所有的子节点:root.childNodes
注意:每个节点的文本值存在TextNode节点中,也就是最后一个节点的第一个子节点
查看是否含有属性:name.hasAttribute('age')
查看属性:name.getAttribute('age')
完整代码:

dom = minidom.parse('default.xml')
root = dom.documentElement
names = root.getElementsByTagName('Name')
for name in names:
    # 它的第一个子节点是一个textnode,存取的是真正的节点值
    print(name.childNodes[0].nodeValue, end='\t')
    if name.hasAttribute('age'):
        print(name.getAttribute('age'), end='\t')
    print('')
# 输出
default 0   
default 1   
default 2   
default 3   
default 4   

基于ElementTree

导入:import xml.etree.ElementTree as ET

写入

创建节点:root = ET.Element('Root')
创建文档:tree = ET.ElementTree(root)
设置文本值:element.text = 'default'
设置属性:element.set('age', str(i))
添加节点:root.append(element)
写入文档:tree.write('default.xml', encoding='utf-8', xml_declaration=True)

但这样写入会有个问题,写入的XML会在同一行,缺少换行符,Etree本身并没有提供换行的选项,翻看了国外大神的回答,对root处理以后,再次写入将有换行符。完整代码如下:

# -*- coding:utf-8 -*-

import xml.etree.ElementTree as ET
# 增加换行符
def __indent(elem, level=0):
    i = "\n" + level*"\t"
    if len(elem):
        if not elem.text or not elem.text.strip():
            elem.text = i + "\t"
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
        for elem in elem:
            __indent(elem, level+1)
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
    else:
        if level and (not elem.tail or not elem.tail.strip()):
            elem.tail = i

root = ET.Element('Root')       # 创建节点
tree = ET.ElementTree(root)     # 创建文档

for i in range(5):
    element = ET.Element('Name')
    element.set('age', str(i))
    element.text = 'default'
    root.append(element)

__indent(root)          # 增加换行符
tree.write('default.xml', encoding='utf-8', xml_declaration=True)

# 文档内容
<?xml version='1.0' encoding='utf-8'?>
<Root>
    <Name age="0">default</Name>
    <Name age="1">default</Name>
    <Name age="2">default</Name>
    <Name age="3">default</Name>
    <Name age="4">default</Name>
</Root>

读取

读取文档:tree = ET.parse('default.xml')
获得根节点:root = tree.getroot()
获得所有子节点:list(root)
查找子节点,注意这里不会递归查找所有子节点:root.findall('Name')
查找子节点,递归查找所有子节点:root.iter('Name')
查看节点名称:root.tag

全部代码:

# -*- coding:utf-8 -*-

import xml.etree.ElementTree as ET

tree = ET.parse('default.xml')
root = tree.getroot()
for node in list(root):
    print(node.text, node.tag, node.get('age'))

for node in root.findall('Name'):
    print(node.text, node.tag, node.get('age'))

# 输出
default Name 0
default Name 1
default Name 2
default Name 3
default Name 4
default Name 0
default Name 1
default Name 2
default Name 3
default Name 4

如有错误,欢迎指正~

  • 45
    点赞
  • 205
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值