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

 <?xml version="1.0" encoding="utf-8"?>
<website>
<page name="index" title="Home Page">
<h1>Welcome to My Home Page</h1>
<p>
Hi, there. My name is Mr. Gumby, and this is my home page. Here
are some of my interests:
</p>
<ul>
<li>
<a href="interests/shouting.html">Shouting</a>
</li>
<li>
<a href="interests/sleeping.html">Sleeping</a>
</li>
<li>
<a href="interests/eating.html">Eating</a>
</li>
</ul>
</page>
<directory name="interests">
<page name="shouting" title="Shouting">
<h1>Mr. Gumby's Shouting Page</h1>
<p>...</p>
</page>
<page name="sleeping" title="Sleeping">
<h1>Mr. Gumby's Sleeping Page</h1>
<p>...</p>
</page>
<page name="eating" title="Eating">
<h1>Mr. Gumby's Eating Page</h1>
<p>...</p>
</page>
</directory>
</website>

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

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

 import os
from xml.sax.handler import ContentHandler
from xml.sax import parse class TestHandler(ContentHandler):
def startElement(self, name, attrs):
print name, attrs.keys() parse('website.xml', TestHandler())

  输出结果:

 website []
page [u'name', u'title']
h1 []
p []
ul []
li []
a [u'href']
li []
a [u'href']
li []
a [u'href']
directory [u'name']
page [u'name', u'title']
h1 []
p []
page [u'name', u'title']
h1 []
p []
page [u'name', u'title']
h1 []
p []

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

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

  websit.xml

 from xml.sax.handler import ContentHandler
from xml.sax import parse
import os class Dispatcher(object): def dispatch(self, prefix, name, attrs=None):
mname = prefix + name.capitalize()
dname = 'default' + prefix.capitalize()
method = getattr(self, mname, None)
if callable(method):
args = ()
else:
method = getattr(self, dname, None)
args = name,
if prefix == 'start':
args += attrs,
if callable(method):
method(*args) def startElement(self, name, attrs):
self.dispatch('start', name, attrs) def endElement(self, name):
self.dispatch('end', name) class WebsiteConstructor(Dispatcher, ContentHandler): passthrough = False def __init__(self, directory):
self.directory = [directory]
self.ensureDirectory() def ensureDirectory(self):
path = os.path.join(*self.directory)
if not os.path.isdir(path):
os.makedirs(path) def characters(self, content):
if self.passthrough:
self.out.write(content) def defaultStart(self, name, attrs):
if self.passthrough:
self.out.write('<' + name)
for key, val in attrs.items():
self.out.write(' %s="%s"' % (key, val))
self.out.write('>') def defaultEnd(self, name):
if self.passthrough:
self.out.write('</%s>' % name) def startDirectory(self, attrs):
self.directory.append(attrs['name'])
self.ensureDirectory() def endDirectory(self):
self.directory.pop() def startPage(self, attrs):
filename = os.path.join(*self.directory + [attrs['name'] + '.html'])
self.out = open(filename, 'w')
self.writeHeader(attrs['title'])
self.passthrough = True def endPage(self):
self.passthrough = False
self.writeFooter()
self.out.close() def writeHeader(self, title):
self.out.write('<html>\n <head>\n <title>')
self.out.write(title)
self.out.write('</title>\n </head>\n <body>\n') def writeFooter(self):
self.out.write('\n </body>\n</html>\n') XML = os.path.join('website.xml')
parse(XML, WebsiteConstructor('public_html'))

  使用

 python website.py

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

  

上一篇:1006 Sign In and Sign Out (25 分)


下一篇:iphone数据存储之-- Core Data的使用