首頁  >  文章  >  後端開發  >  python基礎教學專案三之萬能的XML

python基礎教學專案三之萬能的XML

不言
不言原創
2018-04-03 09:21:561665瀏覽

這篇文章主要為大家詳細介紹了python基礎教程項目三之萬能的XML,具有一定的參考價值,感興趣的小伙伴們可以參考一下

這個項目的名稱與其叫做萬能的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 = &#39;default&#39; + prefix.capitalize()
        method = getattr(self, mname, None)
        if callable(method): args = ()
        else:
            method = getattr(self, dname, None)
            args = name,
        if prefix == &#39;start&#39;: args += attrs,
        if callable(method): method(*args)
    def startElement(self, name, attrs):
        self.dispatch(&#39;start&#39;, name, attrs)
    def endElement(self, name):
        self.dispatch(&#39;end&#39;, 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 &#39;----&#39;
        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(&#39;<&#39; + name)
            for key, val in attrs.items():
                self.out.write(&#39; %s="%s"&#39; %(key, val))
            self.out.write(&#39;>&#39;)
    def defaultEnd(self, name):
        if self.passthrough:
            self.out.write(&#39;</%s>&#39; % name)
    def startDirectory(self, attrs):
        self.directory.append(attrs[&#39;name&#39;])
        self.ensureDirectory()
    def endDirectory(self):
        print &#39;endDirectory&#39;
        self.directory.pop()
    def startPage(self, attrs):
        print &#39;startPage&#39;
        filename = os.path.join(*self.directory + [attrs[&#39;name&#39;]+&#39;.html&#39;])
        self.out = open(filename, &#39;w&#39;)
        self.writeHeader(attrs[&#39;title&#39;])
        self.passthrough = True
    def endPage(self):
        print &#39;endPage&#39;
        self.passthrough = False
        self.writeFooter()
        self.out.close()
    def writeHeader(self, title):
        self.out.write(&#39;<html>\n <head>\n  <title>&#39;)
        self.out.write(title)
        self.out.write(&#39;</title>\n </head>\n <body>\n&#39;)
    def writeFooter(self):
        self.out.write(&#39;\n </body>\n</html>\n&#39;)
parse(&#39;website.xml&#39;,WebsiteConstructor(&#39;public_html&#39;))

看起來這個程序上面分析的複雜了一些,不過偉人毛毛說過,任何複雜的程序都是紙老虎。那我們再來分析一下這個程式。

首先看到這個程式是有兩個類,其實完全可以當作一個類,因為有了繼承。

然後再來看它多了些什麼,除了我們分析出來的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,傳參數時的星號…

相關推薦:

python基礎教學專案二之畫幅好畫

#python基礎教學專案四之新聞聚合

#

以上是python基礎教學專案三之萬能的XML的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn