这个项目的名称与其叫做万能的XML不如叫做自动构建网站,根据一份XML文件,生成对应目录结构的网站,不过只有html还是太过于简单了,如果要是可以连带生成css那就比较强大了。这个有待后续研发,先来研究下怎么html网站结构。 既然是通过XML结构生成网站,那所有的事情都应该由这个XML文件来。先来看下这个XML文件,website.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
< 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" rel = "external nofollow" >Shouting</ a ></ li > < li >< a href = "interests/sleeping.html" rel = "external nofollow" >Sleeping</ a ></ li > < li >< a href = "interests/eating.html" rel = "external nofollow" >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节点(如果存在的话)。
下面来看这部分代码,书中的实现比较复杂,比较灵活。先来看,然后在分析。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
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,传参数时的星号……
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.the5fire.com/python-pro-powerfullxml.html