python对XML的解析总结

5 篇文章 0 订阅

转载了这么多的文章,终于可以写一点自己的东西了。初学Python不久,程序中不当之处还请各位看官不吝赐教。

本文中很多地方都是参考了其他人的博文,具体的也不甚清楚到底参考了哪些,在此仅列出一个大概吧。绿色背景表示含有链接。

感谢gaodeyue,他的例程写的很好。我直接参考了他的DOM构建和解析XML文档的程序写了一个我自己的XML文档。另外的那篇Python处理XML数据之SAX我想也还不错,不过现在觉得还是没必要学,时间又稍微有点紧,所以先不弄了,转载过来好了。其实想写这篇博文也是因为看了他的Python处理XML数据之DOM篇才有这个想法的。非常感谢。

感谢yueguanghaidao,在网上游荡了好久,发现用ElementTree来解析XML文档的很多,但是用ElementTree来生成XML文件的真滴不多,而且很杂乱,然后我就找到了yueguanghaidao的这篇博文,参照着把ElementTree生成XML文档的程序给写出来了。同样非常感谢。本博文的第二大段文字“Python有三种方法解析XML”亦是来自于yueguanhaidao在此再次表示感谢。

感谢大CC,引用了他写的美化程序,非常的好用,非常谢谢!

注:我所使用的Python版本为2.7.3

Python提供了两种XML支持:

第一种是支持两种XML解析的行业标准方法——SAX和DOM 。 SAX(Simple API for XML ,用于XML的简单API)以事件处理为基础,按照遇到XML元素的顺序读取XML文档,触发处理函数来执行处理。DOM (Document Object Model ,文档对象模型)构建表示整个XML文档的树结构。树结构构建完成后, DOM将提供一个遍历树和提取数据的接口。SAX和DOM API都不是源自Python ,Python只是复制了为Java和JavaScript开发的接口。


第二种是支持特定于Python的XML解析方住。尽管可以使用SAX和DOM接口处理XML ,但是标准库中最方便的编程接口还是ElementTree接口。这种方住充分利用了Python的语言特点,大部分用户发现它比SAX或DOM要更加简单快捷。本文将讨论这3 种XML解析方法,重点讨论ElementTree方法。
这里建议读者只关注基本的XML数据解析。Python还包括与实现新类型解析、从头构建XML文档等方面有关的XML模块。此外,各种第三方扩展插件扩展了Python的功能,添加了其他XML功能,如支持XSLT和XPATH。更多信息的链接,请参见http://wiki.python.org/moin/PythonXml

python有三种方法解析XML:SAX、DOM以及ElementTree

1.SAX (simple API for XML )
pyhton 标准库包含SAX解析器,SAX是一种典型的极为快速的工具,在解析XML时,不会占用大量内存。但是这是基于回调机制的,因此在某些数据中,它会调用某些方法进行传递。这意味着必须为数据指定句柄,以维持自己的状态,这是非常困难的。

2.DOM(Document Object Model)
与SAX比较,DOM典型的缺点是比较慢,消耗更多的内存,因为DOM会将整个XML数读入内存中,并为树中的第一个节点建立一个对象。使用DOM的好处是你不需要对状态进行追踪,因为每一个节点都知道谁是它的父节点,谁是子节点。但是DOM用起来有些麻烦。

3.ElementTree(元素树)
ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少,这里主要介绍ElementTree。

下面是一个简单的XML例子,其文件名为ep1.xml

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <bookstore>  
  3.     <book category="COOKING">  
  4.         <title language="English">Everyday Italian</title>  
  5.         <author>Giada De Laurentiis</author>  
  6.         <year>2005</year>  
  7.         <price>30.00</price>  
  8.     </book>  
  9.     <book category="JUVENILE">  
  10.         <title language="English">Harry Potter</title>  
  11.         <author>J K. Rowling</author>  
  12.         <year>2005</year>  
  13.         <price>29.99</price>  
  14.     </book>  
  15.     <book category="WEB">  
  16.         <title language="English">Learning XML</title>  
  17.         <author>Erik T. Ray</author>  
  18.         <year>2003</year>  
  19.         <price>39.95</price>  
  20.     </book>  
  21. </bookstore>  
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
	<book category="COOKING">
		<title language="English">Everyday Italian</title>
		<author>Giada De Laurentiis</author>
		<year>2005</year>
		<price>30.00</price>
	</book>
	<book category="JUVENILE">
		<title language="English">Harry Potter</title>
		<author>J K. Rowling</author>
		<year>2005</year>
		<price>29.99</price>
	</book>
	<book category="WEB">
		<title language="English">Learning XML</title>
		<author>Erik T. Ray</author>
		<year>2003</year>
		<price>39.95</price>
	</book>
</bookstore>


在这段XML中有三个book元素,每个book又有category属性和title、author、year和price四个元素,其中title元素含有language属性。可以看出,XML表现数据非常直观,即使没学过也能很快的理解,相比之下DOM就要稍微复杂一点了。

Python处理XML之DOM篇

这一部分主要讨论如何用xml.dom模块来处理上述XML文件

下面我们会用python的DOM编程接口来生成上面的bookstoreXML数据,在此之前,你需要对DOM又一个简单的认识,如果你已经知道DOM了,可以直接跳到code部分。

在DOM中,文档由不同的节点组成。<book>、<title>这些在’<>’中的叫做元素节点,category这种以'name=value’形式出现在’<>’中的是属性节点,'Harry Potter’、'2005'这些又叫做文本节点(注意:文本本身也是节点,而不是外层元素节点的值,<name>节点的值是null!)。除此以外,节点和节点之间还存在父子关系,比如<bookstore>是整个文档的根节点,它下面有三个book元素子节点,每个book节点又有一个category属性子节点和title、author、year和price四个元素子节点,title元素节点下有一个属性节点language和一个文本子节点Harry Potter,最终一个DOM文档就由各种节点构成一颗节点树。OK,一般来说掌握这些知识足够了,如果你想要系统的学习DOM,请参考W3C的DOM标准

首先编程生成ep1.xml文件


  1. # -*- coding:UTF-8 -*-   
  2. from xml.dom import getDOMImplementation  
  3.   
  4. def create_element_with_text(document,tagname,text):  
  5.     "创建一个元素节点,该节点只有一个文本子节点"  
  6.     #创建元素节点和文本节点   
  7.     elementNode = document.createElement(tagname)  
  8.     textNode = document.createTextNode(text)  
  9.     # 将文本节点作为元素节点的子节点   
  10.     elementNode.appendChild(textNode)  
  11.     return elementNode  
  12.   
  13. def create_bookstore_xml(filename):  
  14.     impl = getDOMImplementation()  
  15.     # 创建文档对象,文档对象用于创建各种节点。   
  16.     # 注意这个文档不是指XML文件,而是DOM文档   
  17.     doc = impl.createDocument(None# namespaceUri   
  18.                               "bookstore"# qualifiedName   
  19.                               None# doctype   
  20.     top_element = doc.documentElement # 得到根节点   
  21.     # 定义要转换的数据   
  22.     bookstore = [{'category':'COOKING''title':'Everyday Italian''language':'English''author':'Giada De Laurentiis''year':2005,'price':30.00},  
  23.                  {'category':'JUVENILE''title':'Harry Potter''language':'English''author':'J K. Rowling''year':2005,'price':39.99},  
  24.                  {'category':'WEB''title':'Learning XML''language':'English''author':'Erik T. Ray''year':2003,'price':39.95}]  
  25.     for book in bookstore:  
  26.         sNode = doc.createElement('book')  
  27.         # 为book添加categroy属性节点,注意属性值需要转化成string类型   
  28.         sNode.setAttribute('category', book['category'])  
  29.         # 给book节点添加四个元素子节点,注意year和price要转成string   
  30.         titleNode = create_element_with_text(doc, 'title', book['title'])  
  31.         titleNode.setAttribute('language', book['language'])  
  32.         authorNode = create_element_with_text(doc, 'author', book['author'])  
  33.         yearNode = create_element_with_text(doc, 'year', str(book['year']))  
  34.         priceNode = create_element_with_text(doc, 'price',str(book['price']))  
  35.         sNode.appendChild(titleNode)  
  36.         sNode.appendChild(authorNode)  
  37.         sNode.appendChild(yearNode)  
  38.         sNode.appendChild(priceNode)  
  39.         # 将遍历的student节点添加到根节点下   
  40.         top_element.appendChild(sNode)  
  41.         # 最后,将DOM文档写到文件中保存   
  42.         xml_file = open(filename, 'w')  
  43.         print doc.toprettyxml()#美化XML输出   
  44.         doc.writexml(xml_file, addindent=' '*4, newl='\n', encoding='utf-8')  
  45.   
  46. if __name__ == '__main__':  
  47.     create_bookstore_xml('bookDOM.xml')  
# -*- coding:UTF-8 -*-
from xml.dom import getDOMImplementation

def create_element_with_text(document,tagname,text):
    "创建一个元素节点,该节点只有一个文本子节点"
    #创建元素节点和文本节点
    elementNode = document.createElement(tagname)
    textNode = document.createTextNode(text)
    # 将文本节点作为元素节点的子节点
    elementNode.appendChild(textNode)
    return elementNode

def create_bookstore_xml(filename):
    impl = getDOMImplementation()
    # 创建文档对象,文档对象用于创建各种节点。
    # 注意这个文档不是指XML文件,而是DOM文档
    doc = impl.createDocument(None, # namespaceUri
                              "bookstore", # qualifiedName
                              None) # doctype
    top_element = doc.documentElement # 得到根节点
    # 定义要转换的数据
    bookstore = [{'category':'COOKING', 'title':'Everyday Italian', 'language':'English', 'author':'Giada De Laurentiis', 'year':2005,'price':30.00},
                 {'category':'JUVENILE', 'title':'Harry Potter', 'language':'English', 'author':'J K. Rowling', 'year':2005,'price':39.99},
                 {'category':'WEB', 'title':'Learning XML', 'language':'English', 'author':'Erik T. Ray', 'year':2003,'price':39.95}]
    for book in bookstore:
        sNode = doc.createElement('book')
        # 为book添加categroy属性节点,注意属性值需要转化成string类型
        sNode.setAttribute('category', book['category'])
        # 给book节点添加四个元素子节点,注意year和price要转成string
        titleNode = create_element_with_text(doc, 'title', book['title'])
        titleNode.setAttribute('language', book['language'])
        authorNode = create_element_with_text(doc, 'author', book['author'])
        yearNode = create_element_with_text(doc, 'year', str(book['year']))
        priceNode = create_element_with_text(doc, 'price',str(book['price']))
        sNode.appendChild(titleNode)
        sNode.appendChild(authorNode)
        sNode.appendChild(yearNode)
        sNode.appendChild(priceNode)
        # 将遍历的student节点添加到根节点下
        top_element.appendChild(sNode)
        # 最后,将DOM文档写到文件中保存
        xml_file = open(filename, 'w')
        print doc.toprettyxml()#美化XML输出
        doc.writexml(xml_file, addindent=' '*4, newl='\n', encoding='utf-8')

if __name__ == '__main__':
    create_bookstore_xml('bookDOM.xml')

可以看出,使用DOM的好处是可以很自由的调整各节点之间的关系,面对频繁添加或者删除节点的需求时,可以轻松地用DOM来解决,SAX在这方面显得非常乏力。然而,DOM的缺点是在解析时需要把整个XML文档映射为内存中的DOM树,如果文件很大的话,构建DOM树就会非常耗资源了。

下面我们就来看看怎么解析刚才生成的XML文件,重新构造出bookstore列表。这里用到了xml.dom.minidom模块中的parse方法。


  1. from xml.dom import minidom  
  2.   
  3. def get_node_text(node):  
  4.     # 得到元素的文本子节点中的内容,strip用于取出文本两头的空白字符   
  5.     return node.childNodes[0].nodeValue.strip()  
  6.   
  7. def parse_bookstore_xml(filename):  
  8.     # 利用minidom模块将XML文件解析成DOM文档对象   
  9.     doc = minidom.parse(filename)  
  10.     top_element = doc.documentElement  
  11.     bookstore = []#列表   
  12.     books = top_element.getElementsByTagName('book')  
  13.     for node in books:  
  14.         book = {} #字典   
  15.         book['category'] = node.getAttribute('category')  
  16.         book['title'] = get_node_text(node.getElementsByTagName('title')[0])  
  17.         #下面两句是做测试用的   
  18.         #print node.getElementsByTagName('title')[0].hasAttributes()   
  19.         #print node.getElementsByTagName('title')[0].hasAttribute('language')   
  20.         book['language']=node.getElementsByTagName('title')[0].getAttribute('language')  
  21.         book['author'] = get_node_text(node.getElementsByTagName('author')[0])  
  22.         book['year'] = get_node_text(node.getElementsByTagName('year')[0])  
  23.         book['price'] = get_node_text(node.getElementsByTagName('price')[0])  
  24.         bookstore.append(book)  
  25.     return bookstore  
  26. if __name__ == '__main__':  
  27.     bookstore = parse_bookstore_xml('ep1.xml')  
  28.     print 'bookstore:'  
  29.     i=1  
  30.     for book in bookstore:  
  31.         print 'book%s'%i  
  32.         print book  
  33.         i=i+1  
  34.         for key in book:  
  35.             print '  %s : %s' % (key,book[key])  
from xml.dom import minidom

def get_node_text(node):
    # 得到元素的文本子节点中的内容,strip用于取出文本两头的空白字符
    return node.childNodes[0].nodeValue.strip()

def parse_bookstore_xml(filename):
    # 利用minidom模块将XML文件解析成DOM文档对象
    doc = minidom.parse(filename)
    top_element = doc.documentElement
    bookstore = []#列表
    books = top_element.getElementsByTagName('book')
    for node in books:
        book = {} #字典
        book['category'] = node.getAttribute('category')
        book['title'] = get_node_text(node.getElementsByTagName('title')[0])
        #下面两句是做测试用的
        #print node.getElementsByTagName('title')[0].hasAttributes()
        #print node.getElementsByTagName('title')[0].hasAttribute('language')
        book['language']=node.getElementsByTagName('title')[0].getAttribute('language')
        book['author'] = get_node_text(node.getElementsByTagName('author')[0])
        book['year'] = get_node_text(node.getElementsByTagName('year')[0])
        book['price'] = get_node_text(node.getElementsByTagName('price')[0])
        bookstore.append(book)
    return bookstore
if __name__ == '__main__':
    bookstore = parse_bookstore_xml('ep1.xml')
    print 'bookstore:'
    i=1
    for book in bookstore:
        print 'book%s'%i
        print book
        i=i+1
        for key in book:
            print '  %s : %s' % (key,book[key])

运行后得到如下结果:

  1. bookstore:  
  2. book1  
  3.   category : COOKING  
  4.   language : English  
  5.   author : Giada De Laurentiis  
  6.   price : 30.00  
  7.   title : Everyday Italian  
  8.   year : 2005  
  9. book2  
  10.   category : JUVENILE  
  11.   language : English  
  12.   author : J K. Rowling  
  13.   price : 29.99  
  14.   title : Harry Potter  
  15.   year : 2005  
  16. book3  
  17.   category : WEB  
  18.   language : English  
  19.   author : Erik T. Ray  
  20.   price : 39.95  
  21.   title : Learning XML  
  22.   year : 2003  
bookstore:
book1
  category : COOKING
  language : English
  author : Giada De Laurentiis
  price : 30.00
  title : Everyday Italian
  year : 2005
book2
  category : JUVENILE
  language : English
  author : J K. Rowling
  price : 29.99
  title : Harry Potter
  year : 2005
book3
  category : WEB
  language : English
  author : Erik T. Ray
  price : 39.95
  title : Learning XML
  year : 2003

解析代码中最关键的就是minidom模块的parse方法以及DOM节点对象的getElementsByTagName和childNodes方法,如果这还不足以满足你的需求,请参考python标准库官方文档中关于xml.dom模块和xml.dom.minidom模块的内容。

Python处理XML之ElementTree篇

同样是上面那个ep1.xml文件,在此用ElementTree来构建和解析

构建ep1.xml

  1. from xml.etree.ElementTree import *  
  2.   
  3. def creat_element_with_text(upnode,tagname,nodetext):  
  4.     "创建一个元素节点,该节点只有一个文本子节点"  
  5.     #创建子节点并为其添加文本节点   
  6.     subnode = SubElement(upnode,tagname)  
  7.     subnode.text = nodetext  
  8.     return subnode  
  9.   
  10. #美化输出结果。elem为根节点,level缺省参数    
  11. def beautify(elem, level=0):   
  12.     i = "\n" + level*"    "  
  13.     if len(elem):   
  14.         if not elem.text or not elem.text.strip():   
  15.             elem.text = i + "    "  
  16.         for e in elem:   
  17.             beautify(e, level+1)   
  18.         if not e.tail or not e.tail.strip():   
  19.             e.tail = i   
  20.     if level and (not elem.tail or not elem.tail.strip()):   
  21.         elem.tail = i   
  22.     return elem  
  23.   
  24. if __name__ == '__main__':  
  25.     #定义要构建的XML的文件的各种元素属性   
  26.     bookstore = [{'category':'COOKING''title':'Everyday Italian''language':'English''author':'Giada De Laurentiis''year':2005,'price':30.00},  
  27.                  {'category':'JUVENILE''title':'Harry Potter''language':'English''author':'J K. Rowling''year':2005,'price':39.99},  
  28.                  {'category':'WEB''title':'Learning XML''language':'English''author':'Erik T. Ray''year':2003,'price':39.95}]  
  29.     bookstoreNode = Element('bookstore')  
  30.     for book in bookstore:  
  31.         #构建book的元素及属性,注意year和price的文本节点要转换成字符串   
  32.         bookNode = SubElement(bookstoreNode,'book')  
  33.         bookNode.attrib['category'] = book['category']  
  34.         titleNode = creat_element_with_text(bookNode,'title',book['title'])  
  35.         titleNode.attrib['language'] = book['language']          
  36.         authorNode = creat_element_with_text(bookNode,'author',book['author'])  
  37.         yearNode = creat_element_with_text(bookNode,'year',str(book['year']))  
  38.         priceNode = creat_element_with_text(bookNode,'price',str(book['price']))  
  39.     tree = ElementTree(bookstoreNode)  
  40.     beautify(bookstoreNode)  
  41.     dump(tree)#用于输出该树   
  42.     #保存到ep1.xml文档中,编码方式是UTF-8   
  43.     tree.write('ep1.xml','UTF-8')  
from xml.etree.ElementTree import *

def creat_element_with_text(upnode,tagname,nodetext):
    "创建一个元素节点,该节点只有一个文本子节点"
    #创建子节点并为其添加文本节点
    subnode = SubElement(upnode,tagname)
    subnode.text = nodetext
    return subnode

#美化输出结果。elem为根节点,level缺省参数 
def beautify(elem, level=0): 
    i = "\n" + level*"    "
    if len(elem): 
        if not elem.text or not elem.text.strip(): 
            elem.text = i + "    "
        for e in elem: 
            beautify(e, level+1) 
        if not e.tail or not e.tail.strip(): 
            e.tail = i 
    if level and (not elem.tail or not elem.tail.strip()): 
        elem.tail = i 
    return elem

if __name__ == '__main__':
    #定义要构建的XML的文件的各种元素属性
    bookstore = [{'category':'COOKING', 'title':'Everyday Italian', 'language':'English', 'author':'Giada De Laurentiis', 'year':2005,'price':30.00},
                 {'category':'JUVENILE', 'title':'Harry Potter', 'language':'English', 'author':'J K. Rowling', 'year':2005,'price':39.99},
                 {'category':'WEB', 'title':'Learning XML', 'language':'English', 'author':'Erik T. Ray', 'year':2003,'price':39.95}]
    bookstoreNode = Element('bookstore')
    for book in bookstore:
        #构建book的元素及属性,注意year和price的文本节点要转换成字符串
        bookNode = SubElement(bookstoreNode,'book')
        bookNode.attrib['category'] = book['category']
        titleNode = creat_element_with_text(bookNode,'title',book['title'])
        titleNode.attrib['language'] = book['language']        
        authorNode = creat_element_with_text(bookNode,'author',book['author'])
        yearNode = creat_element_with_text(bookNode,'year',str(book['year']))
        priceNode = creat_element_with_text(bookNode,'price',str(book['price']))
    tree = ElementTree(bookstoreNode)
    beautify(bookstoreNode)
    dump(tree)#用于输出该树
    #保存到ep1.xml文档中,编码方式是UTF-8
    tree.write('ep1.xml','UTF-8')

解析XML文档,在这里我是采用的大型XML文档解析法,因为项目的原因,XML文档必定非常的大,所以采用了这种方法。其实可以写的很简单的,各位看官可以自己去琢磨一下。

  1. from xml.etree.ElementTree import iterparse  
  2.   
  3. iparse = iterparse('ep6.xml',['start','end'])  
  4. #查找顶层bookstore   
  5. for event,elem in iparse:  
  6.     if event == 'start' and elem.tag == 'bookstore':  
  7.         Nodes = elem  
  8.         #print nodes   
  9.         break  
  10. bookstore = [] #列表   
  11.   
  12. #获取所有book   
  13. #以下三种方法都可以,但是我不知道后两种是否移除掉了不再使用的book   
  14. books = (elem for event,elem in iparse if event == 'end' and elem.tag =='book')  
  15. #books = Nodes.findall('book')   
  16. #books = elem.findall('book')   
  17. for i in books:  
  18.     book = {} #字典   
  19.     book['category'] = i.get('category')  
  20.     #print book['category']   
  21.     book['title'] = i.find('title').text.strip()  
  22.     #获取title元素的属性   
  23.     book['language'] = i.find('title').get('language')  
  24.     book['author'] = i.find('author').text.strip()  
  25.     book['year'] = i.find('year').text.strip()  
  26.     book['price'] = i.find('price').text.strip()  
  27.     bookstore.append(book)  
  28.     #print book   
  29.     #清除不再使用的book元素,减少内存使用   
  30.     Nodes.remove(i)  
  31.   
  32. print "bookstore:"  
  33. i=1  
  34. for book in bookstore:  
  35.     print 'book%s'%i  
  36.     #print book   
  37.     i=i+1  
  38.     for key in book:  
  39.         print '  %s : %s' % (key,book[key])  
from xml.etree.ElementTree import iterparse

iparse = iterparse('ep6.xml',['start','end'])
#查找顶层bookstore
for event,elem in iparse:
    if event == 'start' and elem.tag == 'bookstore':
        Nodes = elem
        #print nodes
        break
bookstore = [] #列表

#获取所有book
#以下三种方法都可以,但是我不知道后两种是否移除掉了不再使用的book
books = (elem for event,elem in iparse if event == 'end' and elem.tag =='book')
#books = Nodes.findall('book')
#books = elem.findall('book')
for i in books:
    book = {} #字典
    book['category'] = i.get('category')
    #print book['category']
    book['title'] = i.find('title').text.strip()
    #获取title元素的属性
    book['language'] = i.find('title').get('language')
    book['author'] = i.find('author').text.strip()
    book['year'] = i.find('year').text.strip()
    book['price'] = i.find('price').text.strip()
    bookstore.append(book)
    #print book
    #清除不再使用的book元素,减少内存使用
    Nodes.remove(i)

print "bookstore:"
i=1
for book in bookstore:
    print 'book%s'%i
    #print book
    i=i+1
    for key in book:
        print '  %s : %s' % (key,book[key])

Python处理XML之SAX篇

(这一部分纯粹的转载,前面已经给了链接了)
前面介绍了python中使用DOM处理XML数据的方法,今天介绍另一个常用接口,SAX。
SAX是Simple API for XML的简称,最初由Java实现,最新版本是2.0,是一种事件驱动的API。SAX的基本思想如下:顺序读取XML文件内容,并在读取过程中根据读到的数据产生对应的事件,由用户编写的Handler决定如何响应事件。python的SAX2实现在xml.sax标准库模块中,下面以students.xml为例,演示SAX的基本用法。

students.xml

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.  <students>  
  3.      <student id="1">   
  4.         <name>zhangsan</name>  
  5.          <age>20</age>  
  6.          <dob>1990.11.22</dob>  
  7.      </student>       
  8.      <student id="2">  
  9.          <name>lisi</name>  
  10.          <age>21</age>  
  11.          <dob>1992.06.15</dob>  
  12.      </student>   
  13. </students>  
<?xml version="1.0" encoding="UTF-8"?>
 <students>
     <student id="1"> 
        <name>zhangsan</name>
         <age>20</age>
         <dob>1990.11.22</dob>
     </student>     
     <student id="2">
         <name>lisi</name>
         <age>21</age>
         <dob>1992.06.15</dob>
     </student> 
</students>

sax_demo.py

  1. # -*- coding:utf-8 -*-   
  2. from xml.sax import handler,parseString    
  3. classMyGeneralHandler(handler.ContentHandler):  
  4.      
  5.     """     自定义事件处理器     """  
  6.     def startDocument(self):  
  7.         print 'Document Start...'  
  8.     def endDocument(self):  
  9.         print 'Document End...'  
  10.     def startElement(self, name, attrs):  
  11.         print 'encounter element(%s)' % (name)  
  12.     def endElement(self, name):  
  13.         print 'leave element(%s)' % (name)  
  14.     def characters(self, content):  
  15.         print 'characters:' + content  
  16. xml_file = open('students.xml','r')  
  17. parseString(xml_file.read(), #xml数据内容   
  18.             MyGeneralHandler()) # 事件处理对象   
  19. xml_file.close()  
# -*- coding:utf-8 -*-
from xml.sax import handler,parseString  
classMyGeneralHandler(handler.ContentHandler):
   
    """     自定义事件处理器     """
    def startDocument(self):
        print 'Document Start...'
    def endDocument(self):
        print 'Document End...'
    def startElement(self, name, attrs):
        print 'encounter element(%s)' % (name)
    def endElement(self, name):
        print 'leave element(%s)' % (name)
    def characters(self, content):
        print 'characters:' + content
xml_file = open('students.xml','r')
parseString(xml_file.read(), #xml数据内容
            MyGeneralHandler()) # 事件处理对象
xml_file.close()

sax_demo.py的运行结果:

  1. Document Start...  
  2. encounter element(students)  
  3. characters:  
  4.   
  5. characters:       
  6. encounter element(student)  
  7. characters:   
  8. characters:  
  9.   
  10. characters:          
  11. encounter element(name)  
  12. characters:zhangsan  
  13. leave element(name)  
  14. characters:  
  15.   
  16. characters:           
  17. encounter element(age)  
  18. characters:20  
  19. leave element(age)  
  20. characters:  
  21.   
  22. characters:           
  23. encounter element(dob)  
  24. characters:1990.11.22  
  25. leave element(dob)  
  26. characters:  
  27.   
  28. characters:       
  29. leave element(student)  
  30. characters:       
  31. characters:  
  32.   
  33. characters:       
  34. encounter element(student)  
  35. characters:  
  36.   
  37. characters:           
  38. encounter element(name)  
  39. characters:lisi  
  40. leave element(name)  
  41. characters:  
  42.   
  43. characters:           
  44. encounter element(age)  
  45. characters:21  
  46. leave element(age)  
  47. characters:  
  48.   
  49. characters:           
  50. encounter element(dob)  
  51. characters:1992.06.15  
  52. leave element(dob)  
  53. characters:  
  54.   
  55. characters:       
  56. leave element(student)  
  57. characters:   
  58. characters:  
  59.   
  60. leave element(students)  
  61. Document End...  
Document Start...
encounter element(students)
characters:

characters:     
encounter element(student)
characters: 
characters:

characters:        
encounter element(name)
characters:zhangsan
leave element(name)
characters:

characters:         
encounter element(age)
characters:20
leave element(age)
characters:

characters:         
encounter element(dob)
characters:1990.11.22
leave element(dob)
characters:

characters:     
leave element(student)
characters:     
characters:

characters:     
encounter element(student)
characters:

characters:         
encounter element(name)
characters:lisi
leave element(name)
characters:

characters:         
encounter element(age)
characters:21
leave element(age)
characters:

characters:         
encounter element(dob)
characters:1992.06.15
leave element(dob)
characters:

characters:     
leave element(student)
characters: 
characters:

leave element(students)
Document End...

从上面的例子可以看出,使用SAX最主要的工作就是编写事件处理类,在该类中决定处理哪些元素和文本。从编程者的角度看,SAX并没有DOM来的直观和方便,DOM可以任意操作文档的任意节点,而在编写SAX的handler时,你需要时刻记住当前解析的节点(见下面的例子)。另外,SAX的事件驱动模型有一个天生的缺陷,就是只能读XML,不能修改!那我们为什么还要用SAX呢?与DOM相比,SAX的优点是:

不需要把整篇XML文档读入内存,在XML文件非常大时,一般使用SAX。
如果文档只需解析一次,使用SAX更有效。
使用SAX可以为XML创建任意的数据结构,而不用非得使用DOM。实际上,SAX与DOM并不是完全互斥等价,基于DOM的解析器在创建DOM树的过程中也可能使用SAX来获取数据,SAX是读取XML数据的一种方式,DOM则是W3C的一套标准。
下面来看一个更有意义的例子,利用SAX来读取刚才的students.xml并创建python中的student字典对象。

  1. # -*- coding:utf-8 -*-   
  2. from xml.sax import handler, parseString  
  3. class StudentsHandler(handler.ContentHandler):  
  4.     def __init__(self, students):  
  5.         self.students = students  
  6.         # 记录解析过程中上一次遇到的元素名   
  7.         self.temp_name = ''  
  8.     def startElement(self, name, attrs):  
  9.         if name == 'students':  
  10.             pass  
  11.         elif name == 'student':  
  12.             student = {}  
  13.             for (attr_name, attr_value) in attrs.items():  
  14.                 # 将id属性作为student对象的属性   
  15.                 student[attr_name] = attr_value  
  16.             self.students.append(student)  
  17.         else:  
  18.             self.temp_name = name  
  19.     def characters(self, content):  
  20.         if self.temp_name:  
  21.             # temp_name不为空表示刚遇到元素节点的开始标签,那么content就是该元素节点中的文本   
  22.             # 由于SAX是从上到下解析XML的,那么该属性应该是最后加入到students列表中的student对象的属性   
  23.             self.students[-1][self.temp_name] = content  
  24.             self.temp_name = ''  
  25. students = []  
  26. xml_file = open('students.xml''r')  
  27. parseString(xml_file.read(), StudentsHandler(students))  
  28. xml_file.close()   
# -*- coding:utf-8 -*-
from xml.sax import handler, parseString
class StudentsHandler(handler.ContentHandler):
    def __init__(self, students):
        self.students = students
        # 记录解析过程中上一次遇到的元素名
        self.temp_name = ''
    def startElement(self, name, attrs):
        if name == 'students':
            pass
        elif name == 'student':
            student = {}
            for (attr_name, attr_value) in attrs.items():
                # 将id属性作为student对象的属性
                student[attr_name] = attr_value
            self.students.append(student)
        else:
            self.temp_name = name
    def characters(self, content):
        if self.temp_name:
            # temp_name不为空表示刚遇到元素节点的开始标签,那么content就是该元素节点中的文本
            # 由于SAX是从上到下解析XML的,那么该属性应该是最后加入到students列表中的student对象的属性
            self.students[-1][self.temp_name] = content
            self.temp_name = ''
students = []
xml_file = open('students.xml', 'r')
parseString(xml_file.read(), StudentsHandler(students))
xml_file.close() 

最后总结一下SAX的常用场合:

1.处理大型XML文件
2.只需要文件中的部分内容,或者只需从XML中获取特定信息
3.比较高级的话题,想要建立自己的XML数据模型。

转载:http://blog.csdn.net/wanghuiqi2008/article/details/8074302

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值