This is the mail archive of the docbook-apps@lists.oasis-open.org mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RE: how to do a glossary with htmlhelp.xsl?


I thought about it some more. Seems like this is a better idea. Now you
get a popup in recent versions of IE (don't know how far back it goes)
and a hyperlink in all browsers. You can use css to make .glossterm look
different from other hyperlinks.

While we're on the subject of glossaries, I've pasted three xsls below
that I had a developer write for me. The idea is that you have a master
glossary for your organization which you include as an entity in all
documents that need glossaries. Then you run these three transformations
(weed.xsl, sort.xsl, unique.xsl, in that order) and end up with a
glossary that contains only glossentrys for terms that occur in the
document. I use Saxon for these transformations rather than Xalan. With
this particular set of transformations, there's a big speed difference
between the two processors. The idea from this came from _DocBook, The
Definitive Guide_ 2.10.2.

David

<!-- Add this template to your html or htmlhelp customization layer. It
causes glossterms to have hyperlinks to the corresponding glossentrys
and the text of the glossdef as the "title" of the <a> element. In IE,
this "title" shows up when the pointer hovers over the link. -->

 <xsl:template match="glossterm[@linkend]">

    <xsl:variable name="targets" select="id(@linkend)"/>
    <xsl:variable name="target" select="$targets[1]"/>

    <xsl:call-template name="check.id.unique">
      <xsl:with-param name="linkend" select="@linkend"/>
    </xsl:call-template>
    
    <a class="glossterm">
      <xsl:if test="@id">
        <xsl:attribute name="name">
          <xsl:value-of select="@id"/>
        </xsl:attribute>
     </xsl:if>

	<!-- link to the glossentry corresponding to this glossterm -->

     <xsl:attribute name="href">
      <xsl:call-template name="href.target">
       <xsl:with-param name="object" select="$target"/>
      </xsl:call-template>
     </xsl:attribute>

	<!-- add a "title" attribute to the link which will 
           show up as a "popup" whenever the pointer hovers 
	     over the link in IE. -->
      <xsl:attribute name="title">
        <xsl:value-of select="normalize-space(id(@linkend)/glossdef)"/>
      </xsl:attribute>
      
     <xsl:call-template name="inline.charseq"/>
    </a>
 </xsl:template>



weed.xsl (Run this one first. Adds a glossentry into the result document
everytime it comes across a glossterm.):

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="book">
  <!-- Make sure that there's only one glossary in the document -->
  <xsl:if test="count(//glossary) > 1">
    <xsl:message terminate="yes">This version of the glossificator
supports only one glossary element</xsl:message>
  </xsl:if>

  <xsl:copy>
   <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
 </xsl:template>

 <xsl:template match="@*|node()">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
 </xsl:template>

 <xsl:template match="glossary">
  <xsl:copy>
   <xsl:apply-templates select="@*"/>

   <!-- This select needs to match all of the glossterms in the body of
the
        document, but not the ones in the glossary itself.  Those will
be
        pulled in recursively as 'glossentry's are added. -->
   <xsl:for-each select="//glossterm">
    <!-- This "if" element makes sure that we don't pull in glossterms
that
         have a "glossary" element ancestor. -->
    <xsl:if test="count(ancestor::glossary) = 0"> 
     <xsl:call-template name="add-glossary-term">
      <xsl:with-param name="term">
       <xsl:value-of select="@linkend" />
      </xsl:with-param>
      <xsl:with-param name="stack">/</xsl:with-param>
     </xsl:call-template>
    </xsl:if>
   </xsl:for-each>

  </xsl:copy>
 </xsl:template>

 <xsl:template name="add-glossary-term">
  <xsl:param name="term" />
  <xsl:param name="stack" />

  <!-- Add this term only if it's not in our current glossterm stack.
This
       will ensure that we don't have any cycles. -->
  <xsl:if test="not(contains($stack,concat('/',$term,'/')))">

   <xsl:for-each select="//glossary//glossentry[@id=$term]">
    <xsl:message>Adding glossary entry: <xsl:value-of
select="@id"/></xsl:message>
    <xsl:copy-of select="." />

    <xsl:for-each select=".//glossterm">

      <xsl:call-template name="add-glossary-term">
       <xsl:with-param name="term">
        <xsl:value-of select="@linkend" />
       </xsl:with-param>
       <xsl:with-param name="stack"><xsl:value-of select="$stack"
/><xsl:value-of select="$term" />/</xsl:with-param>
      </xsl:call-template>

    </xsl:for-each>

    <xsl:for-each select="(.//glosssee|.//glossseealso)">

      <xsl:call-template name="add-glossary-term">
       <xsl:with-param name="term">
        <xsl:value-of select="@otherterm" />
       </xsl:with-param>
       <xsl:with-param name="stack"><xsl:value-of select="$stack"
/><xsl:value-of select="$term" />/</xsl:with-param>
      </xsl:call-template>

    </xsl:for-each>

   </xsl:for-each>
  </xsl:if>

 </xsl:template>

</xsl:stylesheet>


sort.xsl (Sorts the glossentrys):

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="glossary">
  <xsl:copy>
   <xsl:apply-templates select="@*"/>
   <xsl:apply-templates select="glossentry">
    <xsl:sort select="glossterm" />
   </xsl:apply-templates>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="@*|node()">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
 </xsl:template>

</xsl:stylesheet>

unique.xsl (removes duplicate entries):

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:output
   method="xml"
   doctype-public="-//OASIS//DTD DocBook XML V4.1.2//EN"
 
doctype-system="http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd
" />

 <xsl:template match="glossary">
  <xsl:copy>
   <xsl:apply-templates select="@*"/>
   <xsl:for-each select="glossentry">

<xsl:message><xsl:value-of select="@id"/> : <xsl:value-of
select="position()"/></xsl:message>

    <xsl:if test="position() = last() or
	          ./@id !=
following-sibling::glossentry[position()=1]/@id">
      <xsl:apply-templates select="." />
    </xsl:if>
   </xsl:for-each>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="@*|node()">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
 </xsl:template>

</xsl:stylesheet>


----------------------------------------------------------------
To subscribe or unsubscribe from this elist use the subscription
manager: <http://lists.oasis-open.org/ob/adm.pl>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]