製作Docbook文檔

https://blog.csdn.net/moxiaolong/article/details/290407

1. 製作Docbook文檔需要了解的知識:

1) XML - 這是最基本的,如果這個都不懂的話,最好先找本入門級的書看看;
2) DTD - 有助於你理解Docbook的結構;
3) XSL - 有助於定製自己的Docbook;
4) XSL-FO - 最好了解一點,有助於更好的定製自己的PDF輸出。

2. 製作Docbook文檔的最簡單的過程包括以下的步驟:

1) 編輯XML文件;
2) 對XML文件進行處理,生成HTML或者PDF文檔。

2.1. 編輯XML文件

如果使用純文本編輯器來完成這項工作,我敢打賭一天之後你就做不下去了,直接編輯XML可是一件苦差事。使用類似XMLSPY這樣的工具,提供自動填充功能,並且隨時可以進行有效性檢查,不容易出錯,可以讓工作輕鬆不少。

Docbook文檔分兩類:書(book)和文章(article)。article就是一般的文章,不包含章(chapter),只有節(section)。book比較完整,可以包含前言(preface),部分(part),章(chapter),文章(article)等等。以上描述的都是Docbook DTD定義的元素,這裏不可能給出詳細的說明,具體每個元素的結構參見Docbook DTD。

讓我們先來看一個book類型文檔的典型定義:

            list 1. 典型的book類型文檔
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<book>
 <bookinfo>
  <title>My Book</title>
  <author>
   <firstname>My First Name</firstname>
   <surname>My Last Name</surname>
  </author>
  <publisher>
   <publishername>CSDN</publishername>
  </publisher>
  <isbn>ISBN#</isbn>
  <copyright>
   <year>2005</year>
  </copyright>
 </bookinfo>
 <part>
  <title>My Part</title>
  <chapter>
   <title>My Chapter</title>
   <sect1>
    <title>My Section1</title>
    <para>This  is a demo of a book.</para>
   </sect1>
  </chapter>
 </part>
</book>

該文檔聲明使用的DTD爲http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd,所有的內容都包含在book元素中,bookinfo元素包含書名(title)、作者(author)、出版社(publisher)、書號(isbn)和版權(copyright)。接着part元素包含的內容是該書的一個部分,下面有一章,接着有一節(sect1),當然都有各自的標題。

怎麼樣,各個元素的含義是不是很顯而易見,根據元素的名稱,你就能知道自己的內容該包含在什麼元素裏面。

在上面的例子裏面,有些元素不是必須的。譬如bookinfo,可以沒有或者有一個,看Docbook DTD就可以知道。

下面我以article類型的文檔爲例子,說明Docbook文檔的製作過程。

首先是XML聲明,說明文檔的一些基本信息:

<?xml version="1.0" encoding="UTF-8"?>

緊接着是文檔的DTD聲明,說明文檔使用的DTD還有根元素。典型的docbook文檔的DTD聲明如下:

<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

這個聲明表明,文檔的根元素是<article>,使用外部DTD,該DTD用一個公共標識符"-//OASIS//DTD DocBook XML V4.2//EN"標識,該DTD位於網絡的某處。標識符必須是全球唯一的,其形式爲:

prefix//owner-identifier//text-class text-description//language//display-version

第一個prefix爲“+/-”,“+”表示是已註冊的標識,“-”則相反。其他各部分的含義自己對照。

接着就可以添加內容了。首先是根元素:

<article>

</article>

article必須有一個標題:

<article>
    <title>My Article</title>
</article>

標題之後必須有內容,不可能有無內容的文章:

<article>
     <title>My Article</title>
     <sect1>
      </sect1>
</article>

這裏我們添加一個小節,“sect1”是小節的最頂層元素,其編排方式與MS Word的“heading 1”類似。

與article相同,sect1也必須有標題:

<article>
     <title>My Article</title>
     <sect1>
        <title>My Section</title>
      </sect1>
</article>

sect1也不允許無內容:

<article>
     <title>My Article</title>
     <sect1>
        <title>My Section</title>
        <para>This is my first article.</para>
      </sect1>
</article>

正文的內容一般用<para>元素封裝,para即段落(paragraph)的意思。

現在就有了一個最簡單的Docbook文檔。list 2是完整的代碼。

            list 2. 一個簡單的article文檔
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<article>
     <title>My Article</title>
     <sect1>
          <title>My Section</title>
          <para>This is my first article.</para>
     </sect1>
</article>

編輯完成之後,保存爲myarticle.xml,接着就可以生成HTML或者PDF了。

2.2 生成HTML

關於如何安裝配置工具,參見“安裝配置Docbook”。

我使用cygwin下的xsltproc來生成HTML,在cygwin的shell中輸入命令:

xsltproc --nonet --output myarticle.html c:/docbook-xsl-1.67.2/html/docbook.xsl myarticle.xml

--nonet表示我不希望從網絡獲取DTD,這樣可以節省時間。

--output指定我希望輸出的文件名,這裏指定的是myarticle.html。

緊接着是用來轉換XML文件的XSL樣式單,需要注意,使用的是html目錄下的XSL樣式單。

最後是要處理的Docbook文檔。

沒有意外的話,現在你就可以用瀏覽器打開myarticle.html看看效果了。

2.3 生成PDF文件

下面使用FOP生成PDF文件。關於如何安裝配置FOP,參見http://blog.csdn.net/mickeyrat/archive/2005/02/06/283471.aspx。

在控制檯輸入命令:

fop -xml myarticle.xml -xsl C:/docbook-xsl-1.67.2/fo/docbook.xsl myarticle.pdf

Linux的命令類似,注意docbook.xsl的路徑。

-xml指定需要轉換的docbook文檔。

-xsl指定使用的樣式單,注意,這裏使用的fo目錄下的樣式單,這是專爲轉換XSL-FO開發的。

最後是輸出文檔的文件名。

在FOP處理過程中,會輸出許多諸如

property - "background-position-horizontal" is not implemented yet.

的信息。不用理會,這是因爲FOP還在開發中,許多XSL-FO的特性都不支持。這樣的問題並不影響最終文檔的生成。

快打開myarticle.pdf看看效果吧,是不是很專業的PDF文檔?

是不是覺得製作docbook文檔很簡單呢?這麼想可就錯了,本文剩餘的部分介紹製作Docbook文檔的高級技巧。

3. 定製自己的XSL樣式單

當你開始正式製作自己的docbook文檔之後,你會發現生成的文檔並不能完全滿足你對格式的要求,譬如章節號、頁碼、字體等等。這一節就告訴你如何定製自己的XSL樣式單,生成滿足特定需求的文檔。下面的內容會涉及XSL和XSL-FO。

有人可能會想通過修改Docbook DTD達到定製目的,但是這種方式是不建議採用的,因爲修改Docbook DTD之後,你的文檔就不再是Docbook文檔。

因爲Docbook把內容與樣式完全分開,所以修改XSL樣式單,就能夠改變輸出結果。

爲了修改樣式單,你需要有自己的定製層,也就是基於Docbook XSL樣式單之上開發自己的樣式單。千萬不要直接修改Docbook XSL樣式單,這樣做有兩個缺點:

1) 不易維護:你的修改可能會分散在幾十個文件中,過幾天,你就會忘記自己修改過的地方。

2) 不易升級:如果你想升級樣式到新的版本,你不得不把你所做的所有修改合併到新的版本中,合併的過程中肯定要處理大量的衝突,並且容易出錯。

我想你應該知道<xsl:include>與<xsl:import>的區別:使用<xsl:include>引入的元素,如果有重複定義的,第一次出現的有效;使用<xsl:import>引入的元素,最後一個有效。定製層其實是依賴於XSL這樣的一個特性,使用<xsl:import>引入Docbook XSL樣式單的起點文件,然後添加自己的修改。list 3給出一個定製層文件的框架。

                             list 3 customization.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:import href="html/docbook.xsl"/>
    ...
    modifications
    ...
</xsl:stylesheet>

定製層是XSL文件,因此需要引入xsl的名字空間。在第三行,引入轉換HTML的XSL樣式單的起點文件docbook.xsl,如果是XSL-FO的定製層,起點文件在fo目錄下。然後就可以添加自己的修改了。

定製分爲兩類,一類是修改樣式單參數,一類是修改模板。

3.1 修改樣式單參數

打開html/param.xsl或者fo/param.xsl,可以找到所有的樣式單參數。看下面這個例子

<xsl:param name="section.autolabel" select="0"/>

參數的名字是“section.autolabel”,值爲“0”。這個參數的作用是控制生成文檔的時候是否對小節自動編號,譬如“1”,“1.1”等等。“0”表示關閉自動編號。你可以看一下前面生成的文檔,是不是沒有章節號?

要打開自動編號,只需要這樣修改:

<xsl:param name="section.autolabel" select="1"/>

你不是直接在param.xsl裏面改的吧?如果是的話,趕緊改回來!千萬記得,所有的修改都寫在前面生成的customization.xsl。現在重新生成HTML,

xsltproc --nonet --output myarticle.html c:/docbook-xsl-1.67.2/customization.xsl myarticle.xml

或生成PDF
fop -xml myarticle.xml -xsl C:/docbook-xsl-1.67.2/customization.xsl myarticle.pdf

注意,這個參數對HTML和XSL-FO都有效,但是你必須在customization.xsl中用<xsl:import>引入對應的起點文件,否則會報錯。現在新的文檔是不是出現章節號了?

再來一個。看你的PDF文檔,肯定沒有bookmark,因爲在fo/param.xsl中,bookmark的功能被關閉了。在customization.xsl裏添加:

<xsl:param name="fop.extensions" select="1"/>

這樣FOP在處理的時候就會生成bookmark。注意這個參數的名字,“fop.extensions”,表示這個參數屬於FOP的擴展,只對FOP有效。如果你使用PassiveTeX,那麼需要設置“passivetex.extensions”。

再來一個複雜點的:

<xsl:param name="formal.title.placement">
  figure after
  example before
  equation before
  table before
  procedure before
  task before
 </xsl:param>

這個參數作用於文章中的圖、表等等元素的標題,控制標題的位置在前面(before)還是後面(after),param.xsl預定義的都是“before”,這裏把figure的標題放在圖的後面。這個參數對HTML和XSL-FO都有效。在你的文檔中添加<figure>元素,重新生成文檔,就可以看到效果。

3.2 修改模板

Docbook XSL提供很多的參數控制輸出的效果。但是有時候,僅僅修改參數並不能滿足所有的要求,這時,你就需要修改模板。

我們來看一個很現實的例子。XSL-FO定義了一類以“keep-”開頭的屬性,譬如“keep-with-next”,表示前面的內容與後面的內容必須在同一頁,不能斷開在兩頁上。但是除了table,
FOP目前不支持這樣的屬性。所以當文檔比較長的時候,在FOP生成的PDF文檔中,你會發現有某些小節的標題在一頁的底部,而內容卻在下一頁,其他有標題的內容,譬如圖,都會出現這樣的情況。這當然是不合理的,可是無論你怎麼添加“keep-”類的參數,都無濟於事。

對於這樣的情況,FOP的FAQ告訴你的就是,“對不起,我們還沒有實現”,至於什麼時候實現,“你別問,我也不知道”。

所以只能採取一個變通的方式。前面我說過,FOP對於table支持這樣的屬性,那麼是否可以考慮把這樣的內容放在table裏面呢?當然可以,FOP有一個“blind table”的概念,這樣的表除了其中的內容是不可見的,正符合我們的要求。現在的問題就是,Docbook XSL樣式單生成的是通用的XSL-FO文件,不會把像<sect2>這種元素的內容放到“blind table”裏面。那就只剩一條路了(其實還有一條,用商業產品^_^,RenderX的XEP支持“keep-”類屬性),修改樣式單模板。list 4的代碼把<sect2>的內容放到一個“blind table”裏面。
 
                       list 4. blindtable.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                      xmlns:fo="http://www.w3.org/1999/XSL/Format"
                        version="1.0">
    <xsl:import href="docbook.xsl"/>

    <xsl:template match="sect2">
        <xsl:variable name="id">
            <xsl:call-template name="object.id"/>
        </xsl:variable>
   
        <fo:table table-layout="fixed" width="100%">
        <fo:table-column column-number="1"/>
        <fo:table-body>
              <fo:table-row keep-with-next="always">
                   <fo:table-cell id="{$id}" xsl:use-attribute-sets="section.level2.properties">
                       <xsl:call-template name="sect2.titlepage"/>
                   </fo:table-cell>
               </fo:table-row>
               <xsl:variable name="toc.params">
                  <xsl:call-template name="find.path.params">
                      <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
                  </xsl:call-template>
                  <xsl:if test="contains($toc.params, 'toc') and $generate.section.toc.level &gt;= 2">
                       <xsl:call-template name="section.toc"/>
                       <xsl:call-template name="section.toc.separator"/>
                   </xsl:if>
               </xsl:variable>      
               <fo:table-row>
                   <fo:table-cell>
                       <xsl:apply-templates select="*[2]"/>
                   </fo:table-cell>
               </fo:table-row>
           </fo:table-body>
        </fo:table>
        <xsl:apply-templates select="*[position() > 2]"/>
    </xsl:template> 
</xsl:stylesheet>

對於這段代碼就不多做解釋了,總的來說其作用就是覆蓋了sections.xsl中定義的名爲“sect2”的模板,在生成XSL-FO文件的時候,把<sect2>的標題和內容分別放到一個單列表的兩行。因爲這裏用到了fo名字空間,所以在開始要引入fo名字空間。

重新生成PDF文件:

fop -xml yourarticle.xml -xsl C:/docbook-xsl-1.67.2/blindtable.xsl yourarticle.pdf

你會發現所有<sect2>的內容沒有標題與內容斷開在兩頁上的情況了。

4. 總結

到此爲止,你已經瞭解製作Docbook的完整過程:

1) 編輯XML文檔;
2) 生成HTML/PDF;
3) 定製XSL樣式單。

定製XSL樣式單不能直接修改Docbook XSL樣式單,需要創建一個新的XSL文件作爲定製層。

XSL樣式單定製有兩類:

1) 修改XSL參數;
2) 修改XSL模板。

總之Docbook是十分強大的工具,可以用來製作非常專業漂亮的技術文檔,甚至是其他文檔。


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章