Python处理XML

  在Python(以及其他编程语言)内有两种常见的方法处理XML:SAX(Simple API for XML)和DOM(Document Object Model,文档对象模型)。SAX语法分析器读取XML文件并且告知它发现的内容(文本,标签和特性)。由于它一次只村文档的一小部分,所以SAX简单,快速并能有效利用内存。DOM走的则是另外一条路:它构造一个表示整个文档的数据结构(文档树)。这样会慢些并且需要更多内存,但如果希望操作整个文档结构的话则很有用。

  Python内使用DOM的信息 http://docs.python.org/2/library/xml.dom.html 。除了标准的DOM处理外,标准库还包括另外两个模块:

cml.dom.minidom(简化的DOM)和xml.dom.pulldom(SAX和DOM的结合体,减少了内存需求)。

  pyRXP(https://bitbucket.org/rptlab/pyrxp) 是个快速且简单的XML语法分析器(它并不使用DOM,但是会从XML文档中建立完整的文档树)。ElementTree (http://effbot.org/zone/elementtree.htm)则更加灵活易用。

  更多处理XML的Python工具请参看https://wiki.python.org/moin/PythonXml

  我们使用Python内置的SAX进行解析.

  SAX不用将整个文档加载到内存,基于事件驱动的API(Observer模式),用户只需要注册自己感兴趣的事件即可。在使用SAX进行解析时,有很多事件类型可用,但是这里只用到3个:元素的开始(开始标签的匹配项),元素的结束(关闭标签的匹配项)以及纯文本(字符)。要解析XML文件,可使用xml.sax模块的parse函数。这个函数负责读取文件并且生成时间——由于它要生成这3类事件,所以要调用一些事件处理程序。这些处理程序会作为内容处理程序(content handler)对象的方法来实现。需要继承 xml.sax.handler 中的 ContentHandler 类,因外它实现了所有需要的事件处理程序(只不过是没有任何效果的伪操作),可以在需要的时候覆盖这些函数。

  下面是一个xml文件 website.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <website>
 3   <page name="index" title="Home Page">
 4     <h1>Welcome to My Home Page</h1>
 5     <p>
 6       Hi, there. My name is Mr. Gumby, and this is my home page. Here
 7       are some of my interests:
 8     </p>
 9     <ul>
10       <li>
11         <a href="interests/shouting.html">Shouting</a>
12       </li>
13       <li>
14         <a href="interests/sleeping.html">Sleeping</a>
15       </li>
16       <li>
17         <a href="interests/eating.html">Eating</a>
18       </li>
19     </ul>
20   </page>
21   <directory name="interests">
22     <page name="shouting" title="Shouting">
23       <h1>Mr. Gumby's Shouting Page</h1>
24       <p>...</p>
25     </page>
26     <page name="sleeping" title="Sleeping">
27       <h1>Mr. Gumby's Sleeping Page</h1>
28       <p>...</p>
29     </page>
30     <page name="eating" title="Eating">
31       <h1>Mr. Gumby's Eating Page</h1>
32       <p>...</p>
33     </page>
34   </directory>
35 </website>

      我们需要处理上述的xml文件,根据xml的内容可知,website.xml是一个网站系统的内容文件,我们根据其意思使用Python自动生成一个简易的网站系统。

  我们先用一个简单的例子演示如何使用Python SAX方式解析XML

1 import os
2 from xml.sax.handler import ContentHandler
3 from xml.sax import parse
4 
5 class TestHandler(ContentHandler):
6     def startElement(self, name, attrs):
7         print name, attrs.keys()
8 
9 parse('website.xml', TestHandler())

  输出结果:

 1 website []
 2 page [u'name', u'title']
 3 h1 []
 4 p []
 5 ul []
 6 li []
 7 a [u'href']
 8 li []
 9 a [u'href']
10 li []
11 a [u'href']
12 directory [u'name']
13 page [u'name', u'title']
14 h1 []
15 p []
16 page [u'name', u'title']
17 h1 []
18 p []
19 page [u'name', u'title']
20 h1 []
21 p []

  使用SAX非常简单,如果我们对某个标签感兴趣,我们使用 if 语句进行判断然后进行相应的处理即可。

 

    我们现在编写一个完整的Python脚本对上面的XML进行处理:

  websit.xml

 1 from xml.sax.handler import ContentHandler
 2 from xml.sax import parse
 3 import os
 4 
 5 class Dispatcher(object):
 6 
 7     def dispatch(self, prefix, name, attrs=None):
 8         mname = prefix + name.capitalize()
 9         dname = 'default' + prefix.capitalize()
10         method = getattr(self, mname, None)
11         if callable(method):
12             args = ()
13         else:
14             method = getattr(self, dname, None)
15             args = name,
16         if prefix == 'start':
17             args += attrs,
18         if callable(method):
19             method(*args)
20 
21     def startElement(self, name, attrs):
22         self.dispatch('start', name, attrs)
23 
24     def endElement(self, name):
25         self.dispatch('end', name)
26 
27 class WebsiteConstructor(Dispatcher, ContentHandler):
28 
29     passthrough = False
30 
31     def __init__(self, directory):
32         self.directory = [directory]
33         self.ensureDirectory()
34 
35     def ensureDirectory(self):
36         path = os.path.join(*self.directory)
37         if not os.path.isdir(path):
38             os.makedirs(path)
39 
40     def characters(self, content):
41         if self.passthrough:
42             self.out.write(content)
43 
44     def defaultStart(self, name, attrs):
45         if self.passthrough:
46             self.out.write('<' + name)
47             for key, val in attrs.items():
48                 self.out.write(' %s="%s"' % (key, val))
49             self.out.write('>')
50 
51     def defaultEnd(self, name):
52         if self.passthrough:
53             self.out.write('</%s>' % name)
54 
55     def startDirectory(self, attrs):
56         self.directory.append(attrs['name'])
57         self.ensureDirectory()
58 
59     def endDirectory(self):
60         self.directory.pop()
61 
62     def startPage(self, attrs):
63         filename = os.path.join(*self.directory + [attrs['name'] + '.html'])
64         self.out = open(filename, 'w')
65         self.writeHeader(attrs['title'])
66         self.passthrough = True
67 
68     def endPage(self):
69         self.passthrough = False
70         self.writeFooter()
71         self.out.close()
72 
73     def writeHeader(self, title):
74         self.out.write('<html>\n <head>\n <title>')
75         self.out.write(title)
76         self.out.write('</title>\n </head>\n <body>\n')
77 
78     def writeFooter(self):
79         self.out.write('\n </body>\n</html>\n')
80 
81 XML = os.path.join('website.xml')
82 parse(XML, WebsiteConstructor('public_html'))

  使用

1 python website.py

  运行后我们会得到一堆HTML文件,文件内容即是xml文件定义的内容

 

  

posted on 2014-01-05 20:24  Arts&Crafts  阅读(825)  评论(0编辑  收藏  举报

导航