本教程講述如何建立 EPUB 格式的電子圖書。EPUB 是一種基於 XML 的、對開發者友好的格式,正逐漸成爲數字圖書的事實標準。但 EPUB 不只可用於圖書,還包括: php
本教程首先手工建立一個 EPUB 圖書,幫助您瞭解其構成和須要的文件。而後說明如何捆綁完成的數字圖書,按照規範進行驗證以及在不一樣的閱讀系統上測試。 css
而後討論如何從 DocBook XML 生成 EPUB — 最經常使用的技術文檔標準之一 — 以及如何使用 Python 實現從 DocBook 到 EPUB 的自動建立。 html
經過本教程能夠學習以下內容: java
本教程對操做系統沒有特殊要求,可是應該熟悉建立文件和目錄的機制。建議使用 XML 編輯器或者集成開發環境(IDE)。 git
對於本教程後半部分的 EPUB 建立自動化內容,須要讀者瞭解基本的 XML 處理技巧 — XSLT、 DOM 或者基於 SAX 的解析 — 並熟悉使用 XML 原生 API 構造 XML 文檔。 編程
閱讀本教程不須要熟悉 EPUB 文件格式。 瀏覽器
嘗試本教程中的例子,須要一個 Java 解釋器(1.5 或更高版本)和 Python 解釋器(2.4 或更高版本)以及相應的 XML 庫。不過,有經驗的 XML 開發人員很容易將這些例子修改成適合任何編程語言和 XML 庫。 網絡
回頁首 app
瞭解 EPUB 的背景,EPUB 最適合作什麼,以及 EPUB 和便攜式文檔格式(PDF)的區別。 jsp
EPUB 是可逆的數字圖書和出版物 XML 格式,數字出版業商業和標準協會 International Digital Publishing Forum (IDPF) 制定的標準。IDPF 於 2007 年 10 月正式採用 EPUB,隨後被主流出版商迅速採用。可使用各類開放源代碼或者商業軟件在全部主流操做系統、Sony PRS 之類的 e-ink 設備或者 Apple iPhone 之類的小型設備上閱讀 EPUB 格式。
雖然最先採用 EPUB 的是傳統的印刷品出版商,可是這並不妨礙它在電子圖書中的應用。利用免費的軟件工具,能夠將網頁捆綁成 EPUB,轉化成文本文件或者將原有的 DocBook XML 文檔轉化成結構良好的、有效的 EPUB(後一點將在 從 DocBook 到 EPUB 一節討論)。
PDF 仍然是世界上應用最普遍的電子文檔格式。從圖書出版商的角度來看,PDF 的優勢包括:
EPUB 包括三個單獨的 IDPF 規範,雖然實際上將其統稱爲 EPUB 更保險:
此外,對於檔案中的特定類型的內容,EPUB 還重用了其餘一些標準,如 XHTML 1.0 和 Digital Accessible Information SYstem (DAISY)。
從軟件開發人員的角度來看,PDF 還遠遠不夠理想:
EPUB 解決了 PDF 和開發人員友好性有關的全部瑕疵。一個 EPUB 就是一個簡單 ZIP 格式文件(使用 .epub 擴展名),其中包括按照預先定義的方式排列的文件。如何製做 ZIP 文檔有一些技巧,稍後將在 將 EPUB 文件捆綁爲 ZIP 文檔 一節介紹。除此之外,EPUB 很是簡單:
最關鍵的在於 EPUB 元數據是 XML,EPUB 內容是 XHTML。若是您的文檔構建系統產生的結果用於 Web 和/或基於 XML,那麼也可用於生成 EPUB。
最小的 EPUB 包至少要包含幾個文件。規範對於 EPUB 包中這些文件的格式、內容和位置要求可能很嚴格。這一節討論使用 EPUB 標準必須瞭解的基礎知識。
小型 EPUB 文件的基本結構遵循 清單 1 所示的樣式。準備好分發以前,整個目錄結構被壓縮到一個 ZIP 格式文件中,幾點特殊要求將在 用 ZIP 打包 EPUB 文件 一節討論。
mimetype META-INF/ container.xml OEBPS/ content.opf title.html content.html stylesheet.css toc.ncx images/ cover.png
提示:可 下載 符合該結構的一個電子圖書,但建議按照本教程的說明本身建立一個。
編寫 EPUB 圖書以前首先建立 EPUB 項目的目錄。打開文本編輯器或者 Eclipse 之類的 IDE。建議採用支持 XML 的編輯器 — 具體而言就是可以根據 參考資料 給出的 Relax NG 模式進行驗證。
這個文件很是簡單,必須命名爲 mimetype,文件內容以下:
application/epub+zip
要注意,mimetype 文件不能包含新行或者回車。
此外,mimetype 文件必須做爲 ZIP 檔案中的第一個文件,並且自身不能壓縮。用 ZIP 打包 EPUB 文件 一節將介紹如何使用通常的 ZIP 參數將其包含進來。如今建立該文件並保存,並確保它在 EPUB 項目的根目錄中。
EPUB 根目錄下必須包含 META-INF 目錄,並且其中要有一個文件 container.xml。EPUB 閱讀系統首先查看該文件,它指向數字圖書元數據的位置。
建立目錄 META-INF。在其中建立一個新文件 container.xml。container 文件很是小,可是對結構要求很嚴格。將 清單 2 中的代碼粘貼到 META-INF/container.xml 中。
<?xml version="1.0"?> <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> <rootfiles> <rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml" /> </rootfiles> </container>
full-path(粗體)的值僅僅是該文件的一部分,不一樣的文件可能相差甚大。目錄路徑必須相對於 EPUB 文件根目錄自己,而不是 META-INF 目錄。
META-INF 目錄還能夠包含其餘幾個文件。這些文件使 EPUB 支持數字簽名、加密和數字版權管理(DRM)。本教程不討論這些主題。更多信息請參閱 OCF 規範。
mimetype 和 container 是 EPUB 檔案中僅有的兩個須要嚴格限制位置的文件。建議(儘管不是必須的)將其餘文件保存到 EPUB 的子目錄下(按照慣例,一般被稱爲 OEBPS,即 Open eBook Publication Structure,但不是必須的)。
接下來在 EPUB 項目中建立目錄 OEBPS。本教程下一節將介紹 OEBPS 中的文件 — 數字圖書的核心:元數據和頁面。
儘管該文件名沒有特殊要求,但一般被稱爲 content.opf。它指定了圖書中全部 內容的位置,如文本和圖像等其餘媒體。它還給出了另外一個元數據文件,內容的 Navigation Center eXtended (NCX) 表。
該 OPF 文件是 EPUB 規範中最複雜的元數據。建立 OEBPS/content.opf 並粘貼 清單 3 所示的內容。
<?xml version='1.0' encoding='utf-8'?> <package xmlns="http://www.idpf.org/2007/opf" xmlns:dc="http://purl.org/dc/elements/1.1/" unique-identifier="bookid" version="2.0"> <metadata> <dc:title>Hello World: My First EPUB</dc:title> <dc:creator>My Name</dc:creator> <dc:identifier id="bookid">urn:uuid:12345</dc:identifier> <meta name="cover" content="cover-image" /> </metadata> <manifest> <item id="ncx" href="toc.ncx" media-type="text/xml"/> <item id="cover" href="title.html" media-type="application/xhtml+xml"/> <item id="content" href="content.html" media-type="application/xhtml+xml"/> <item id="cover-image" href="images/cover.png" media-type="image/png"/> <item id="css" href="stylesheet.css" media-type="text/css"/> </manifest> <spine toc="ncx"> <itemref idref="cover" linear="no"/> <itemref idref="content"/> </spine> <guide> <reference href="cover.html" type="cover" title="Cover"/> </guide> </package>
OPF 文檔自己必須使用名稱空間 http://www.idpf.org/2007/opf,元數據則使用 Dublin Core Metadata Initiative (DCMI) 名稱空間http://purl.org/dc/elements/1.1/。
最好如今將 OPF 和 DCMI 模式添加到 XML 編輯器中。EPUB 用到的全部模式均可以 下載。
Dublin Core 定義了一組經常使用的元數據,可用於描述各類不一樣的數字資料,它不是 EPUB 規範的一部分。全部這些術語均可以出如今 OPF 元數據部分。編寫要分發的 EPUB 時,這裏能夠放不少內容,目前來講 清單 4 的內容就足夠了。
... <metadata> <dc:title>Hello World: My First EPUB</dc:title> <dc:creator>My Name</dc:creator> <dc:identifier id="bookid">urn:uuid:12345</dc:identifier> <meta name="cover" content="cover-image" /> </metadata> ...
有兩個術語是必須的,即 title 和 identifier。按照 EPUB 規範,標識符必須 是唯一的,可是這個唯一的值要靠數字圖書的建立者來定義。對於圖書出版商來講,這個字段通常包含 ISBN 或者 Library of Congress 編號。對於其餘 EPUB 建立者,能夠考慮使用 URL 或者很大的隨機生成的唯一用戶 ID(UUID)。要注意,屬性 unique-identifier 的值必須和 dc:identifier 元素的 ID 屬性匹配。
其餘和內容相關的能夠考慮添加的元數據包括:
關於 DCMI 的更多信息請參閱 參考資料。
EPUB 規範沒有要求包含 name 屬性值爲 cover 的 meta 元素,但爲了增長封面和圖像的可移植性,建議這樣作。一些 EPUB 呈現程序喜歡使用圖像文件做爲封面,另外一些則願意使用包含內聯封面圖像的 XHTML 文件。該例子顯示了這兩種狀況。meta 元素的 content 屬性的值應該是圖書封面圖像在 manifest 中的 ID 號,manifest 是 OPF 文件的一部分。
OPF manifest 列出了 EPUB 內容(不包括元數據)中的全部資源。就是說,一般是組成電子圖書文本的一組 XHTML 文件再加上一些相關的媒體如圖像。EPUB 鼓勵使用 CSS 設定圖書內容的樣式,所以 manifest 中也包含 CSS。進入數字圖書的全部文件都必須在 manifest 中列出。
清單 5 顯示了 manifest 的一部分。
... <manifest> <item id="ncx" href="toc.ncx" media-type="text/xml"/> <item id="cover" href="title.html" media-type="application/xhtml+xml"/> <item id="content" href="content.html" media-type="application/xhtml+xml"/> <item id="cover-image" href="images/cover.png" media-type="image/png"/> <item id="css" href="stylesheet.css" media-type="text/css"/> </manifest> ...
更高級的 manifest 文件可能包含多個 XHTML 文件以及圖像和 CSS。可 下載 一個完整的包含各類常見類型的 EPUB 例子。
第一項 toc.ncx(參見 下一節)是必須的。全部的項都有相應的 media-type 值,XHTML 內容的媒體類型爲 application/xhtml+xml。媒體類型必須正確,不能 是 text/html或者其餘類型。
EPUB 支持四種核心 圖像文件類型:Joint Photographic Experts Group (JPEG)、Portable Network Graphics (PNG)、Graphics Interchange Format (GIF) 和 Scalable Vector Graphics (SVG)。若是可以提供對核心類型的後退轉換(fall-back),也可包含不支持的文件類型。關於後退轉換內容的更多信息請參閱 OPF 規範。
href 屬性的值應該是一個相對於該 OPF 文件 的統一資源標識符(URI)。(很容易和 container.xml 中對 OPF 文件的引用混淆,其中的引用是相對於 EPUB 的總體引用)。這裏的 OPF 文件位於和內容相同的 OEBPS 目錄中,所以不須要路徑信息。
manifest 告訴 EPUB 閱讀器哪些文件屬於檔案,spine 則指定這些文件出現的順序或 — 按照 EPUB 的說法 — 數字圖書的線性閱讀順序。能夠將 OPF spine 看做是書中 「頁面」 的順序。按照文檔順序從上到下依次讀取 spine。清單 6 顯示了 OPF 文件的一個片斷。
... <spine toc="ncx"> <itemref idref="cover" linear="no"/> <itemref idref="content"/> </spine> ...
每一個 itemref 元素都須要有一個 idref 屬性,而且和 manifest 中的某個 ID 匹配。toc 屬性也是必需的。它引用 manifest 中表示內容 NCX 表文件名的 ID。
spine 中的 linear 屬性代表該項是做爲線性閱讀順序中的一項,仍是和前後次序無關。建議將封面定義爲 linear=no。符合 EPUB 規範的閱讀系統將首先打開 spine 中沒有 設置爲 linear=no 中的第一項。
OPF 內容文件的最後一部分是 guide。這一節是可選的,但最好保留。清單 7 顯示了 guide 文件的部份內容。
... <guide> <reference href="cover.html" type="cover" title="Cover"/> </guide> ...
guide 能夠爲 EPUB 閱讀系統提供語義信息。manifest 定義了 EPUB 中的物理資源,spine 提供了這些資源的順序信息,guide 負責解釋這些部分的含義。下面是能夠出如今 OPF guide 中的部分值:
完整的列表請參閱 OPF 2.0 規範(參見 參考資料)。
因爲 NCX 源自其餘標準,使用 NCX 編碼的信息和 OPF 內容之間存在重複。若是經過程序生成 EPUB,這算不上什麼問題,由於一樣的代碼可輸出到兩個文件中。兩個位置的信息要一致,不一樣的 EPUB 讀者可能使用不一樣位置的值。
儘管 OCF 文件是做爲 EPUB 自己的一部分定義的,但最後一個主要的元數據文件參照了不一樣的數字圖書標準。DAISY 是一個專門爲不能使用傳統書籍的讀者設計數據格式的組織,一般是由於視力受損或者不便於使用印刷的書籍。EPUB 借用了 DAISY 的 NCX DTD。NCX 定義了數字圖書的目錄表。複雜的圖書中,目錄表一般採用層次結構,包括嵌套的內容、章和節。
使用 XML 編輯器建立 OEBPS/toc.ncx 並粘貼 清單 8 所示的代碼。
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd"> <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1"> <head> <meta name="dtb:uid" content="urn:uuid:12345"/> <meta name="dtb:depth" content="1"/> <meta name="dtb:totalPageCount" content="0"/> <meta name="dtb:maxPageNumber" content="0"/> </head> <docTitle> <text>Hello World: My First EPUB</text> </docTitle> <navMap> <navPoint id="navpoint-1" playOrder="1"> <navLabel> <text>Book cover</text> </navLabel> <content src="title.html"/> </navPoint> <navPoint id="navpoint-2" playOrder="2"> <navLabel> <text>Contents</text> </navLabel> <content src="content.html"/> </navPoint> </navMap> </ncx>
DTD 要求 NCX <head> 標記中包含四個 meta 元素:
docTitle/text 的內容是圖書的標題,和 OPF 中的 dc:title 匹配。
二者很容易混淆,由於兩個文件都描述了文檔的順序和內容。要說明二者的區別,最簡單的辦法就是拿印刷書來打比方:OPF spine 描述了書中的各個章節是如何實際鏈接起來的,比方說翻過第一章的最後一頁就看到第二章的第一頁。NCX 在圖書的一開始描述了目錄。目錄確定會包含書中主要的章節,可是還可能包含沒有單獨分頁的小節。
一條法則是 NCX 包含的 navPoint 元素一般比 OPF spine 中的 itemref 元素多。實際上,spine 中的全部項都會出如今 NCX 中,但 NCX 可能更詳細。
navMap 是 NCX 文件中最重要的部分,定義了圖書的目錄。navMap 包含一個或多個navPoint 元素。每一個 navPoint 都要包含下列元素:
該文檔的結構很是簡單:只有兩頁,不存在嵌套關係。就是說有兩個 navPoint 元素,它們的 playOrder 值按升序排列,從 1 開始。在 NCX 中能夠命名這些章節,以便讀者跳到電子圖書不一樣的部分。
如今知道了 EPUB 須要的全部元數據,能夠加入真正的圖書內容了。可使用 下載 的內容,也能夠本身寫,只要文件名和元數據匹配便可。
而後建立下列文件和文件夾:
清單 9 包含了一個有效的 EPUB 內容頁。將其做爲標題頁(title.html),用一個相似的頁面做爲主要內容頁(content.html)。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Hello World: My First EPUB</title> <link type="text/css" rel="stylesheet" href="stylesheet.css" /> </head> <body> <h1>Hello World: My First EPUB</h1> <div><img src="images/cover.png" alt="Title page"/></div> </body> </html>
EPUB 的 XHTML 須要符合幾條要求,和通常的 Web 開發不一樣:
EPUB 支持 CSS 的方式有一些細微的差異,可是不會影響樣式表的通常用法(詳情參閱 OPS 規範)。清單 10 中的簡單 CSS 文件能夠設置基本的字體,並把標題設爲紅色。
body { font-family: sans-serif; } h1,h2,h3,h4 { font-family: serif; color: red; }
有趣的是,EPUB 很是支持 CSS 2 @font-face 規則,容許內嵌字體。若是建立技術文檔,這點可能可有可無,可是若是用多種語言或針對特定領域編寫 EPUB,可以指定具體的字體數據就頗有必要了。
如今已經準備好了建立 EPUB 圖書所需的全部內容。下一節將按照 OCF 規範將圖書裝訂起來,並看看如何進行驗證。
如今,應當能夠對 EPUB 包進行打包。這個包能夠是您本身建立的一本新書,也可以使用從本文 下載 部分得到的原始文件。
EPUB 規範的 OEBPS Container Format 討論了 EPUB 和 ZIP,最重要的幾點是:
在類 UNIX® 操做系統上,使用 ZIP 2.3 可經過兩個命令來建立 EPUB ZIP 文件,如 清單 11 所示(這些命令假設當前工做目錄爲 EPUB 項目。)
$ zip -0Xq my-book.epub mimetype $ zip -Xr9Dq my-book.epub *
第一個命令建立了一個新的 ZIP 檔案,並添加了沒有進行壓縮的 mimetype 文件。第二個命令添加其餘內容。選項 -X 和 -D 最大限度地減小 .zip 文件中可有可無的信息;-r 遞歸地包含 META-INF 和 OEBPS 目錄的內容。
雖然 EPUB 標準並不很難,但其 XML 文件必須符合特定的模式。若是使用模式感知的 XML 編輯器生成元數據和 XHTML,就能事半功倍。對 EpubCheck 包進行最後檢查(參見 參考資料)。
Adobe 負責維護 EpubCheck 包,它是採用 Berkeley Software Distribution (BSD) 許可證的開源項目。它是一個能夠做爲獨立工具、Web 應用程序運行的 Java 程序,或者能夠將它集成到在 Java Runtime Environment (JRE) 1.5 或更高版本下運行的應用程序中。
在命令行中運行很是簡單。清單 12 給出了一個例子。
$ java -jar /path/to/epubcheck.jar my-book.epub
若是沒有建立輔助文件或者元數據文件出錯,可能會看到 清單 13 所示的錯誤消息。
my-book.epub: image file OEBPS/images/cover.png is missing my-book.epub: resource OEBPS/stylesheet.css is missing my-book.epub/OEBPS/title.html(7): 'OEBPS/images/cover.png': referenced resource missing in the package Check finished with warnings or errors!
這時候可能須要設置 CLASSPATH 使它指向 EpubCheck 的安裝位置,由於確實須要導入幾個外部庫。若是獲得這樣的消息則須要設置 CLASSPATH:
org.xml.sax.SAXParseException: no implementation available for schema language with namespace URI "http://www.ascc.net/xml/schematron"
若是驗證成功,就會看到 「No errors or warnings detected(沒有檢測到錯誤或警告)」。祝賀您完成了第一個 EPUB!
測試不只僅是驗證,還要保證書的外觀看起來不錯。樣式表能正確工做嗎?章節的邏輯順序是否正確?書中是否包含了全部須要的內容?
有多重 EPUB 閱讀器可供選擇。圖 1 顯示了 Adobe Digital Editions (ADE) 的屏幕截圖,這是最經常使用的 EPUB 閱讀器。
字體顏色和圖像都顯示出來了,不錯。ADE 未能用 sans-serif 字體正確地顯示標題,不過這多是 CSS 的問題。這時候最好換一個閱讀器試試。圖 2 是用我本身編寫的、開放源代碼的、基於 Web 的 EPUB 閱讀器 Bookworm 顯示的同一本書。
這裏的問題在於 ADE 不支持這種特殊聲明。若是數字圖書的格式很是重要,那麼就必須瞭解不一樣閱讀軟件的特色。
前面咱們費了很大力氣手工建立了一個簡單的 EPUB,如今看看如何將一種常見的 XML 文檔 DocBook 轉換成 EPUB。
DocBook 是須要維護大型技術文檔的開發人員經常使用的選擇。與傳統字處理程序生成的文件不一樣,可使用基於文本的版本控制系統管理 DocBook 輸出。因爲 DocBook 是 XML,很容易將其轉換成不一樣輸出格式。2008 年夏天出現了正式的 DocBook XSL 項目,將 EPUB 做爲一種輸出格式。
從一個簡單 DocBook 文檔開始,如 清單 14 所示。 該文檔的類型爲 book,包括前言、兩個章節以及標題頁面中內聯顯示的圖像。圖像和 DocBook 源文件的目錄相同。能夠本身建立該文件和標題頁,也可 下載 本文提供的例子。
<?xml version="1.0" encoding="utf-8"?`> <book> <bookinfo> <title>My EPUB book</title> <author><firstname>Liza</firstname> <surname>Daly</surname></author> <volumenum>1234</volumenum> </bookinfo> <preface id="preface"> <title>Title page</title> <figure id="cover-image"> <title>Our EPUB cover image icon</title> <graphic fileref="cover.png"/> </figure> </preface> <chapter id="chapter1"> <title>This is a pretty simple DocBook example</title> <para> Not much to see here. </para> </chapter> <chapter id="end-notes"> <title>End notes</title> <para> This space intentionally left blank. </para> </chapter> </book>
而後從 參考資料 下載最新版本的 DocBook XSL 樣式表,並安裝 xsltproc 或 Saxon 之類的 XSLT 處理程序。本文使用 xsltproc,大多數類 UNIX 系統上都能找到。轉換 DocBook 文件,只須要用 DocBook XSL 中包含的 EPUB 模塊運行該文件便可,如 清單 15 所示。
$ xsltproc /path/to/docbook-xsl-1.74.0/epub/docbook.xsl docbook.xml Writing OEBPS/bk01-toc.html for book Writing OEBPS/pr01.html for preface(preface) Writing OEBPS/ch01.html for chapter(chapter1) Writing OEBPS/ch02.html for chapter(end-notes) Writing OEBPS/index.html for book Writing OEBPS/toc.ncx Writing OEBPS/content.opf Writing META-INF/container.xml
DocBook-to-EPUB 轉換管道仍然比較新,可能須要定製 XSLT 以獲得須要的結果。
而後添加 mimetype 文件並創建 epub+zip 檔案。清單 16 顯示了這三個命令和經過 EpubCheck 驗證程序的結果。
$ echo "application/epub+zip" > mimetype $ zip -0Xq my-book.epub mimetype $ zip -Xr9D my-book.epub * $ java -jar epubcheck.jar my-book.epub No errors or warnings detected
太簡單了!圖 3 顯示了 ADE 中的結果。
DocBook XSL 大大下降了生成 EPUB 的複雜性,可是在 XSLT 以外還有幾個步驟要執行。最後一節給出的 Python 示例程序可以生成有效的 EPUB 包。本教程顯示了不一樣的方法,可 下載 完整的 docbook2epub.py 程序。
可以使用不一樣的 Python XSLT 庫,我喜歡 lxml。它不但提供了 XSLT 1.0 必要的功能,並且解析效率高,徹底支持 XPath 1.0,提供了專門處理 HTML 的擴展。若是喜歡不一樣的庫或者使用 Python 之外的編程語言,修改這些例子也很簡單。
使用 lxml 調用 XSLT 的最有效辦法是事先解析 XSLT,而後建立反覆使用的轉換器。這樣很方便,由於個人 DocBook-to-EPUB 須要轉換多個 DocBook 文件。如 清單 17 所示。
import os.path from lxml import etree def convert_docbook(docbook_file): docbook_xsl = os.path.abspath('docbook-xsl/epub/docbook.xsl') # Give the XSLT processor the ability to create new directories xslt_ac = etree.XSLTAccessControl(read_file=True, write_file=True, create_dir=True, read_network=True, write_network=False) transform = etree.XSLT(etree.parse(docbook_xsl), access_control=xslt_ac) transform(etree.parse(docbook_file))
DocBook XSL 中的 EPUB 模塊建立輸出文件自己,所以轉換過程什麼也不返回。相反,DocBook 在當前工做目錄中建立了兩個文件夾(META-INF 和 OEBPS),包含轉換的結果。
DocBook XSL 不會對文檔中使用的任何圖片執行操做,僅僅建立元數據文件和要呈現的 XHTML。因爲 EPUB 規範要求 content.opf manifest 列出全部資源,能夠預料到 manifest 將尋找原始 DocBook 文件引用的任何圖片。清單 18 顯示了這種技術,其中假定 path 變量包含 DocBook XSLT 生成的、當前所處理的 EPUB 的路徑。
import os.path, shutil from lxml import etree def find_resources(path='/path/to/our/epub/directory'): opf = etree.parse(os.path.join(path, 'OEBPS', 'content.opf')) # All the opf:item elements are resources for item in opf.xpath('//opf:item', namespaces= { 'opf': 'http://www.idpf.org/2007/opf' }): # If the resource was not already created by DocBook XSL itself, # copy it into the OEBPS folder href = item.attrib['href'] referenced_file = os.path.join(path, 'OEBPS', href): if not os.path.exists(referenced_file): shutil.copy(href, os.path.join(path, 'OEBPS'))
DocBook XSL 不會建立 mimetype 文件,不過 清單 19 中所示的代碼能夠完成這項任務。
def create_mimetype(path='/path/to/our/epub/directory'): f = '%s/%s' % (path, 'mimetype') f = open(f, 'w') # Be careful not to add a newline here f.write('application/epub+zip') f.close()
如今只須要將文件打包成有效的 EPUB ZIP 包。須要分兩步:將未經壓縮的 mimetype 文件做爲第一個文件加進去,而後添加其餘目錄。如 清單 20 所示。
import zipfile, os def create_archive(path='/path/to/our/epub/directory'): '''Create the ZIP archive. The mimetype must be the first file in the archive and it must not be compressed.''' epub_name = '%s.epub' % os.path.basename(path) # The EPUB must contain the META-INF and mimetype files at the root, so # we'll create the archive in the working directory first and move it later os.chdir(path) # Open a new zipfile for writing epub = zipfile.ZipFile(epub_name, 'w') # Add the mimetype file first and set it to be uncompressed epub.write(MIMETYPE, compress_type=zipfile.ZIP_STORED) # For the remaining paths in the EPUB, add all of their files # using normal ZIP compression for p in os.listdir('.'): for f in os.listdir(p): epub.write(os.path.join(p, f)), compress_type=zipfile.ZIP_DEFLATED) epub.close()
好了!切記要進行驗證。
上一節 中的 Python 腳本僅僅是充分實現 EPUB 轉換自動化的第一步。爲了簡化起見,沒有涉及一些常見的狀況,好比任意嵌套的路徑、樣式表或者內嵌字體。Ruby 愛好者能夠看看 DocBook XSL 分發包中所含的 dbtoepub,方法與此相似。
由於 EPUB 仍是一種比較年輕的格式,不少有效的轉換方法還等待人們去創造。所幸的是,多數結構化標記,如 reStructuredText 或 Markdown 都已經存在生成 HTML 或者 XHTML 的渠道了;稍加修改來生成 EPUB 應該很是容易,尤爲是有了本文所示的 DocBook-to-EPUB Python 或 Ruby 腳本這些例子之後。
由於 EPUB 基本上就是 ZIP 和 XHTML,與其使用 .zip 文件,沒有理由不使用 EPUB 來分發文檔。擁有 EPUB 閱讀器的讀者可從傳統元數據和自動目錄表收益,沒有閱讀器的讀者也可將其做爲通常 ZIP 文件並在瀏覽器中查看 XHTML 內容。考慮將 EPUB 生成的代碼添加到各種文檔系統中,如 Javadoc 或 Perldoc。EPUB 是爲具備圖書長度的文檔設計的,所以很是適合愈來愈多的在線或者漸進式編程圖書。
描述 | 名字 | 大小 |
---|---|---|
本教程中用於構建 EPUB 的資源 | epub-raw-files.zip | 8KB |
EPUB 工具的 DocBook1 | docbook-to-epub.zip | 7KB |
注意: