XSL-FO 高级技术7

概述 第 1 页(共5 页)


XSL-FO 常用于将 HTML 文档转换成 PDF。要做到这一点,使用 XSLT 将 HTML 元素转换成格式化对象,格式化对象是用 XSL-FO 显示的文档的基本构件。然后,再将格式化对象转换成 PDF。本章概述如何将 HTML 文档转换成相应的格式化对象。然后,下一章(使转换技术工作)将使用这些模板自动创建目录和一组书签,最后创建一个样本 PDF 文档。

本章只包含少数几个 HTML 元素来演示基本过程。对于所有我所见到在 PDF 转换中起作用的 HTML 元素,我已经整理了一本更完整的指南,说明它们的格式化对象中的等价对象和 XSLT 转换模板。一旦您学习了本教程中的技术,就可以参考该参考指南(请参阅参考资料)来对具有更多元素的 HTML 文档构建转换模板。

简要说明:本章示例中几乎所有的 XSLT 模板都包含这个元素:


<xsl:apply-templates select="*|text()"/>

该元素告诉 XSLT 处理器获取当前元素的所有文本及其子元素,并转换它们。不管 HTML 元素之间如何嵌套,这一递归技术确保处理所有这些元素。


<body>文档主体 第 2 页(共5 页)


<body> 元素的 XSL-FO 等价元素是 <fo:flow flow-name="xsl-region-body"> 元素。为了保持 HTML 文档和 XSLT 样式表之间的对称,这里的示例将该处理用于 <body> 元素来生成相应的 XSL-FO 元素。对于示例文档,<fo:flow flow-name="xsl-region-body"> 元素包含以下六项:

  • 文档标题(<head> 内的 HTML title 元素)
  • 欢迎消息 developerWorks loves you!
  • developerWorks URL
  • 目录
  • 文档中的所有内容
  • 用于标识文档最后一页的 id

很明显,包括了其中的大部分项,使得文档有预期的布局。您可以更改 XSLT 模板来创建不同布局(例如,或许您喜欢标题页),或者可以使用多个样式表以多种格式显示相同信息。下面是完整的模板:


<xsl:template match="body">
  <fo:flow flow-name="xsl-region-body">
    <!-- Item 1 -->
    <xsl:apply-templates select="/html/head/title"/>

    <!-- Item 2 -->
    <fo:block space-after="12pt" line-height="17pt" 
      font-size="14pt" text-align="center">
      developerWorks loves you!
    </fo:block>

    <!-- Item 3 -->
    <fo:block space-after="24pt" line-height="17pt" 
      font-size="14pt" text-align="center" font-weight="bold" 
      font-family="monospace">
      ibm.com/developerWorks
    </fo:block>

    <!-- Item 4 -->
    <xsl:call-template name="toc"/>

    <!-- Item 5 -->
    <xsl:apply-templates select="*|text()"/>

    <!-- Item 6 -->
    <fo:block id="TheVeryLastPage" font-size="0pt"
      line-height="0pt" space-after="0pt"/>
  </fo:flow>
</xsl:template>


<h1><h6> 标题 第 3 页(共5 页)


转换标题标记相对比较简单;将每个标记放到 <fo:block> 元素中,并根据标题级别更改字体、字体大小和其它属性。要使顶层标题真正突出,示例布局在 <h1> 文本之前放置了分页符和一条水平线。下面是所用的格式化选项:

HTML 标记字体大小线高后面的空格其它
<h1> 28pt32pt22pt在文本的前面添加分页符和一条水平线
<h2> 24pt28pt18pt
<h3> 21pt24pt14pt
<h4> 18pt21pt12pt
<h5> 16pt19pt12pt文本加下划线
<h6> 14pt17pt12pt文本加下划线用斜体字表示

下面是一些标题元素:


<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><h6> 标题 — 模板 第 4 页(共5 页)


<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>水平的直线 第 5 页(共5 页)


有一个特殊的 XSL-FO 元素 <fo:leader>,它是为处理水平的直线而设计的。下面是一些 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(它创建空白区域)的值。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值