python基础教程项目三之万能的XML

作者:the5fire 时间:2022-09-22 05:33:25 

这个项目的名称与其叫做万能的XML不如叫做自动构建网站,根据一份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" 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节点(如果存在的话)。
下面来看这部分代码,书中的实现比较复杂,比较灵活。先来看,然后在分析。


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

标签:python,基础教程
0
投稿

猜你喜欢

  • Python面试之os.system()和os.popen()的区别详析

    2023-09-14 18:15:39
  • python操作kafka实践的示例代码

    2021-04-19 10:57:34
  • Golang 实现Redis 协议解析器的解决方案

    2024-02-19 20:09:36
  • 利用django model save方法对未更改的字段依然进行了保存

    2021-12-21 21:24:18
  • mysql中的utf8与utf8mb4存储及区别

    2024-01-16 15:48:09
  • Python pygorithm模块用法示例【常见算法测试】

    2023-05-19 00:23:59
  • JS笛卡尔积算法与多重数组笛卡尔积实现方法示例

    2024-05-03 15:32:07
  • python中封包建立过程实例

    2021-11-13 14:29:08
  • 如何对MySQL数据库日志文件进行维护

    2009-02-04 13:23:00
  • 来自腾讯的一个不固定高度得消息的滚动特效

    2024-04-17 10:19:34
  • 对python模块中多个类的用法详解

    2021-03-17 17:27:21
  • 使用Python中OpenCV和深度学习进行全面嵌套边缘检测

    2021-04-21 10:21:34
  • 如何用ASP建立Index Server查询对象并为其参数赋值?

    2010-06-11 19:59:00
  • 基于bootstrop常用类总结(推荐)

    2024-04-17 09:52:42
  • Django+python服务器部署与环境部署教程详解

    2023-01-29 15:16:22
  • Python中生成Epoch的方法

    2021-06-27 15:21:15
  • javascript中直接写php代码的方法

    2024-05-02 16:27:46
  • Go语言学习之反射的用法详解

    2023-06-16 06:40:40
  • Python中模拟enum枚举类型的5种方法分享

    2022-05-04 01:00:10
  • 在Python中字符串、列表、元组、字典之间的相互转换

    2021-08-30 07:09:42
  • asp之家 网络编程 m.aspxhome.com