python操作xml创建网站

看到一个python写的项目博客,试着运行了下,感觉挺好,虽然不是很懂,但还是很喜欢,顺便分享下


项目: 根据一份XML文件,生成对应目录结构的网站,不过只有html还是太过于简单了,如果要是可以连带生成css那就比较强大了。这个有待后续研发,先来研究下怎么html网站结构。 既然是通过XML结构生成网站,那所有的事情都应该由这个XML文件来。先来看下这个XML文件,website.xml:

<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 int:</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>shouting page</h1>
        <p>....</p>
      </page>
      <page name="sleeping" title="Sleeping">
        <h1>sleeping page</h1>
        <p>....</p>
      </page>
      <page name="eating" title="Eating">
        <h1>Eating page</h1>
        <p>....</p>
      </page>
    </directory>
</website>

有了这个文件,下面应该来看怎么通过这个文件生成网站。

首先我们要解析这个xml文件,python解析xml和在java中一样,有两种方式,SAX和DOM,两种处理方式不同点在于速度和范围,前者讲究的是效率,每次只处理文档的一小部分,快速而能有效的利用内存,后者是相反的处理方式,先把所有的文档载入到内存,然后再进行处理,速度比较慢,也比较消耗内存,唯一的好处就是可以操作整个文档。

在python中使用sax方式处理xml要先引入xml.sax中的parse函数,还有xml.sax.handler中的ContentHandler,后面的这个类是要和parse函数来配合使用的。使用方式如下: parse('xxx.xml',xxxHandler),这里面的xxxHandler要继承上面的ContentHandler,不过只要继承就行,不需要有所作为。 然后这个parse函数在处理xml文件的时候,会调用xxxHandler中的startElement函数和endElement函数来一个xml中的标签的开始和结束,中间的过程使用一个名为characters的函数来处理标签内部的所有字符串。

有了上面的这些认识,我们已经知道如何处理xml文件了,然后再来看那个罪恶的源头website.xml文件,分析其结构,只有两个节点:page和directory,很明显page表示一个页面,directory表示一个目录。

所以处理这个xml文件的思路就变的清晰了。读取xml文件的每一个节点,然后判断是page还是directory如果是page则创建html页面,然后把节点中的内容写到文件里。如果遇到directory就创建一个文件夹,然后再处理其内部的page节点(如果存在的话)。

下面来看这部分代码,书中的实现比较复杂,比较灵活。先来看,然后在分析。


#!/usr/bin/env python

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

class Dispatcher:
    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)
        print path
        print '----'
        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)
            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):
        print 'endDirectory'
        self.directory.pop()

    def startPage(self, attrs):
        print 'startPage'
        filename = os.path.join(*self.directory + [attrs['name'] + '.html'])
        self.out = open(filename,'w')
        self.writeHeader(attrs['title'])
        self.passthrough = True

    def endPage(self):
        print 'endPage'
        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'))

首先看到这个程序是有两个类,其实完全可以当作一个类,因为有了继承。

然后再来看它多了些什么,除了我们分析出来的startElement和endElement以及characters,多出来了startPage,endPage;startDirectory,endDirectory;defaultStart,defaultEnd;ensureDirectory;writeHeader,writeFooter;和dispatch,这些个函数。除了dispatch,前面的函数都很好理解,每一对函数都是单纯的处理对应的html标签以及xml节点。而dispatch比较复杂,复杂之处在于他是用来动态拼合函数并且进行执行的。

dispatch的处理思路是,首先根据传递的参数(就是操作名称以及节点名称)判断是否存在对应的函数如startPage,如果不存在则执行default+操作名称:如defaultStart。

一个函数一个函数搞清楚之后,就知道整个处理流程是什么样了。首先创建一个public_html的文件,存放整个网站,然后读xml的节点,通过startElement和endElement调用dispatch进行处理。然后就是dispatch怎么调用具体的处理函数了。 到此为止,这个项目算是分析完了。

主要掌握的内容一个是python中使用SAX处理XML,另一个就是python中的函数的使用,比如getattr,传参数时的星号……


下面是我读完后查的资料和运行结果:

 a),callable 函数, 可以检查一个对象是否是可调用的 (无论是直接调用或是通过 apply). 对于函数, 方法, lambda 函式, 类, 以及实现了 _ _call_ _ 方法的类实例, 它都返回 True.

b),getattr()函数是Python自省的核心函数,具体使用大体如下:
 获取对象引用getattr
getattr用于返回一个对象属性,或者方法


class A:   
    def __init__(self):   
        self.a = 'a'  
    def method(self):   
        print "method print"  
  
a = A()   
print getattr(a, 'a', 'default') #如果有属性a则打印a,否则打印default   
print getattr(a, 'b', 'default') #如果有属性b则打印b,否则打印default   
print getattr(a, 'method', 'default')   #如果有方法method,否则打印其地址,否则打印default   
print getattr(a, 'method', 'default')()   #如果有方法method,运行函数并打印None否则打印default


程序运行结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值