python---XML的快速入门

前言

XML的解析方法有很多,但是本教程值介绍xml.etree.cElementTree的解析方法
因为它使用C语言实现,因为它的速度要快很多,而且内存消耗也要少很多。所以
学这个方法就够了。

什么是XML?

将XML文档解析为树(tree)
我们先从基础讲起。XML是一种结构化、层级化的数据格式,最适合体现XML的数据结构就是树。ET提供了两个对象:ElementTree将整个XML文档转化为树,Element则代表着树上的单个节点。对整个XML文档的交互(读取,写入,查找需要的元素),一般是在ElementTree层面进行的。对单个XML元素及其子元素,则是在Element层面进行的。下面我们举例介绍主要使用方法。

我们使用下面的XML文档,作为演示数据:

<?xml version="1.0"?>
<doc>
    <branch name="codingpy.com" hash="1cdf045c">
        text,source
    </branch>
    <branch name="release01" hash="f200013e">
        <sub-branch name="subrelease01">
            xml,sgml
        </sub-branch>
    </branch>
    <branch name="invalid">
        <sub-branch name="helloworld" hash="4242">
            哈哈哈
        </sub-branch>
    </branch>
</doc>

树的结构
树的结构

XML文档—-读操作

import xml.etree.cElementTree as ET
xml = ET.ElementTree(file='xmltest.xml')

获取根节点

root = xml.getroot()

获取了根节点,我们来看看根节点的信息

print(root.tag,root.attrib)
输出:
doc {}

一个节点的信息包括三个部分:tag attrib text
根节点是一个特殊的节点,所以它只有tag
以下面的节点为例:

branch {'name': 'codingpy.com', 'hash': '1cdf045c'} 
        text,source
tag = branch
attrib = {'name': 'codingpy.com', 'hash': '1cdf045c'}
text = text,source

查看子节点信息

这里我们来看看根节点的子节点信息

for child in root:
    print(child.tag,child.attrib,child.text)
输出:
branch {'name': 'codingpy.com', 'hash': '1cdf045c'} 
        text,source

branch {'name': 'release01', 'hash': 'f200013e'} 

branch {'name': 'invalid'} 

可以看到输出了root节点下面的三个branch节点,第一个branch是有text,而其他两个没有text信息

通过索引访问节点

son = root[1][0]
print(son.tag,son.attrib,son.text)
输出:
sub-branch {'name': 'subrelease01'} 
            xml,sgml

当然,要通过索引的方式访问节点,我们必须清楚地知道树的结构。

遍历整个XML树

for elem in root.iter():
    print(elem.tag,elem.attrib,elem.text)
输出:
doc {} 

branch {'name': 'codingpy.com', 'hash': '1cdf045c'} 
        text,source

branch {'name': 'release01', 'hash': 'f200013e'} 

sub-branch {'name': 'subrelease01'} 
            xml,sgml

branch {'name': 'invalid'} 

sub-branch {'name': 'helloworld', 'hash': '4242'} 
            哈哈哈

注意,这里的root.iter( )其实返回的是一个迭代器

遍历指定的节点

for elem2 in root.iter(tag = 'sub-branch'):
    print(elem2.tag,elem2.attrib,elem2.text)
输出:
sub-branch {'name': 'subrelease01'} 
            xml,sgml

sub-branch {'name': 'helloworld', 'hash': '4242'} 
            哈哈哈

这里找出了所有tag = ‘sub-branch’的节点
root.iter( )的函数声明

def iter(self, tag=None):

所以,这里的遍历指定节点只能指定tag

按路径查找第一个匹配的子节点

函数声明:
find(path, namespaces=None) method of xml.etree.ElementTree.Element instance

需要手动输入路径

elem3 = root.find('branch/sub-branch')
print(elem3.tag,elem3.attrib,elem3.text)
输出:
sub-branch {'name': 'subrelease01'} 
            xml,sgml

按路径查找所有匹配的节点

遍历迭代器方式:

声明:def iterfind(self, path, namespaces=None):
for elem4 in root.iterfind('branch/sub-branch'):
    print(elem4.tag,elem4.attrib,elem4.text)
输出:
sub-branch {'name': 'subrelease01'} 
            xml,sgml

sub-branch {'name': 'helloworld', 'hash': '4242'} 
            哈哈哈

遍历列表方式:

声明:def findall(self, path, namespaces=None):
for elem5 in root.findall('branch/sub-branch'):
    print(elem5.tag,elem5.attrib,elem5.text)
输出:
sub-branch {'name': 'subrelease01'} 
            xml,sgml

sub-branch {'name': 'helloworld', 'hash': '4242'} 
            哈哈哈

遍历条件具体到属性attrib (路径+属性)

for elem6 in root.iterfind('branch/sub-branch[@name="helloworld"]'):
    print(elem6.tag,elem6.attrib,elem6.text)
输出:
sub-branch {'name': 'helloworld', 'hash': '4242'} 
            哈哈哈

findall( )用法也一样。
findall()和iterfind()作用都一样,只不过前者返回列表,后者返回的迭代器。也是说前者可以进行索引,后者不能够索引。

XML文档—写操作

增加节点属性

声明:

def set(self, key, value):
elem = root.find('branch')
elem.set('haha','hehe')
print(elem.tag,elem.attrib,elem.text)
elem2 = root.find('branch')
print(elem2.tag,elem2.attrib,elem2.text)
输出:branch {'name': 'codingpy.com', 'hash': '1cdf045c', 'haha': 'hehe'} 
        text,source

branch {'name': 'codingpy.com', 'hash': '1cdf045c', 'haha': 'hehe'} 
        text,source

修改节点信息

elem = root.find('branch/sub-branch')
elem.tag = 'test-branch'
elem.attrib = {'name':'test','hash':'123'}
elem.text = '\n这只是一个测试\n'
print(elem.tag,elem.attrib,elem.text)
输出:
test-branch {'name': 'test', 'hash': '123'} 
这只是一个测试

现在修改之后,我们需要保存至文件,才能够永久的保存,不然只是保存在内存里面。

写入信息到xml文件

声明:

write(file_or_filename, encoding=None, xml_declaration=None, default_namespace=None, method=None, *, short_empty_elements=True) method of xml.etree.ElementTree.ElementTree instance

一句话即可

xml.write('xmltest.xml')

构建一个XML文档

a1 = ET.Element('elem')#创建节点
b1 = ET.SubElement(a1,'elem2')#创建某个节点的子节点
b2 = ET.SubElement(a1,'elem2')
b2.text = 'I love you'#添加正文
a2 = ET.Element('elem')
root = ET.Element('root')#创建根节点
root.extend((a1,a2))#把a1,a2添加到根节点
tree = ET.ElementTree(root)#根据根节点创建树
tree.write('treexml.xml')#写入到xml文档
for t in tree.iter():
    print(t.tag,t.attrib,t.text)
xml文档:
<root>
    <elem>
        <elem2 />
        <elem2>
            I love you
        </elem2>
    </elem>
    <elem />
</root>

本文有待更新,之后会添加更多的使用方法。

猜你喜欢

转载自blog.csdn.net/tobe_numberone/article/details/80930748