码迷,mamicode.com
首页 > 编程语言 > 详细

python练习三—解析xml

时间:2016-05-07 16:31:42      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:

使用python解析xml,主要使用sax的ContentHandler中的标签开始和标签结束的方法驱动,然后在开始(或者结束)事件中决定使用什么处理方法,使用dispatcher来决定并分发到指定方法内处理处理流程如下:

  • 初始化的时候创建一个目录list
  • 遇到page在当前目录下新建一个html文件,标志接下来的标签是要使用default处理,写到html页面中
  • 遇到page内部的标签,使用default处理
  • 遇到page结束标签,该html写完,填充结尾标签,关闭流
  • 遇到directory标签,往directory的list】中添加下以及目录名称
  • 遇到page重复第1,2,3步
  • 解析完成

代码如下

#! /usr/bin/env python
# -*- coding=utf-8 -*-

import os
import sys
from xml.sax.handler import ContentHandler
from xml.sax import parse

class Dispatcher:
    ‘‘‘
    根据具体的xml标签分发到具体的解析函数解析
    ‘‘‘

    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)

    # 重载父类的startElement方法
    def startElement(self, name, attrs):
        self.dispatch(start, name, attrs)

    # 重载父类的endElement方法
    def endElement(self, name):
        self.dispatch(end, name)

class WebsiteConstructor(Dispatcher, ContentHandler):
    ‘‘‘
    分析website.xml构建html网页
    ‘‘‘

    # 该标签是否是正文,是否被page包裹,是否需要解析
    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, chars):
       if self.passthrough:
           self.out.write(chars)
    def defaultStart(self, name, attrs):
        if self.passthrough:
            self.out.write(< + name)
            print -----
            print attrs
            for key, val in attrs.items():
                self.out.write( %s=%s % (key, val))
                print 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)
        print os.path
        print filename
        print self.directory
        print self.directory + [attrs[name] + .html]
        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)



# 执行程序
parse(website.xml, WebsiteConstructor(public_html))

参照书中写完代码之后,发现"args += attrs"一直报错,调试的时候发现

TypeError: coercing to Unicode: need string or buffer, instance found

在"+="运算符连边需要的是string或者buffer,实际上是instance,在这条语句里面attrs是AttributesImpl的对象,前面"args = name"将name赋值给args,args是string,所以attrs类型不对,一开始还以为是ContentHandler API改变了(因为该书已经比较早了),在ipython交互命令行中查看帮助文档,发现没有错,折腾调试了挺久,对照书中源码发现有两处少了",",当时已经疯了。。。。。

args = name,
args += attrs,

少了上面两个逗号,内心的崩溃啊,由此可见自己python基本知识还是漏了

args = name # args仅仅是一个对象,并不是元组
args = name, # args是一个元组

一个逗号引发的血案。。。。。

还有就是"+=",该运算符两边类型必须一致,都是字符串(列表,元组)

 


 

完整代码

http://pan.baidu.com/s/1pLqxLKv

python练习三—解析xml

标签:

原文地址:http://www.cnblogs.com/sunshine-2015/p/5468402.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!