DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> HTML 至格式化對象(FO)轉換指南:Doug Tidwell (下)
HTML 至格式化對象(FO)轉換指南:Doug Tidwell (下)
編輯:XML詳解     

 <h1> 至 <h6> 標題

  轉換標題標記相對較簡單;將每種標題放入 <fo:block> 元素,然後根據標題級別更改字體、字體大小和其它屬性。為了使頂級標題真正突出,該示例布局在 <h1> 文本之前放置了一個分頁符和一條水平線。以下是所用的格式選項:

Html 標記 字體大小 行高 標題後的空間 其它 <h1> 28pt 32pt 22pt 在文本之前添加分頁符和水平線 <h2> 24pt 28pt 18pt 無 <h3> 21pt 24pt 14pt 無 <h4> 18pt 21pt 12pt 無 <h5> 16pt 19pt 12pt 文本 加下劃線 <h6> 14pt 17pt 12pt 文本 加下劃線 並且是 斜體字

  以下是一些標題元素:

<h1>Sample text from Henry FIElding's <cite>Tom Jones</cite></h1> 
<h2><b>Book I.</b> Containing as Much of the Birth of the Foundling 
 as Is Necessary or Proper to Acquaint the Reader with in the 
 Beginning of This History</h2> 
<h3><b>Chapter VII.</b> Containing Such Grave Matter, That the Reader 
 Cannot Laugh Once Through the Whole Chapter, Unless Peradventure He 
 Should Laugh at the Author</h3> 

  這些元素被轉換為以下格式化對象:

<fo:block break-before="page"> 
 <fo:leader leader-pattern="rule"/> 
</fo:block> 
<fo:block font-family="serif" space-after="22pt" keep-with-next="always" 
  line-height="32pt" font-size="28pt" id="tomjones"> 
 Sample text from Henry FIElding's 
  <fo:inline font-style="italic">Tom Jones</fo:inline> 
</fo:block> 
<fo:block font-family="serif" space-after="18pt" keep-with-next="always" 
  line-height="28pt" font-size="24pt" id="N10017"> 
 <fo:inline font-weight="bold">Book I.</fo:inline>  
 Containing as Much of the Birth of the Foundling 
 as Is Necessary or Proper to Acquaint the Reader with in the 
 Beginning of This History 
</fo:block> 
<fo:block font-family="serif" space-after="14pt" keep-with-next="always" 
  line-height="24pt" font-size="21pt" id="N1001C"> 
 <fo:inline font-weight="bold">Chapter VII.</fo:inline>  
 Containing Such Grave Matter, That the Reader 
 Cannot Laugh Once Through the Whole Chapter, Unless Peradventure He 
 Should Laugh at the Author 
</fo:block> 

  在 <h1> 元素的文本前插入的分頁符使得共同使用命名錨點和 <h1> 元素變得復雜。出於這個原因, <h1> 元素的 XSLT 模板檢查前一個元素,看它是否為命名錨點。以下是 <h1> 和 <h6> 元素的模板:

<xsl:template match="h1"> 
  
     
    <fo:block break-before="page"> 
  <fo:leader leader-pattern="rule"/> 
 </fo:block> 
 <fo:block font-size="28pt" line-height="32pt" 
    
     
    keep-with-next="always" 
   space-after="22pt" font-family="serif"> 
  <xsl:attribute name="id"> 
   <xsl:choose> 
    <xsl:when test="@id"> 
     <xsl:value-of select="@id"/> 
    </xsl:when> 
     
     
    <xsl:when test="name(preceding-sibling::*[1]) = 'a' and 
             preceding-sibling::*[1][@name]"> 
     <xsl:value-of select="preceding-sibling::*[1]/@name"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="generate-id()"/> 
    </xsl:otherwise> 
   </xsl:choose> 
  </xsl:attribute> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:block> 
</xsl:template> 
<xsl:template match="h6"> 
 <fo:block font-size="14pt" line-height="17pt" 
   keep-with-next="always" space-after="12pt" 
   font-family="serif" 
     
    font-style="italic" 
   text-decoration="underline"> 
  <xsl:attribute name="id"> 
   <xsl:choose> 
    <xsl:when test="@id"> 
     <xsl:value-of select="@id"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="generate-id()"/> 
    </xsl:otherwise> 
   </xsl:choose> 
  </xsl:attribute> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:block> 
</xsl:template> 
      
    

  最後提一點:因為標題可用於書簽和目錄,而且它還是有用的鏈接點,所以最好確保每個標題都有一個 id 。如果給定的標題元素已經有 id 屬性,那麼就使用它;如果沒有,則使用 XSLT generate-id() 函數創建一個:

<xsl:attribute name="id"> 
 <xsl:choose> 
  <xsl:when test="@id"> 
   <xsl:value-of select="@id"/> 
  </xsl:when> 
  <xsl:otherwise> 
    
     
    <xsl:value-of select="generate-id()"/> 
  </xsl:otherwise> 
 </xsl:choose> 
</xsl:attribute> 
      
    

  <hr> 水平線

  <fo:leader> 是一個特殊的 XSL-FO 元素,它被設計成用來處理水平線。以下是一些 Html 標記:

<p>Here's a short paragraph.</p> 
<hr/> 
<p>Here's another paragraph, following a horizontal rule.</p> 

  表示該內容的 XSL-FO 標記類似於這樣:

<fo:block> 
 Here's a short paragraph. 
</fo:block> 
<fo:block> 
 <fo:leader leader-pattern="rule"/> 
</fo:block> 
<fo:block> 
 Here's another paragraph, following a horizontal rule. 
</fo:block> 

  處理 <hr> 元素的 XSLT 模板非常簡單:

<xsl:template match="hr"> 
 <fo:block> 
   
     
    <fo:leader leader-pattern="rule"/> 
 </fo:block> 
</xsl:template> 
      
    

  最後提一點: leader-pattern 屬性還支持 dots 和 space 值,前者通常用於目錄,後者創建一個空白區域。

  <i> 斜體字文本

  在 XSL-FO 中很容易表示 Html <i> 元素:只需將該元素的文本放入帶 font-style="italic" 屬性的 <fo:inline> 中即可。下面是一個示例,它與前面演示的 <b> 元素的示例非常相似:

<p>Jackdaws <i>love</i> my big sphinx of quartz.</p> 

  使用基本的 XSL-FO 元素 <fo:block> 和 <fo:inline> 來處理以上內容:

<fo:block> 
 Jackdaws <fo:inline font-style="italic">love</fo:inline> 
 my big sphinx of quartz. 
</fo:block> 

  <fo:block> 元素總是會引起換行,而 <fo:inline> 元素則不會。由於這個原因,所以使用 <fo:inline> 來處理 <i> 元素的內容。下面這個簡單的 XSLT 模板可完成這項工作:

<xsl:template match="i"> 
 <fo:inline 
     
    font-style="italic"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  <img> 嵌入的圖像

  <img> 直接映射至 XSL-FO <fo:external-graphic> 元素。將 <img> 轉換為 <fo:external-graphic> 之所以復雜是由於 FOP 工具不支持象 width="200" 這樣的 HTML 屬性; width 和 height 屬性必須包括長度單位(例如 width="200px" )。出於這個原因,可這樣設置 XSLT 模板:使處理器在生成 <fo:external-graphic> 元素時檢查 Html 值。以下是模板:

<xsl:template match="img"> 
 <fo:block space-after="12pt"> 
  <fo:external-graphic src="{@src}"> 
   <xsl:if test="@width"> 
    <xsl:attribute name="width"> 
     <xsl:choose> 
       
     
    <xsl:when test="contains(@width, 'px')"> 
       <xsl:value-of select="@width"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="concat(@width, 'px')"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:attribute> 
   </xsl:if> 
   <xsl:if test="@height"> 
    <xsl:attribute name="height"> 
     <xsl:choose> 
       
     
    <xsl:when test="contains(@height, 'px')"> 
       <xsl:value-of select="@height"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="concat(@height, 'px')"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:attribute> 
   </xsl:if> 
  </fo:external-graphic> 
 </fo:block> 
</xsl:template> 
      
    

  注意:模板按原樣使用 src 屬性,而處理器根據需要將長度單位添加到 width 和 height 屬性。

  <kbd> 鍵盤輸入

  通常以稍大的等寬字體來表示鍵盤輸入(在 HTML 中,用 <kbd> 元素表示鍵盤輸入)。下面是 Html 樣本:

<p> 
 An easy way to delete a directory and all its contents (including 
 all subdirectorIEs) is with the <kbd>rd /s</kbd> command. 
</p> 

  可以用如下的 XSL-FO 元素來表示該樣本:

<fo:block> 
 An easy way to delete a directory and all its contents (including 
 all subdirectorIEs) is with the 
 <fo:inline font-family="monospace" font-size="110%">rd /s</fo:inline> 
 command. 
</fo:block> 

  進行這一轉換的 XSLT 模板比較簡單:

<xsl:template match="kbd"> 
 <fo:inline 
     
    font-family="monospace" font-size="110%"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  <li> 列表項

  處理列表項 幾乎和處理段落一樣,只是有幾處細微的差別。因為這些差別取決於列表項的父元素( <li> 元素在 <ol> 元素中還是在 <ul> 元素中?),所以請在 <ol> 元素 和 <ul> 元素 項下查看有關列表項的詳細信息。

  <nobr> 無換行的文本

  HTML <nobr> 元素指出:無論 <nobr> 元素中包含多少內容,浏覽器都不應換行。例如,考慮以下 Html 標記:

<p> 
 On the Windows 2000 command line, you can use the ampersand (&) to 
 combine several commands into one statement. 
 <nobr> 
  pushd d:\\projects\\xslfo & del *.fo & rebuild.bat & popd 
 </nobr> 
 is an example of this technique. 
</p> 

  要用格式化對象表示這一內容,可使用帶 wrap-option="no-wrap" 屬性的 <fo:inline> 元素。

<fo:block> 
 On the Windows 2000 command line, you can use the ampersand (&) 
 to combine several commands into one statement.  
 <fo:inline wrap-option="no-wrap">pushd d:\\projects\\xslfo & 
 del *.fo & rebuild.bat & popd </fo:inline> is an 
 example of this technique. 
</fo:block> 

  進行這一轉換的 XSLT 模板比較簡單:

<xsl:template match="nobr"> 
 <fo:inline 
     
    wrap-option="no-wrap"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  <ol> 有序列表

  XSL-FO 詞匯所具有的特征是:有專門用於列表(包括有序列表)的元素。以下是樣本 Html 列表:

<p>A few of my favorite albums</p> 
<ol> 
 <li>A Love Supreme</li> 
 <li>Remain in Light</li> 
 <li>London Calling</li> 
 <li>The Indestructible Beat of Soweto</li> 
 <li>The Joshua Tree</li> 
</ol> 

  要用 XSL-FO 表示這些列表項,必須使用這幾個元素: <fo:list-block> 、 <fo:list-item> 、 <fo:list-item-label> 和 <fo:list-item-body> 。下面介紹如何使用它們:

  <fo:list-block> 元素包含整個列表。

  每個 <fo:list-item> 元素包含單個列表項;該元素包含 <fo:list-item-label> 和 <list-item-body> 元素。

  <fo:list-item-label> 是內容旁邊的標號。例如,對於有序列表, <fo:list-item-label> 元素可能包含文本 10. 。

  <fo:list-item-body> 包含列表項的實際內容。

  下面是 Html 標記轉換為格式化對象後的情形:

<fo:block>A few of my favorite albums</fo:block> 
<fo:list-block provisional-distance-between-starts="0.75cm" 
 provisional-label-separation="0.5cm" space-after="12pt" 
 start-indent="1cm"> 
 <fo:list-item> 
  <fo:list-item-label end-indent="label-end()"> 
   <fo:block>1. </fo:block> 
  </fo:list-item-label> 
  <fo:list-item-body start-indent="body-start()"> 
   <fo:block> 
    A Love Supreme 
   </fo:block> 
  </fo:list-item-body> 
 </fo:list-item> 
  ... 
 <!-- other list items appear here --> 
  ... 
</fo:list-block> 

  以下顯示了進行轉換的 XSLT 模板。這些模板必須處理以下幾種情況:

  如果該列表出現在另一列表中,則不在該列表後插入任何空白。否則,在該列表後插入距離為 12 點的垂直空間。

  如果該列表不在任何其它列表中,則將其縮進 1 cm 。否則,它縮進的距離為 1 cm 加上其它每個列表縮進的 1.25 cm 。例如,如果該列表是第三級列表,則將該列表縮進 3.5 cm 。

  如果 <ol> 元素有 start 屬性,則以這個數字開始對列表項編號。如果沒有該屬性,那麼只需用 XSLT position() 函數對列表項編號。

  如果 <ol> 元素有 type 屬性,則用這個值來決定應該如何格式化每個列表項的數字(羅馬數字、阿拉伯數字或按字母次序的字符)。該模板用 <xsl:number> 元素的 format 屬性做到這一點。

  以下就是轉換所有 <ol> 和 <li> 項的 XSLT 模板(使用帶項目符號的列表中的規則):

<xsl:template match="ol"> 
 <fo:list-block provisional-distance-between-starts="1cm" 
  provisional-label-separation="0.5cm"> 
  <xsl:attribute name="space-after"> 
   <xsl:choose> 
     
     
    <xsl:when test="ancestor::ul or ancestor::ol"> 
     <xsl:text>0pt</xsl:text> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:text>12pt</xsl:text> 
     </xsl:otherwise> 
   </xsl:choose> 
  </xsl:attribute> 
  <xsl:attribute name="start-indent"> 
   <xsl:variable name="ancestors"> 
    <xsl:choose> 
      
     
    <xsl:when test="count(ancestor::ol) or count(ancestor::ul)"> 
      <xsl:value-of select="1 + 
                 (count(ancestor::ol) + 
                  count(ancestor::ul)) * 
                 1.25"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:text>1</xsl:text> 
     </xsl:otherwise> 
    </xsl:choose> 
   </xsl:variable> 
   <xsl:value-of select="concat($ancestors, 'cm')"/> 
  </xsl:attribute> 
  <xsl:apply-templates select="*"/> 
 </fo:list-block> 
</xsl:template> 
<xsl:template match="ol/li"> 
 <fo:list-item> 
  <fo:list-item-label end-indent="label-end()"> 
   <fo:block> 
    <xsl:variable name="value-attr"> 
     <xsl:choose> 
       
     
    <xsl:when test="../@start"> 
       <xsl:number value="position() + ../@start - 1"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:number value="position()"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:variable> 
    <xsl:choose> 
      
     
    <xsl:when test="../@type='i'"> 
      <xsl:number value="$value-attr" format="i. "/> 
     </xsl:when> 
     <xsl:when test="../@type='I'"> 
      <xsl:number value="$value-attr" format="I. "/> 
     </xsl:when> 
     <xsl:when test="../@type='a'"> 
      <xsl:number value="$value-attr" format="a. "/> 
     </xsl:when> 
     <xsl:when test="../@type='A'"> 
      <xsl:number value="$value-attr" format="A. "/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:number value="$value-attr" format="1. "/> 
     </xsl:otherwise> 
    </xsl:choose> 
   </fo:block> 
  </fo:list-item-label> 
  <fo:list-item-body start-indent="body-start()"> 
   <fo:block> 
    <xsl:apply-templates select="*|text()"/> 
   </fo:block> 
  </fo:list-item-body> 
 </fo:list-item> 
</xsl:template> 
      
    

  這兩個模板將 <ol> 和 <li> 元素轉換成相應的 XSL-FO 元素。

  <p> 段落

  將 Html 段落元素轉換成 <fo:block> 元素比較簡單。例如,考慮下面這個段落:

<p>When in the Course of human events, it becomes necessary 
 for one people to dissolve the political bonds which have connected 
 them with another, and to assume among the powers of the earth, 
 the separate and equal station to which the Laws of Nature and 
 of Nature's God entitle them, a decent respect to the opinions 
 of mankind requires that they should declare the causes which 
 impel them to the separation.</p> 

  該段落將轉換成以下 XSL-FO 標記:

<fo:block font-size="12pt" line-height="15pt 
 space-after="12pt">When in the Course of human events, it becomes 
 necessary for one people to dissolve the political bonds which 
 ... 
</fo:block> 

  下面是進行該轉換的簡單的 XSLT 模板:

<xsl:template match="p"> 
 <fo:block font-size="12pt" line-height="15pt" 
  space-after="12pt"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:block> 
</xsl:template> 

  我們用 font-size 、 line-height 和 space-after 屬性的缺省值實現該模板。顯然,如果願意的話,您可以更改這些值。

  <pre> 預先格式化的文本

  <pre> 元素有幾處復雜之處。需要保留它包含的所有空白域,並且需要關閉 XSL-FO 引擎執行的自動換行。依照約定,還要用等寬字體顯示 <pre> 元素的內容。下面這段摘錄是示例 <pre> 元素:

<pre> 
public static void main(String args[]) 
{ 
 System.out.println("Hello, world!"); 
} 
</pre> 

  要正確處理這個 <pre> 元素示例,必須將其轉換成以下 XSL-FO 標記:

<fo:block font-family="monospace" 
 white-space-collapse="false" 
 wrap-option="no-wrap"> 
public static void main(String args[]) 
{ 
 System.out.println("Hello, world!"); 
} 
</fo:block> 

  進行這一轉換的 XSLT 模板比較簡單:

<xsl:template match="pre"> 
 <fo:block 
     
    font-family="monospace" 
  white-space-collapse="false" 
  wrap-option="no-wrap"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:block> 
</xsl:template> 
      
    

  <samp> 樣本文本

  通常用稍大的等寬字體表示 <samp> 元素。盡管很少使用 <samp> ,但將它轉換成格式化對象很容易。以下是一個樣本 <samp> 元素:

<p>The <samp>DOCTYPE</samp> keyWord lets you 
 refer to a DTD from your XML source document.</p> 

  將其轉換成格式化對象的 XSLT 模板簡短明了:

<xsl:template match="samp"> 
 <fo:inline 
     
    font-family="monospace" 
   font-size="110%"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  <small> 字體較小的文本

  轉換 <small> 元素也很容易。如您所料,它是用較小的字體表示的。因為 <big> 元素的模板用比正常字體大 20% 的 font-size 表示該元素,所以有理由將 <small> 定義為比正常字體小 20%。以下是簡單的 XSLT 模板:

<xsl:template match="small"> 
 <fo:inline 
     
    font-size="80%"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  假如有 <p>The Lakers' chances for a fourth straight title are <small>slim</small>.</p> 這樣一個段落,則模板生成這樣的標記:

<fo:block font-size="12pt" line-height="15pt" space-after="12pt"> 
 The Lakers' chances for a fourth straight title are 
 <fo:inline font-size="80%">slim</fo:inline>. 
</fo:block> 

  和 <big> 元素一樣,在內部相互嵌套多個 <small> 元素會創建逐漸變小的文本。

  <strike> 加刪除線的文本

  實現 Html <strike> 元素比較簡單;創建帶 text-decoration="line-through" 屬性的 <fo:inline> 元素。加刪除線的文本可用於突出顯示文檔中的刪除部分。以下是示例:

<p>The underline property 
 <strike>is not currently supported by FOP.</strike> 
 is now supported by FOP.</p> 

  在顯示時,該段落清楚地表明文本是如何變化的。 <strike> 的 XSLT 模板比較簡短:

<xsl:template match="strike"> 
 <fo:inline 
     
    text-decoration="line-through"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  注: text-decoration 屬性的關鍵字可以是負值也可以是正值。如果出於某種原因而希望在啟用 line-through 的一長段文本中關閉其中一小段具有 line-through 的文本,可以創建一個帶 text-decoration="no-line-through" 屬性的 <fo:inline> 元素。也可以指定多個值;屬性 text-decoration="line-through underline" 同時對文本加刪除線和下劃線。

  <strong> 突出顯示的文本

  通常以粗體字顯示 <strong> 元素。以下是進行該轉換的簡單模板:

<xsl:template match="strong"> 
 <fo:inline 
     
    font-weight="bold"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  <sub> 下標文本

  要處理下標文本,可使用 XSL-FO vertical-align 屬性更改文本的基線。通常還需要縮小字體。以下是一個 Html 樣本:

<p>When I'm thirsty, nothing beats a cold 
 glass of H<sub>2</sub>O.</p> 

  以下是我們的 XSLT 模板:

<xsl:template match="sub"> 
 <fo:inline 
     
    vertical-align="sub" 
    font-size="75%"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  <sup> 上標文本

  正如下標文本一樣,可使用 XSL-FO vertical-align 屬性來處理上標文本。以下是一個 Html 樣本:

<p>Einstein's famous e=mc<sup>2</sup> 
 is an equation that changed the world. </p> 

  以下是我們的 XSLT 模板:

<xsl:template match="sup"> 
 <fo:inline 
     
    vertical-align="super" 
    font-size="75%"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  <table> 表標記

  要處理 Html <table> 元素,最大的難題是確定 XSL-FO 表應該有多少列,以及這些列的寬度。FOP 要求為表中的每一列提供一個 <fo:table-column> 元素。一旦處理完這些列,就只需調用表中所有元素的 XSLT 模板。這一 XSLT 模板處理類似於這樣的 cols :

<table cols="200 100pt" border="1"> 

  需要將 cols 屬性轉換成以下標記:

<fo:table-column column-width="200pt"/> 
<fo:table-column column-width="100pt"/> 

  要實現這一轉換,需要使用常用的被稱為 尾遞歸(tail recursion)的 XSLT 技術。創建這樣一個指定的模板:它使用屬性值的首個單詞,將其轉換成 <fo:table-column> 元素,然後調用自身以處理屬性值的余下部分。最終,處理整個屬性。下面來看這個 XSLT 模板是如何處理 <table> 元素的:

<xsl:template match="table"> 
 <fo:table 
     
    table-layout="fixed"> 
  <xsl:choose> 
    
     
    <xsl:when test="@cols"> 
    <xsl:call-template name="build-columns"> 
     <xsl:with-param name="cols" 
      select="concat(@cols, ' ')"/> 
    </xsl:call-template> 
   </xsl:when> 
   <xsl:otherwise> 
    <fo:table-column column-width="200pt"/> 
   </xsl:otherwise> 
  </xsl:choose> 
  <fo:table-body> 
   <xsl:apply-templates select="*"/> 
  </fo:table-body> 
 </fo:table> 
</xsl:template> 
      
    

  如果有 cols 屬性,則處理器調用 build-columns 模板;否則它創建一個 <fo:table-column> 元素。另請注意: <fo:table> 元素有屬性 table-layout="fixed" ;目前,如果沒有該屬性,FOP 會發出一條警告消息。

  讓我們研究一下 build-columns 模板:

<xsl:template 
     
    name="build-columns"> 
 <xsl:param name="cols"/> 
  
 <xsl:if test="string-length(normalize-space($cols))"> 
  <xsl:variable name="next-col"> 
   <xsl:value-of select="substring-before($cols, ' ')"/> 
  </xsl:variable> 
  <xsl:variable name="remaining-cols"> 
   <xsl:value-of select="substring-after($cols, ' ')"/> 
  </xsl:variable> 
  <xsl:choose> 
   <xsl:when test="contains($next-col, 'pt')"> 
    <fo:table-column column-width="{$next-col}"/> 
   </xsl:when> 
   <xsl:when test="number($next-col) > 0"> 
    <fo:table-column column-width="{concat($next-col, 'pt')}"/> 
   </xsl:when> 
   <xsl:otherwise> 
    <fo:table-column column-width="50pt"/> 
   </xsl:otherwise> 
  </xsl:choose> 
   
  <xsl:call-template name="build-columns"> 
   <xsl:with-param name="cols" select="concat($remaining-cols, ' ')"/> 
  </xsl:call-template> 
 </xsl:if> 
</xsl:template> 
      
    

  首先,模板在除去所有首尾處的空白(這是 XSLT normalize-space() 函數所做的工作)之後檢查 $cols 參數的長度。接下來,它將 $cols 值分為兩部分:第一個空格 之前的子串,和 之後的所有內容。(注:當處理器從 <table> 元素的模板調用該模板時,它將一個空格添加到值的末尾,因此始終至少有一個空格。)

  既然 $cols 參數被分為兩部分,則首先處理第一部分:

  如果值包含字符串 pt ,則假定它是一個類似 200pt 的值,並且生成帶該值的 <fo:table-column> 元素。

  如果值是數字,則將字符串 pt 添加到它的末尾,然後生成 <fo:table-column> 元素。使用 XSLT number() 函數將該值轉換成數字。如果值不是數字(譬如,假設它是 number(xyz) ),則函數返回字符串 NaN (表示不是數字)。

  如果以上兩條規則都不適用,則僅創建 column-width 為 50pt 的新 <fo:table-column> 元素。

  在處理器處理完 $cols 參數的第一部分之後,這個指定的模板用 $cols 參數的最後部分調用自己,並在值的末尾添加一個空格以確保存在空格。

  <td> 表單元

  HTML <td> 元素直接映射至 XSL-FO <fo:table-cell> 元素。缺省情況下,模板要求表單元的頂部、底部以及左右兩邊各留有距離為 3 點的空間。有三種 Html 屬性需要處理: colspan 、 rowspan 和 align 。您還要以有限的方式處理 border 屬性。

  colspan 和 rowspan 屬性直接映射成 XSL-FO number-columns-spanned 和 number-rows-spanned 屬性,因此處理它們並不困難。

  HTML align 屬性映射成 XSL-FO text-align 屬性,但有兩組不同的值。HTML align 的 left 、 center 、 right 和 justify 值映射成 XSL-FO text-align 的 start 、 center 、 end 和 justify 。這裡最後的復雜之處在於可能在 Html <td> 、 <tr> 、 <thead> 或 <table> 元素上出現對齊值,因此必須檢查所有的祖先元素直到找到該值為止。(注:在 <fo:block> 元素上設置 text-align 屬性,而不是在 <fo:table-cell> 上。)

  最後,如果 <td> 、 <tr> 、 <thead> 或 <table> 元素有 border="1" 屬性,則用 border-style="solid" border-color="black" border-width="1pt" 這三個 XSL-FO 屬性在表單元的四周繪制邊框。

  以下是完整的 XSLT 模板,其中的大多數由確定使用哪種 XSL-FO 屬性的 <xsl:choose> 元素所組成:

<xsl:template match="td"> 
  
     
    <fo:table-cell 
  padding-start="3pt" padding-end="3pt" 
  padding-before="3pt" padding-after="3pt"> 
  <xsl:if test="@colspan"> 
   <xsl:attribute name="number-columns-spanned"> 
    <xsl:value-of select="@colspan"/> 
   </xsl:attribute> 
  </xsl:if> 
  <xsl:if test="@rowspan"> 
   <xsl:attribute name="number-rows-spanned"> 
    <xsl:value-of select="@rowspan"/> 
   </xsl:attribute> 
  </xsl:if> 
  <xsl:if test="@border='1' or 
         ancestor::tr[@border='1'] or 
         ancestor::thead[@border='1'] or 
         ancestor::table[@border='1']"> 
   <xsl:attribute name="border-style"> 
    <xsl:text>solid</xsl:text> 
   </xsl:attribute> 
   <xsl:attribute name="border-color"> 
    <xsl:text>black</xsl:text> 
   </xsl:attribute> 
   <xsl:attribute name="border-width"> 
    <xsl:text>1pt</xsl:text> 
   </xsl:attribute> 
  </xsl:if> 
  <xsl:variable name="align"> 
   <xsl:choose> 
    <xsl:when test="@align"> 
     <xsl:choose> 
      <xsl:when test="@align='center'"> 
       <xsl:text>center</xsl:text> 
      </xsl:when> 
      <xsl:when test="@align='right'"> 
       <xsl:text>end</xsl:text> 
      </xsl:when> 
      <xsl:when test="@align='justify'"> 
       <xsl:text>justify</xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:text>start</xsl:text> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:when> 
    <xsl:when test="ancestor::tr[@align]"> 
     <xsl:choose> 
      <xsl:when test="ancestor::tr/@align='center'"> 
       <xsl:text>center</xsl:text> 
      </xsl:when> 
      <xsl:when test="ancestor::tr/@align='right'"> 
       <xsl:text>end</xsl:text> 
      </xsl:when> 
      <xsl:when test="ancestor::tr/@align='justify'"> 
       <xsl:text>justify</xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:text>start</xsl:text> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:when> 
    <xsl:when test="ancestor::thead"> 
     <xsl:text>center</xsl:text> 
    </xsl:when> 
    <xsl:when test="ancestor::table[@align]"> 
     <xsl:choose> 
      <xsl:when test="ancestor::table/@align='center'"> 
       <xsl:text>center</xsl:text> 
      </xsl:when> 
      <xsl:when test="ancestor::table/@align='right'"> 
       <xsl:text>end</xsl:text> 
      </xsl:when> 
      <xsl:when test="ancestor::table/@align='justify'"> 
       <xsl:text>justify</xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:text>start</xsl:text> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:text>start</xsl:text> 
    </xsl:otherwise> 
   </xsl:choose> 
  </xsl:variable> 
   
     
    <fo:block text-align="{$align}"> 
   <xsl:apply-templates select="*|text()"/> 
  </fo:block> 
 </fo:table-cell> 
</xsl:template> 
      
    

  <tfoot> 表頁腳

  很少用到 <tfoot> 元素,它可以創建表頁腳。它包含若干表行( <tr> )元素,每個表行元素包含若干表單元。要處理它,只需調用用於 <tfoot> 元素所包含的 <tr> 元素的 XSLT 模板:

<xsl:template match="tfoot"> 
  
     
    <xsl:apply-templates select="tr"/> 
</xsl:template> 
      
    

  <th> 表頭單元

  Html <th> 元素包含一個表頭單元。要處理它,可創建一個四周邊界寬度為 3 點的 <fo:table-cell> (如前面在 <td> 元素的缺省值中指定的那樣)。 <fo:table-cell> 元素包含一個文本為粗體且居中的 <fo:block> 元素。該模板查找此元素有 border="1" 屬性的祖先元素;如果其中任何一個有這樣的邊界屬性,則該模板相應地設置 XSL-FO 邊界屬性。以下是完整的 XSLT 模板:

<xsl:template match="th"> 
 <fo:table-cell 
   
     
    padding-start="3pt" padding-end="3pt" 
  padding-before="3pt" padding-after="3pt"> 
  <xsl:if test="@border='1' or 
         ancestor::tr[@border='1'] or 
         ancestor::table[@border='1']"> 
   <xsl:attribute name="border-style"> 
    <xsl:text>solid</xsl:text> 
   </xsl:attribute> 
   <xsl:attribute name="border-color"> 
    <xsl:text>black</xsl:text> 
   </xsl:attribute> 
   <xsl:attribute name="border-width"> 
    <xsl:text>1pt</xsl:text> 
   </xsl:attribute> 
  </xsl:if> 
  <fo:block 
     
    font-weight="bold" text-align="center"> 
   <xsl:apply-templates select="*|text()"/> 
  </fo:block> 
 </fo:table-cell> 
</xsl:template> 
      
    

  <thead> 表頭

  處理極少使用的 <thead> 元素和處理 <tfoot> 元素相似。以下是一個簡單的 XSLT 模板:

<xsl:template match="thead"> 
  
     
    <xsl:apply-templates select="tr"/> 
</xsl:template> 
      
    

  <title> 文檔標題

  我們假定所有這些指令都是為了將 FO 文檔最終轉換成 PDF 文件,後者有需要遵循的布局。為完成教程示例中所要求的 PDF 布局,需要將文檔的標題( <Html> 元素中 <head> 元素中的 <title> 元素)設置為大字體、粗體並且位於頁面頂部中央。以下是 XSLT 模板:

<xsl:template match="title"> 
 <fo:block space-after="18pt" line-height="27pt" 
   
     
    font-size="24pt" font-weight="bold" text-align="center"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:block> 
</xsl:template> 
      
    

  <tr> 表行

  HTML <tr> 元素直接映射成 XSL-FO <fo:table-row> 元素。因為處理表的絕大部分工作都在 <td> 元素的模板中,所以現在必須要做的就是創建 <fo:table-row> 並調用 Html <tr> 元素中所包含的每個元素的 XSLT 模板。以下是一個簡單的模板:

<xsl:template match="tr"> 
  
     
    <fo:table-row> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:table-row> 
</xsl:template> 
      
    

  <tt> 電報體文本

  電報體文本是以等寬字體顯示的。以下是 XSLT 模板:

<xsl:template match="tt"> 
 <fo:inline 
     
    font-family="monospace"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  <u> 加下劃線的文本

  要顯示加下劃線的文本,可使用 XSL-FO text-decoration 屬性。以下是簡短的 Html 樣本:

<p>When typewriters ruled the earth, 
 <u>underlining</u> was the most 
 common way to highlight text.</p> 

  當將其轉換成 XSL-FO 時,要使用帶 text-decoration="underline" 屬性的 <fo:inline> 元素:

<xsl:template match="u"> 
 <fo:inline 
     
    text-decoration="underline"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  注: text-decoration 屬性的關鍵字可以是負值也可以是正值。如果出於某種原因而希望在啟用 underline 的一長段文本中關閉其中一小段具有 underline 屬性的文本,則可以創建一個帶 text-decoration="no-underline" 屬性的 <fo:inline> 元素。也可以指定多個值;屬性 text-decoration="underline line-through" 同時對文本加刪除線和下劃線。

  <ul> 無序列表

  無序列表比有序列表和定義列表簡單,因為 <fo:list-item-label> 是所有項的項目符號。以下是用作樣本的 Html 列表:

<p>A few of my favorite albums</p> 
<ul> 
 <li>A Love Supreme</li> 
 <li>Remain in Light</li> 
 <li>London Calling</li> 
 <li>The Indestructible Beat of Soweto</li> 
 <li>The Joshua Tree</li> 
</ul> 

  要用到的 XSL-FO 列表元素有: <fo:list-block> 、 <fo:list-item> 、 <fo:list-item-label> 和 <fo:list-item-body> 。以下是如何將 Html 列表轉換為 XSL-FO:

<fo:block>A few of my favorite albums</fo:block> 
<fo:list-block provisional-distance-between-starts="0.2cm" 
 provisional-label-separation="0.5cm" 
 space-after="12pt" start-indent="1cm"> 
 <fo:list-item> 
  <fo:list-item-label end-indent="label-end()"> 
   <fo:block>•</fo:block> 
  </fo:list-item-label> 
  <fo:list-item-body start-indent="body-start()"> 
   A Love Supreme 
  </fo:list-item-body> 
 </fo:list-item> 
 ... 
 <fo:list-item> 
  <fo:list-item-label end-indent="label-end()"> 
   <fo:block>•</fo:block> 
  </fo:list-item-label> 
  <fo:list-item-body start-indent="body-start()"> 
   The Joshua Tree 
  </fo:list-item-body> 
 </fo:list-item> 
</fo:list-block> 

  該模板使用 Unicode 實體 • 作為項目符號。

  將 <ul> 和 <li> 項轉換成格式化對象的 XSLT 模板在處理 <ul> 元素時遵循以下規則:

  如果該列表出現在另一列表中,則不在其後插入任何空白。

  如果該列表不在任何其它列表中,則將其縮進 1 cm 。否則,它縮進的距離為 1 cm 加上其它每個列表縮進的 1.25 cm 。例如,如果該列表是第三級列表,則將該列表縮進 3.5 cm 。

  以下是 XSLT 模板:

<xsl:template match="ul"> 
 <fo:list-block provisional-distance-between-starts="1cm" 
  provisional-label-separation="0.5cm"> 
  <xsl:attribute name="space-after"> 
   <xsl:choose> 
     
     
    <xsl:when test="ancestor::ul or ancestor::ol"> 
     <xsl:text>0pt</xsl:text> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:text>12pt</xsl:text> 
    </xsl:otherwise> 
   </xsl:choose> 
  </xsl:attribute> 
  <xsl:attribute name="start-indent"> 
   <xsl:variable name="ancestors"> 
    <xsl:choose> 
      
     
    <xsl:when test="count(ancestor::ol) or count(ancestor::ul)"> 
      <xsl:value-of select="1 + 
                 (count(ancestor::ol) + 
                  count(ancestor::ul)) * 
                 1.25"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:text>1</xsl:text> 
     </xsl:otherwise> 
    </xsl:choose> 
   </xsl:variable> 
   <xsl:value-of select="concat($ancestors, 'cm')"/> 
  </xsl:attribute> 
  <xsl:apply-templates select="*"/> 
 </fo:list-block> 
</xsl:template> 
<xsl:template match="ul/li"> 
 <fo:list-item> 
   
     
    <fo:list-item-label end-indent="label-end()"> 
   <fo:block>•</fo:block> 
  </fo:list-item-label> 
  <fo:list-item-body start-indent="body-start()"> 
   <fo:block> 
    <xsl:apply-templates select="*|text()"/> 
   </fo:block> 
  </fo:list-item-body> 
 </fo:list-item> 
</xsl:template> 
      
    

  <var> 變量名

  通常以斜體等寬字體來顯示變量名。使用 XSL-FO font-family 和 font-style 屬性。以下是一個簡短的樣本:

<p>To run the FOP program, you must make sure 
 your <var>classpath</var> variable 
 is set correctly.</p> 

  以下是進行該轉換的 XSLT 模板:

<xsl:template match="var"> 
 <fo:inline 
     
    font-style="italic" 
   font-family="monospace"> 
  <xsl:apply-templates select="*|text()"/> 
 </fo:inline> 
</xsl:template> 
      
    

  本文示例源代碼或素材下載

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved