吾八哥学Python(十二):XML数据的解析
上一篇学习了Python里JSON数据的生成与解析,今天来学习Python里的xml格式的数据解析。
XML 指可扩展标记语言(eXtensible Markup Language),标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。XML 标签没有被预定义,您需要自行定义标签,是W3C 的推荐标准。
Python里解析XML数据有如下常用的几种方法SAX,DOM,以及ElementTree,通过一些网络资料查询得知ElementTree应该是效率最好的一种方式,所以这里我暂时只学习ElementTree的解析方法,以后再去接触学习另外两种解析方式。
数据样本:
<?xml version="1.0" encoding="utf-8"?> <root> <userinfo> <username>5bug</username> <password>123456</password> <web>www.5bug.wang</web> </userinfo> <servers name="上海服务器"> <server ip="192.168.1.101" port="8881"/> <server ip="192.168.1.102" port="8882"/> <server ip="192.168.1.103" port="8883"/> </servers> </root>
解析方法:
ElementTree读取xml文件方法为parse(),读取xml字符串的方法为fromstring()
ElementTree获取节点的方法为:
1.获得指定节点->getiterator()方法
2.获得指定节点->findall()方法
3.获得指定节点->find()方法
4.获得子节点->getchildren()
5.读取节点文本值为text
6.获取节点的属性值为attrib[]
7.判断节点某个属性是否存在为attrib.has_key()
练习代码:
代码如下:
from xml.etree import ElementTree as ET def read_xml(filename): root = ET.parse(filename) userinfo = root.find('userinfo') for child in userinfo.getchildren(): print(child.text) servers = root.find('servers') print(servers.attrib['name']) for child in servers.getchildren(): print(child.attrib) if __name__ == '__main__': read_xml(r'C:/Users/5bug.wang/Desktop/test.xml')
执行结果:
5bug 123456 www.5bug.wang 上海服务器 {'ip': '192.168.1.101', 'port': '8881'} {'ip': '192.168.1.102', 'port': '8882'} {'ip': '192.168.1.103', 'port': '8883'}
XML里的一些信息都读取出来了,还是比较简单。
XML命名空间
下面再看一个解析XML的时候经常会遇到的一个问题,解析指定了XML命名空间的XML文件。样例文本就拿本站的网站地图文件吧,可以通过https://5bug.wang/sitemap.xml获取。带有命名空间的XML文件通过ElementTree解析的话在读取节点的时候需要指定命名空间,否则会无法读取到,之前遇到过这个坑,哈哈!通过各种查询找到了解决方法。具体解析代码如下:
# Autor: 5bug # WebSite: http://www.5bug.wang # 吾八哥网技术交流QQ群: 643829693 import re from xml.etree import ElementTree as ET #读取命名空间 def get_namespace(element): m = re.match('\{.*\}', element.tag) return m.group(0) if m else '' #解析node信息 def read_node(node): for child in node.getchildren(): print(child.text) #解析xml def read_xml(filename): root = ET.parse(filename) namespace = get_namespace(root.getroot()) list = root.getiterator(namespace + 'url') for node in list: read_node(node) if __name__ == '__main__': read_xml(r'C:/Users/5bug.wang/Desktop/sitemap.xml')
本文首发学Python网:http://www.xuepython.wang