以 XML 撰寫

有一段時間,我大部分的寫作都是使用 XML 進行的,甚至連我最後一本書都是用 XML 編寫的。當我向人們提到這件事時,他們會問我許多關於我經驗的問題,這促使我寫下這篇文章。

2003 年 1 月



我如何開始

第一步 - 重構目錄

大約在 2000 年,當我的重構書籍出版時,我開始使用 XML。我已經建立了一個網站,並決定新增一個網站作為重構資訊的入口網站。我在該網站上列出我書中所有的重構(以及其他一些重構),並決定使用 XML 來儲存這些重構,這樣我希望能更容易編輯和更新它們。

整體而言,我發現網站工作有點麻煩。以 HTML 編寫很麻煩,特別是如果我想進行全域變更或在 HTML 檔案中搜尋有用的資訊時。此外,我無法輕鬆地準備 HTML 和印刷用的資料。我夢想著能寫出可以以 HTML 或良好的印刷格式進行格式化的單一文字。當時我手邊的工具都沒有辦法同時做好這兩件事。

在寫作時,我一直都是邏輯樣式的愛好者。只要我在文字處理器中開始做任何非瑣碎的事情,我都會設定與寫作內容結構相符的邏輯樣式。這樣我就可以分別思考內容和格式,儘管你可以看出我的 HTML 格式並不複雜。因此,以 XML 標記文字,然後為 HTML 分別格式化的想法非常吸引我。

雖然我對重構目錄所做的努力有點粗糙(或至少現在看來是如此),但我對整個流程的運作方式感到非常滿意。我使用 Framemaker 編寫這本書,當時的版本允許使用一種原始但有效的方法將 Frame 資料儲存在 XML 中。產生的 XML 沒問題,但並非我想要的,因為它標記了 Framemaker 詞彙中的元素,而不是我想用於網站的標籤。很幸運地,XSLT 非常適合解決這個問題,即使我沒有使用過 XSLT,也很容易寫出一個樣式表,可以轉換我想保留的元素,同時過濾掉我不想要在網站上的元素。

一旦我將檔案整理好,我就可以寫另一個 XSLT 樣式表,以 HTML 顯示檔案。一個樣式表格式化了批次,如果我想再次變更,我只需要變更一個地方即可。(DRY 原則是一件好事!)

由於每個檔案都是文字且結構良好,我還可以寫一個程式來建立目錄索引檔案。這個 Java 程式會讀取目錄中的每個目錄檔案,並從索引中的每個重構寫出選取的資訊。這樣一來,如果我新增或變更重構,我只要執行程式即可更新索引。透過將所有內容放入 ant 指令碼,我只要執行 ant 的建置流程,就能重新產生整個網站。總之,我對整個體驗非常滿意

網站和書籍

對於重構目錄的成功感到滿意,我開始在我的網站上使用 XML 和 XSLT。我開始以 XML 編寫文章,並將它們轉換為 HTML。我喜歡這樣,因為我不必費心處理 HTML 的所有格式化程式碼,我只要使用 XML 中的一組簡單標籤寫入,讓樣式表處理其餘部分即可。我也可以使用 XSLT 執行任務,例如自動為每篇文章產生目錄。

因此,隨著 2001 年的到來,我在這個環境中變得越來越熟練,並找出如何讓 XSLT 屈服於我的意志。我想到這可能是時候使用 XML 編寫一本書了。到目前為止,我所有的寫作都是使用 Framemaker 完成的。Framemaker 有其缺點,但對我來說,它的優點是它的穩固性和強大的交叉參照功能。然而,我對其封閉的檔案格式感到沮喪,這通常意味著我無法執行該工具不支援的任務。你也不可以在沒有昂貴且笨拙的附加軟體的情況下在 Frame 中撰寫指令碼。然而,對我來說,真正問題是我想將我新興的書以 HTML 放在網路上,而且我不滿意 Frame 的轉換流程,當然比不上 XML/XSLT。

所以我開始使用 XML 編寫我的 P of EAA 書,總的來說,我喜歡它的結果。可以說,我的下一本書也會使用 XML 編寫。我發現它不僅對我有用,而且在與共同作者合作時,也有一些技巧很方便,特別是當 Dave Rice 最終來到澳洲時。優點並非 XML,而是 XML 是一種純文字格式,這開啟了適用於純文字的工具。

輸入文字

人們問的第一個問題似乎是「你用什麼在文字中輸入」。對我來說,答案顯而易見——文字編輯器。作為一名程式設計師,我對許多文字編輯器相當熟悉,而 XML 作為一種格式的優點之一是你可以使用任何你喜歡的文字編輯器來輸入內容。這對合作者來說很棒,因為我不必擔心讓他們購買昂貴的軟體來為這本書貢獻他們的章節。

在我撰寫這本書時,我選擇的文字編輯器是 TextPad——這肯定是我在軟體上花費的 30 美元中最值得的。它快速且充滿了簡單但實用的功能。我發現它的剪輯程式庫非常擅長以我想要的方式標記文字。

我考慮過其他 XML 編輯工具,但對各種替代方案不感興趣。他們大多數都希望 DTD 能做任何有趣的事情,而我直到遊戲後期才開始使用 DTD。

就在這幾個月,我開始使用 XEmacs。我斷斷續續使用 emacs 多年了,但大多數時間都沒有使用,因為我使用的每台電腦似乎都沒有它,或者 Windows 埠對系統的其餘部分一無所知(我認為剪貼是基本功能。)Windows 上的 Xemacs 21.4 非常友善。SGML 主要模式非常適合基於文字的文件,特別是如果你有 DTD——我現在有了。當然,你必須習慣 emacs 按鍵組合,這在現今看來非常復古。

我試過 XML spy 幾次,但它並不真正符合我的目的。它更專注於面向資料的 XML,而且不太適合輸入文字。一旦我習慣了按鍵組合,我便錯過了 XEmacs 中那些不錯的按鍵組合。

我會看看未來如何發展。我當然可以想像一個比簡單文字編輯器更好的工具,但到目前為止,文字編輯器已經擊敗了一些非常花哨和昂貴的工具。

轉換為 HTML

當你製作 HTML 頁面時,這種方法特別有效。對我來說,使用 XML 撰寫並使用 XSLT 轉換非常有效。

它並非始於此。XSLT 是一種痛苦的語言——一個你不應該使用任何基於 XML 的東西作為程式設計語言的絕佳理由。有些人可能會發現它的 lisp 類似資料/程式相似性很有吸引力。我只是發現它非常難以撰寫和使用。它也非常複雜,這一點完全沒有幫助。

儘管有缺點,XSLT 還是很強大的。但有一些技巧可以讓你的生活更健康

  • 請記住,XSLT 就像一種函數式程式語言,它不允許以一般的方式使用變數,因此當您想要迴圈時,請使用遞迴。
  • 使用它來比對模式,而不是用來驅動輸出。因此,請優先使用 <xsl:template match = "foo"> 而不是 <xsl:for-each>。(如果您曾經使用過 awk,您會更習慣這種方式。)
  • 取得 Michael Kay 的 XSLT 程式設計師參考。這是一本令人望而生畏的大書,但它是一個非常好的參考。它不是學習 XSLT 最棒的書,但我發現它在回答詳細問題時非常棒。

在產生 HTML 時,事實上在許多其他地方,我依賴建置指令碼。對於這本書,我使用 ant 指令碼自動建置程式碼和建置書頁。擁有建置指令碼讓生活輕鬆許多。

然而,總而言之,我真的很喜歡 XML/XSLT 給我的分離。我發現使用一組簡單的邏輯標籤撰寫程式容易多了,即使我的頁面格式非常簡單。有一天,我可能會有一個漂亮的網站。

轉換為印刷品

雖然轉換為 HTML 簡單又明顯,但書籍需要列印樣式格式。那是一個更大的問題

我的第一次嘗試是使用 Apache 的 FOP 搭配 XSL-FO。當時 (2002 年初) 我發現,雖然 XSL-FO 明顯具備我所需的所有功能,但 FOP 有限制,讓我無法使用它,特別是對於這麼大的一本書。使用 FOP 路線的另一個問題,至少在當時,是出版商還沒有真正準備好。

我認為這些問題只是暫時的。隨著我們獲得更好的 XSL-FO 工具,這將會是產生可列印輸出的顯然方式。當我下次需要產生可列印輸出時,我會再看看 XSL-FO。

我最後做的事情是回到我信賴的 Framemaker。我透過自動從 XML 產生 Framemaker 檔案來執行此操作。我分兩個階段執行此操作。第一個是 XSLT 轉換,它將我用於 P of EAA 的標籤轉換為反映我正在使用的 Frame 子集的標籤。然後,我使用 Ruby 指令碼從類似 Frame 的 XML 轉換為 Frame 的文字 MIF 格式檔案。在第一步中使用 XSLT 在執行轉換時可以順利處理所有困難的調整,但 XSLT 不適合處理 Frame 所需的精確文字格式。XSLT 和 Ruby 的組合運作得非常完美。

現在可供 XML 列印的另一個選項是使用 Open Office。Open Office 的檔案格式是壓縮的 XML,它們會小心將內容與格式分開。因此,使用 XSLT 來轉換內容並在 Open Office 中另外加入格式應該是件簡單的事。未來版本的 Microsoft Word 也可能會支援這種事情。

圖表

我的寫作常包含圖表,特別是 UML 圖表,而且我常被問到我用什麼來製作。我長期避免使用花俏的 CASE 工具,而偏好 Visio,甚至在 Visio 中,我也不使用產品附帶的標準 UML 範本。CASE 工具和 Visio 的 UML 範本的問題在於,它們試圖表現得很聰明。然而,它們對 UML 的聰明程度遠低於一般開發人員,所以這些工具反而會造成阻礙。

因此,我使用由 Pavel Hruby 開發的一組不同範本(請參閱我的 連結 頁面取得連結)。

Visio 最令人沮喪的是它的輸出有惱人的小故障。例如,當你輸出到 gif 時,結果並不好,經常會切掉圖形的頂端。我期待瀏覽器對 SVG 有更多支援,而且未來可能會試驗 Open Office 的繪圖功能,看看是否能產生更好的結果。

有一件重要的事我一開始沒做,就是撰寫一個腳本,自動將所有 Visio 圖表匯出到 gif。我後來才這麼做(它會檢查 Visio 檔案是否在對應的 gif 產生後被修改)。一旦有了這個腳本,生活就容易多了,幸好 Visio 很容易使用幾乎任何腳本語言(在我的情況中,是 Ruby)來驅動。

自動程式碼匯入

使用這個架構最棒的事之一,就是自動匯入範例程式碼。大多數作者對範例程式碼感到頭痛,幾乎總是會出錯,而且他們的範例程式碼不一致或無法編譯,這只是因為同步複製和貼上的程式碼很困難。

我能夠做得更好。我將所有程式碼範例保存在目錄中,在這些目錄中,我可以使用 Ant 來建置和測試整個目錄。然後,我可以在原始碼檔案中加上註解標籤,標示要匯入到書中的程式碼區段。接著,我寫了一些簡單的 Java 程式碼,快速瀏覽原始碼檔案,並產生包含原始碼片段的 XML 檔案。然後,當我執行 XSLT 時,這些片段就可以輕鬆匯入到輸出中。這是一個奇妙的過程,消除了原本雜亂的步驟,而且讓我可以在需要時,自信地變更我的程式碼範例。

協作和版本控制

我在 P of EAA 中與幾個人合作,最明顯的是 David Rice,他寫了書中一大段內容。由於我們兩人都修改文字和程式碼範例,因此我們需要仔細協調工作。

答案是 CVS。由於 XML 檔案只是文字,因此 CVS 證明是一種處理我們協作的完美方式。每當我們修改任何內容時,我們都會將檔案上傳到 CVS。這變得至關重要,因為我們在最後期限前全力衝刺,而 David 在澳洲工作。

當然,CVS 對我個人也很有用。它允許我在任何時候安全地修改文字,因為我知道每個檔案總是有穩定的版本記錄。我們對所有內容進行版本控制,包括我們的東西所依賴的各種 Java 函式庫和 .NET 組件。就像程式設計師應該始終使用版本控制一樣,作者也應該如此!

最後的想法

即使在 XML 相關技術的早期,我發現 XML 是撰寫一本重要書籍的絕佳方式。現在我幾乎在所有寫作中毫不猶豫地使用它,包括這篇文章。(主要的例外是我在撰寫 IEEE 軟體專欄時,他們喜歡收到 Word 檔案,而且它很短,所以我不會遇到其他常見的問題。)

如果您正在考慮將 XML 用於網站、報告或書籍;如果您是極客,並且樂於使用 XSLT、腳本等,我強烈推薦您使用它。如果您不太懂技術,那麼我會等待時機,但請密切注意支援 XML 的文字處理器。如果新的 Word 與傳聞相符,事情將會變得有趣。


重大修訂

2003 年 1 月