吾八哥博客

您现在的位置是:首页 > 码农手记 > Python > 正文

Python

吾八哥学Python(十二):XML数据的解析

吾八哥2017-07-21Python5880

上一篇学习了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