python笔记:常用内建模块—XML

一、DOM vs SAX

操作XML有两种方法:DOM和SAX。DOM会把整个XML读入内存,解析为树,因此占用内存大,解析慢,优点是可以任意遍历树的节点。SAX是流模式,边读边解析,占用内存小,解析快,缺点是我们需要自己处理事件

优先考虑SAX,因为DOM实在太占内存

二、使用SAX解析XML

需准备好这3个函数:start_element,end_element和char_data,就可开始解析XML。

举例,当SAX解析器读到一个节点时:

<a href="/">python</a>

产生三个事件:

1、start_element事件,在读取<a href="/">时;

2、char_data事件,在读取python时;

3、end_element事件,在读取</a>时。

解析一段xml的代码:

from xml.parsers.expat import ParserCreate

class DefaultSaxHandler(object):
    def start_element(self, name, attrs):
        print('sax:start_element: %s, attrs: %s' % (name, str(attrs)))

    def end_element(self, name):
        print('sax:end_element: %s' % name)

    def char_data(self, text):
        print('sax:char_data: %s' % text)

xml = r'''<?xml version="1.0"?>
<ol>
    <li><a href="/python">Python</a></li>
    <li><a href="/ruby">Ruby</a></li>
</ol>
'''

handler = DefaultSaxHandler()
parser = ParserCreate()
parser.StartElementHandler = handler.start_element
parser.EndElementHandler = handler.end_element
parser.CharacterDataHandler = handler.char_data
parser.Parse(xml)

直接解析xml的步骤:

1、准备一段xml的代码,待解析

xml = r'''<?xml version="1.0"?>
<ol>
    <li><a href="/python">Python</a></li>
    <li><a href="/ruby">Ruby</a></li>
</ol>
'''

2、定义DefaultSaxHandler类,类中定义三个方法分别用于解析标签开头、标签内内容、标签结尾

 class DefaultSaxHandler(object)
    def start_element(self, name, attrs):
        print('sax:start_element: %s, attrs: %s' % (name, str(attrs)))
    def end_element(self, name)
        print('sax:start_element: %s, attrs: %s' % (name, str(attrs)))
    def char_data(self, text):
        print('sax:char_data: %s' % text)

3、使用DefaultSaxHandler( )创建DefaultSaxHander ( )

handler=DefaultSaxHandler( ) # 创建DefaultSaxHandler()对象

4、使用ParserCreate( )创建xml解析器

parser=ParserCreate( )  #创建 XML 解析器。该函数建立一个新的 XML 解析器并返回可被其它 XML 函数使用的资源句柄

5、分别调用handler的三个方法,并将返回值赋给对应的parser.ElementHandler

parser.StartElementHandler=handler.start_element #调用handler的start_element方法,并将返回值赋给parser.StartElementHandler

parser.EndElementHandler=handler.end_element #调用handler的end_element方法,并将返回值赋给EndElementHandler

parser.CharacterDataHandler=handler.char_data #调用handler的char_data方法,并将返回值赋给CharacterDataHandler

6、最后调用parse()传入xml参数,从而进行解析

parser.Parse(xml)   

运行:


三、生成xml

除了解析XML外,如何生成XML呢?99%的情况下需要生成的XML结构都是非常简单的,因此,最简单也是最有效的生成XML的方法是拼接字符串:

L = []
L.append(r'<?xml version="1.0"?>')
L.append(r'<root>')
L.append(encode('some & data'))
L.append(r'</root>')

return ''.join(L)

join()函数的用法 :https://www.cnblogs.com/jsplyy/p/5634640.html

如果要生成复杂的XML呢?建议你不要用XML,改成JSON。附:JSON与XML的区别比较  https://www.cnblogs.com/lsohvaen001/p/7887502.html

总结:解析XML时,注意找出自己感兴趣的节点,响应事件时,把节点数据保存起来解析完毕后,就可以处理数据。

四、练习

题目:


代码 :

from xml.parsers.expat import ParserCreate
from urllib import request
parse_dict = {}
class DefaultSaxHandler(object):
    def start_element(self, name, attrs):
        if name == 'yweather:location':
            parse_dict['city'] = attrs['city']

def parseXml(xml_str):
    print(xml_str + '\n')
    handler = DefaultSaxHandler()
    parser = ParserCreate()
    parser.StartElementHandler = handler.start_element
    parser.Parse(xml_str)
    return parse_dict
# 测试:
URL = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20%3D%202151330&format=xml'
with request.urlopen(URL, timeout=4) as f:
    data = f.read()
result = parseXml(data.decode('utf-8'))
assert result['city'] == 'Beijing'
 
print('ok')

运行:


解析url所指向内容的步骤:

1、准备一个url

URL = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20%3D%202151330&format=xml'

2、打开并读入url内容

with request.urlopen(URL, timeout=4) as f:
    data = f.read()

3、定义DefaultSaxHandler类,设置响应事件,注意找出自己感兴趣的节点,把节点数据保存起来

class DefaultSaxHandler(object):  #定义DefaultSaxHandler类
    def start_element(self, name, attrs):  #设置响应事件
        if name == 'yweather:location': #自己感兴趣的节点
            parse_dict['city'] = attrs['city']  #把节点数据(即yweather:location标签的city属性值)保存到全局变量parse_dict的city值

4、定义函数 parseXml用于解析xml文件

def parseXml(xml_str):
    print(xml_str + '\n')
    handler = DefaultSaxHandler() #创建DefaultSaxHandler对象handler
    parser = ParserCreate() #创建解析器
    parser.StartElementHandler = handler.start_element #调用start_element方法,爆粗将节点数据
    parser.Parse(xml_str) 解析url的内容xml_str
    return parse_dict 返回保存了节点数据的全局变量parse_dict

5、调用函数parseXml()进行解析xml内容

result = parseXml(data.decode('utf-8')) #将返回值赋给result
assert result['city'] == 'Beijing' #使用断言看result的city属性值是否为'beijing' 
 
print('ok') #运行完毕打印ok


猜你喜欢

转载自blog.csdn.net/zyckhuntoria/article/details/81033972