【2】文件读写-2-9-python读写xml

一、创建xml

xml.dom.minidom模块实现创建一个XML文档。

创建XML的过程:

  1. 内存数据产生
  2. 产生xml内存对象(也就是DOM树)
  3. 产生根对象
  4. 往根对象里加数据
  5. 把xml内存对象写到文件

下面是一个创建xml文档的简单实例:

import xml.dom.minidom

#在内存中创建一个空的文档
doc = xml.dom.minidom.Document() 

#创建一个根节点Managers对象
root = doc.createElement('Managers') 

#设置根节点的属性
root.setAttribute('company', 'xx科技') 
root.setAttribute('address', '科技软件园') 
#将根节点添加到文档对象中
doc.appendChild(root) 

managerList = [{'name' : 'joy',  'age' : 27, 'sex' : '女'},
                            {'name' : 'tom', 'age' : 30, 'sex' : '男'},
                            {'name' : 'ruby', 'age' : 29, 'sex' : '女'}
]

for i in managerList :
    nodeManager = doc.createElement('Manager')
    nodeName = doc.createElement('name')
    #给叶子节点name设置一个文本节点,用于显示文本内容
    nodeName.appendChild(doc.createTextNode(str(i['name'])))

    nodeAge = doc.createElement("age")
    nodeAge.appendChild(doc.createTextNode(str(i["age"])))

    nodeSex = doc.createElement("sex")
    nodeSex.appendChild(doc.createTextNode(str(i["sex"])))

    #将各叶子节点添加到父节点Manager中,
    #最后将Manager添加到根节点Managers中
    nodeManager.appendChild(nodeName)
    nodeManager.appendChild(nodeAge)
    nodeManager.appendChild(nodeSex)
    root.appendChild(nodeManager)
#开始写xml文档
fp = open('c:\\wcx\\Manager.xml', 'w')
doc.writexml(fp, indent='\t', addindent='\t', newl='\n', encoding="utf-8")

执行结果: 

<?xml version="1.0" encoding="utf-8"?>
        <Managers address="科技软件园" company="xx科技">
                <Manager>
                        <name>joy</name>
                        <age>27</age>
                        <sex>女</sex>
                </Manager>
                <Manager>
                        <name>tom</name>
                        <age>30</age>
                        <sex>男</sex>
                </Manager>
                <Manager>
                        <name>ruby</name>
                        <age>29</age>
                        <sex>女</sex>
                </Manager>
        </Managers>

参数解析:

writexml(writer, indent, addindent, newl, encoding)

writer是文件对象
indent是每个tag前填充的字符,如:'  ',则表示每个tag前有两个空格
addindent是每个子结点的缩近字符,如下面的例子中单引号中我直接用的tab键
newl是每个tag后填充的字符,如:'\n',则表示每个tag后面有一个回车
encoding是生成的XML信息头中的encoding属性值,在输出时minidom并不真正进行编码的处理,如果你保存的文本内容中有汉字,则需要自已进行编码转换。

二、读xml

xml文件示例:

<?xml version="1.0" encoding="utf-8" ?>
<!-- This is list of customers -->
<customers>
    <customer ID="C001">
        <name>Acme Inc.</name>
        <phone>12345</phone>
        <comments>
            <![CDATA[Regular customer since 1995]]>
        </comments>
    </customer>
    <customer ID="C002">
        <name>Star Wars Inc.</name>
        <phone>23456</phone>
        <comments>
            <![CDATA[A small but healthy company.]]>
        </comments>
    </customer>
</customers>

读的代码:

# -*- coding: utf-8 -*-
"""
        @Author  : LiuZhian
        @Time    : 2019/4/24 0024 上午 9:19
        @Comment : 
"""
from xml.dom.minidom import parse
def readXML():
    domTree = parse("./customer.xml")
    # 文档根元素
    rootNode = domTree.documentElement
    print(rootNode.nodeName)

    # 所有顾客
    customers = rootNode.getElementsByTagName("customer")
    print("****所有顾客信息****")
    for customer in customers:
        if customer.hasAttribute("ID"):
            print("ID:", customer.getAttribute("ID"))
            # name 元素
            name = customer.getElementsByTagName("name")[0]
            print(name.nodeName, ":", name.childNodes[0].data)
            # phone 元素
            phone = customer.getElementsByTagName("phone")[0]
            print(phone.nodeName, ":", phone.childNodes[0].data)
            # comments 元素
            comments = customer.getElementsByTagName("comments")[0]
            print(comments.nodeName, ":", comments.childNodes[0].data)

if __name__ == '__main__':
    readXML()

输出示例:

。。。

三、替换内容

def updateXML():
    domTree = parse("./customer.xml")
    # 文档根元素
    rootNode = domTree.documentElement

    names = rootNode.getElementsByTagName("name")
    for name in names:
        if name.childNodes[0].data == "Acme Inc.":
            # 获取到name节点的父节点
            pn = name.parentNode
            # 父节点的phone节点,其实也就是name的兄弟节点
            # 可能有sibNode方法,我没试过,大家可以google一下
            phone = pn.getElementsByTagName("phone")[0]
            # 更新phone的取值
            phone.childNodes[0].data = 99999

    with open('updated_customer.xml', 'w') as f:
        # 缩进 - 换行 - 编码
        domTree.writexml(f, addindent='  ', encoding='utf-8')

if __name__ == '__main__':
    updateXML()

四、我的内容

4.1 将xml文件拆分成多个文件

domTree = xml.dom.minidom.parse(INPUT)
# 文档根元素
rootNode = domTree.documentElement
customers = rootNode.getElementsByTagName("Sequence")
fpobj_list = []
fpobj_list_raw = []

new_doc = xml.dom.minidom.Document() 
new_root = new_doc.createElement('PredictionResults') 
new_doc.appendChild(new_root) 
num = 0
xml_id = 0
# print(len(customers))

for child in customers:
        num+=1
        new_root.appendChild(child)
        if num >=cut_num :
                num = 0
                xml_id +=1
                # xml_fp = 
                fp = open('%s/tmp-%s.xml'%(resultdir,xml_id), 'w')
                new_doc.writexml(fp, encoding="utf-8") 

                new_doc = xml.dom.minidom.Document() 
                new_root = new_doc.createElement('PredictionResults') 
                new_doc.appendChild(new_root) 

        if num == len(customers):
                xml_id +=1
                fp = open('%s/tmp-%s.xml'%(resultdir,xml_id), 'w')
                new_doc.writexml(fp, encoding="utf-8") 

参考资料

个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn

Sam avatar
About Sam
专注生物信息 专注转化医学