3.3. Transformera till DocBook

I tables.xml har vi nu ett 'well-formed' XML dokument. Detta skall nu mappas mot docbook. XSL-transformering är precis vad docbook i XML går ut på. En XML-parser validerar dokumentet som skall översättas, mot en DTD, docbooks DTD. Om det är OK kan processen med att skapa måldokumentet fortsätta. Skapandet av måldokumentet sker genom att köra det genom ett antal XSL-stylesheet, som byter docbook-taggarna mot t.ex. HTML-taggar.

Problemet här, är att tables.xml inte alls stämmer med docbooks DTD. Vi löser det med att skicka in det i ett eget XSL-stylesheet, som byter ut XML-taggarna från make_tables.tcl till docbook-XML-taggar. Detta stylesheet kallar vi to_docbook_table.xsl. Om det verkar helt obegripligt, så gör det inte så mycket, XSL är inte helt enkelt.

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml"/>

  <!-- Main -->
  <xsl:template match="/">
    <chapter> <!-- document root -->
      <title>
        Database Table Description
      </title>
      <xsl:apply-templates/>
    </chapter>
  </xsl:template>

  <!-- The table -->
  <xsl:template match="Tables">
    <para>  <!-- found node Tables, print something and continue -->
       This chapter was autogenerated to document the
       structure of database tables used in project XXX.
    </para>
    <xsl:apply-templates/>
  </xsl:template>

  <!-- The tables -->
  <xsl:template match="Table">
  <!-- Inside a table node, start a new section-->
    <xsl:variable name="Table_Name" select="Name"/>
    <sect1 id="{$Table_Name}">
      <title>
        <xsl:value-of select="$Table_Name"/>
      </title>
      <xsl:apply-templates/>
    </sect1>
  </xsl:template>

  <xsl:template match="Name"/>         <!-- surpress output again-->
  <xsl:template match="Description"/>  <!-- surpress output again -->

  <!-- Keys -->
  <xsl:template match="Keys">
  <!-- If there are any keys, process them, else say they are missing-->
    <xsl:choose>
      <xsl:when test="count(Key) > 0">
        <table>
          <title>Keys in <xsl:value-of select="../Name"/> </title>
          <tgroup cols="4">
            <thead>
              <row>
                <entry> Name </entry>
                <entry> Primary? </entry>
                <entry> Unique? </entry>
                <entry> Definition </entry>
              </row>
            </thead>
            <tbody>
              <xsl:apply-templates/>
            </tbody>
          </tgroup>
        </table>
      </xsl:when>
      <xsl:otherwise>
        <para>
          There are no keys.
        </para>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="Key">
  <!-- Fill the table -->
    <row>
      <entry>
        <xsl:value-of select="Name"/>
      </entry>
      <entry>
        <xsl:value-of select="IsPrimary"/>
      </entry>
      <entry>
        <xsl:value-of select="IsUnique"/>
      </entry>
      <entry>
        <xsl:value-of select="Definition"/>
      </entry>
    </row>
  </xsl:template>

  <!-- Relations -->
  <xsl:template match="Relations">
    <xsl:choose>
      <xsl:when test="count(Relation) > 0">
        <table>
          <title>Relations for <xsl:value-of select="../Name"/> </title>
          <tgroup cols="5">
            <thead>
              <row>
                <entry> Description </entry>
                <entry> Constraints </entry>
                <entry> # of keys </entry>
                <entry> Index </entry>
                <entry> Foreign keys </entry>
              </row>
            </thead>
            <tbody>
              <xsl:apply-templates/>
            </tbody>
          </tgroup>
        </table>
      </xsl:when>
      <xsl:otherwise>
        <para>
          There are no relations.
        </para>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="Relation">
    <row>
      <entry>
        <xsl:value-of select="Relatedtable"/>
      </entry>
      <entry>
        <xsl:value-of select="Delconstr"/>
      </entry>
      <entry>
        <xsl:value-of select="Keyno"/>
      </entry>
      <entry>
        <xsl:value-of select="Index"/>
      </entry>
      <entry>
        <xsl:value-of select="Foreignkeyfields"/>
      </entry>
    </row>
  </xsl:template>

  <!-- Fields -->
  <xsl:template match="Fields">
    <xsl:choose>
      <xsl:when test="count(Fielddesc) > 0">
        <table>
          <title>Fields in <xsl:value-of select="../Name"/></title>
          <tgroup cols="5">
            <thead>
              <row>
                <entry> Fieldname </entry>
                <entry> Type </entry>
                <entry> Not null? </entry>
                <entry> Has defult? </entry>
                <entry> Field number </entry>
              </row>
            </thead>
            <tbody>
              <xsl:apply-templates/>
            </tbody>
          </tgroup>
        </table>
      </xsl:when>
      <xsl:otherwise>
        <para>
          There are no fields.
        </para>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="Fielddesc">
    <row>
      <entry>
        <xsl:value-of select="Name"/>
      </entry>
      <entry>
        <xsl:value-of select="Type"/>
      </entry>
      <entry>
        <xsl:value-of select="NotNull"/>
      </entry>
      <entry>
        <xsl:value-of select="HasDef"/>
      </entry>
      <entry>
        <xsl:value-of select="FieldNum"/>
      </entry>
    </row>
  </xsl:template>
</xsl:stylesheet>
    

Om du nu har orkat hänga med, så är resten ganska enkelt. Vi vill skapa docbook_tables.xml som är datat från tables.xml, fast med docbook-syntax. Dags att utnyttja Saxon. Saxon behöver en del parametrar, så vi skapar en Makefile, som vi bygger på efter hand. Justera sökvägarna efter ditt system.

Vi skapar en katalogstrukur enligt nedan


[bnl@della docbook_xml]$tree
|-- source
|   |-- Makefile
|   |-- datamodel.xml
|   |-- make_tables.tcl
|   |-- tables.xml
|   `-- to_docbook_table.xsl
`-- target
    |-- html
    |-- html_one
    `-- pdf
      
    
där Makefile ser ut så här:
#A list over source files
SRC=datamodel.xml docbook_tables.xml tables.xml to_docbook_table.xsl
DB=/usr/share/sgml/docbook/xsl-stylesheets
SAXON=/home/bnl/distributions/java/saxon.jar
TARGET=/home/bnl/public_html/sslug/docbook_xml/target

OPTIONS=paper.type=A4 \
        admon.graphics=1 \
        admon.graphics.path=$(DB)/images/ \
        use.extensions=1 \
        fop.extensions=1 \
        section.autolabel=1 \
        callout.graphics.path=$(DB)/images/callouts/ \
        tablecolumns.extension=0

#What to do when just 'make' is run
all: docbook_tables.xml

docbook_tables.xml: tables.xml
        java -jar $(SAXON) tables.xml  to_docbook_table.xsl \
        $(OPTIONS) > docbook_tables.xml
    
Skapa docbook_tables.xml genom att skriva:

[bnl@della source]$make docbook_tables.xml
    
Vi har nu allt vi behöer för att komma i mål