Преобразование в XSL-FO при помощи таблицы стилей XSLT

Преобразование в XSL-FO при помощи таблицы стилей XSLT

В этой главе я создам таблицу стилей для преобразования planets.xml в planets.fo. Я буду создавать таблицу шаг за шагом; для справки я приведу ее окончательный вид (листинг 11.2).

Листинг 11.2. planets.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:template match="PLANETS">

  <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

   <fo:layout-master-set>

    <fo:simple-page-master master-name="page"

     page-height="400mm" page-width="300mm"

     margin-top="10mm" margin-bottom="10mm"

     margin-left="20mm" margin-right="20mm">

     <fo:region-body

      margin-top="0mm" margin-bottom="10mm"

      margin-left="0mm" margin-right="0mm"/>

     <fo:region-after extent="10mm"/>

    </fo:simple-page-master>

   </fo:layout-master-set>

   <fo:page-sequence master-name="page">

    <fo:flow flow-name="xsl-region-body">

     <fo:block font-weight="bold" font-size="36pt"

      line-height="48pt" font-family="Times" color="blue">

      The Planets Table

     </fo:block>

     <xsl:apply-templates/>

    </fo:flow>

   </fo:page-sequence>

  </fo:root>

 </xsl:template>

 <xsl:template match="PLANET/NAME">

  <fo:block font-weight="bold" font-size="28pt"

   line-height="48pt" font-family="Times"

   font-style="italic">

   Planet:

   <xsl:apply-templates/>

  </fo:block>

 </xsl:template>

 <xsl:template match="PLANET/MASS">

  <fo:block font-size="24pt" line-height="32pt"

   font-family="Times">

   <fo:inline text-decoration="underline">

    Mass

   </fo:inline>:

   <xsl:apply-templates/>

   [Earth = 1]

  </fo:block>

 </xsl:template>

 <xsl:template match="PLANET/DAY">

  <fo:block font-size="24pt" line-height="32pt"

   font-family="Times">

   <fo:inline text-decoration="underline">

    Day

   </fo:inline>:

   <xsl:apply-templates/>

   [Earth = 1]

  </fo:block>

 </xsl:template>

 <xsl:template match="PLANET/RADIUS">

  <fo:block font-size="24pt" line-height="32pt"

   font-family="Times">

   <fo:inline text-decoration="underline">

    Radius

   </fo:inline>:

   <xsl:apply-templates/>

   miles

  </fo:block>

 </xsl:template>

 <xsl:template match="PLANET/DENSITY">

  <fo:block font-size="24pt" line-height="32pt"

   font-family="Times">

   <fo:inline text-decoration="underline">

    Density

   </fo:inline>:

   <xsl:apply-templates/>

   [Earth = 1]

  </fo:block>

 </xsl:template>

 <xsl:template match="PLANET/DISTANCE">

  <fo:block font-size="24pt" line-height="32pt"

   font-family="Times">

   <fo:inline text-decoration="underline">

    Distance

   </fo:inline>:

   <xsl:apply-templates/>

   million miles

  </fo:block>

 </xsl:template>

</xsl:stylesheet>

После применения этой таблицы стилей для преобразования planets.xsl будет получен файл planets.fo, который при помощи форматирующих объектов XSL-FO создает документ с видом, показанным на рис. 11.1. Вот как выглядит planets.fo (листинг 11.3).

Листинг 11.3. planets.fo

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

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

 <fo:layout-master-set>

  <fo:simple-page-master margin-right="20mm"

   margin-left="20mm" margin-bottom="10mm"

   margin-top="10mm" page-width="300mm"

   page-height="400mm" master-name="page">

   <fo:region-body margin-right="0mm" margin-left="0mm"

    margin-bottom="10mm" margin-top="0mm"/>

   <fo:region-after extent="10mm"/>

  </fo:simple-page-master>

 </fo:layout-master-set>

 <fo:page-sequence master-name="page">

  <fo:flow flow-name="xsl-region-body">

   <fo:block color="blue" font-family="Times"

    line-height="48pt" font-size="36pt" font-weight="bold">

    The Planets Table

   </fo:block>

   <fo:block font-style="italic" font-family="Times"

    line-height="48pt" font-size="28pt" font-weight="bold">

    Planet:

    Mercury

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Mass

    </fo:inline>:

    .0553

    [Earth = 1]

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fо:inline text-decoration="underline">

     Day

    </fo:inline>:

    58.65

    [Earth = 1]

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Radius

    </fo:inline>:

    1516

    miles

   </fo:block>

   <fo:block font-family="Times" line height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Density

    </fo:inline>:

    .983

    [Earth = 1]

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Distance

    </fo:inline>:

    43.4

    million miles

   </fo:block>

   <fo:block font-style="italic" font-family="Times" line-height="48pt"

    font-size="28pt" font-weight="bold">

    Planet:

    Venus

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Mass

    </fo:inline>:

    .815

    [Earth = 1]

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Day

    </fo:inline>:

    116.75

    [Earth = 1]

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Radius

    </fo:inline>:

    3716

    miles

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Density

    </fo:inline>:

    .943

    [Earth = 1]

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Distance

    </fo:inline>:

    66.8

    million miles

   </fo:block>

   <fo:block font-style="italic" font-family="Times" line-height="48pt"

    font-size="28pt" font-weight="bold">

    Planet:

    Earth

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Mass

    </fo:inline>:

    1

    [Earth = 1]

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Day

    </fo:inline>:

    1

    [Earth = 1]

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Radius

    </fo:inline>:

    2107

    miles

   </fo:block>

   <fo:block font-family="Times" line-height="32pt" font-size="24pt">

    <fo:inline text-decoration="underline">

     Density

    </fo:inline>:

    1

    [Earth = 1]

    </fo:block>

    <fo:block font-family=Times" line-height="32pt" font-size="24pt">

     <fo:inline text-decoration="underline">

      Distance

     </fo:inline>:

     128.4

     million miles

    </fo:block>

   </fo:flow>

  </fo:page-sequence>

</fo:root>

Для того чтобы обработать planets.fo и создать форматированный документ, я воспользуюсь процессором fop от Apache XML Project. Как утверждает Apache: «FOP — первое в мире средство форматирования, управляемое форматирующими объектами XSL. Приложение Java считывает дерево форматирующих объектов и затем преобразует его в документ PDF. Дерево форматирующих объектов может быть представлено в форме документа XML (полученного на выходе такого процессора XSLT, как XT или Xalan) или может быть передано в память как документ DOM или (в случае XT) событий SAX».

Я пользуюсь fop 0.17, — последней версией процессора на момент написания книги (похоже, что новые версии выходят практически ежемесячно). Процессор fop можно бесплатно загрузить с http://xml.apache.org/fop. Пакет загрузки fop включает три необходимых для работы файла JAR: fop.jar, w3c.jar и xerces.jar, которые нужно включить в classpath (добавьте правильные пути к этим файлам JAR в соответствии с требованиями вашей системы):

С:>set classpath=.;fop.jar;xerces.jar;w3c.jar

Для преобразования planets.fo в planets.pdf служит класс fop org.apache.fop.apps.CommandLine, которому в командной строке нужно передать имя входного документа, planets.fo, и имя выходного, planets.pdf:

C:>java org.apache.fop.apps.CommandLine planets.fo planets.pdf

Вот и все; окончательный результат, planets.pdf, в средстве просмотра Adobe Acrobat Reader вы увидите, если вернетесь к рис. 11.1.

Теперь вы видели, как выполняется процедура в общем; давайте перейдем к деталям и посмотрим, как создаются документы XSL-FO. Чтобы подробно все рассмотреть, я собираюсь взять за основу листинг 11.2, таблицу стилей XSLT, создающую planets.fo.

СОЗДАНИЕ ДОКУМЕНТОВ XSL-FO С НУЛЯ

Заметьте, что не обязательно создавать таблицу стилей для преобразования документов XSL в форму XSL-FO. Я мог бы написать planets.fo так, как показано в листинге 11.3, с нуля, не прибегая к таблицам стилей XSLT. Но такой способ, как правило, годится только для коротких документов XML. Документы с форматированием XSL-FO становятся весьма длинными очень быстро (сравните длину planets.xml с planets.fo), поэтому для создания документов XSL-FO практически всегда применяйте таблицы стилей XSLT (хотя некоторые примеры в следующей главе достаточно коротки для того, чтобы написать их непосредственно при помощи XSL-FO).