]> granicus.if.org Git - docbook-dsssl/commitdiff
Integrate support for three indexing methods:
authorBob Stayton <bobs@sagehill.net>
Sun, 14 May 2006 04:33:40 +0000 (04:33 +0000)
committerBob Stayton <bobs@sagehill.net>
Sun, 14 May 2006 04:33:40 +0000 (04:33 +0000)
- the original English-only method.
- Jirka Kosek's method using EXSLT extensions.
- Eliot Kimber's method using Saxon extensions.
Use the 'index.method' parameter to select.

xsl/fo/autoidx.xsl

index 1d549ba02903861d93e06cbe74f1b55182498dea..0c99fe16f61a7081c9310819679c9a71fefddf51 100644 (file)
@@ -4,11 +4,15 @@
 <!ENTITY lowercase "'abcdefghijklmnopqrstuvwxyz'">
 <!ENTITY uppercase "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'">
 
-<!ENTITY primary   'normalize-space(concat(primary/@sortas, primary[not(@sortas)]))'>
-<!ENTITY secondary 'normalize-space(concat(secondary/@sortas, secondary[not(@sortas)]))'>
-<!ENTITY tertiary  'normalize-space(concat(tertiary/@sortas, tertiary[not(@sortas)]))'>
+<!ENTITY primary   'normalize-space(concat(primary/@sortas, primary[not(@sortas) or @sortas = ""]))'>
+<!ENTITY secondary 'normalize-space(concat(secondary/@sortas, secondary[not(@sortas) or @sortas = ""]))'>
+<!ENTITY tertiary  'normalize-space(concat(tertiary/@sortas, tertiary[not(@sortas) or @sortas = ""]))'>
 
 <!ENTITY sep '" "'>
+<!-- Documents using the kimber index method must have a lang attribute -->
+<!-- Only one of these should be present in the entity -->
+
+<!ENTITY lang 'concat(/*/@lang, /*/@xml:lang, "en")'>
 <!ENTITY scope 'count(ancestor::node()|$scope) = count(ancestor::node())
                 and ($role = @role or $type = @type or
                 (string-length($role) = 0 and string-length($type) = 0))'>
                 xmlns:fo="http://www.w3.org/1999/XSL/Format"
                 xmlns:rx="http://www.renderx.com/XSL/Extensions"
                 xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions"
+                xmlns:i="urn:cz-kosek:functions:index"
+                xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"
+                xmlns:func="http://exslt.org/functions"
+                xmlns:k="java:com.isogen.saxoni18n.Saxoni18nService"
+                xmlns:exslt="http://exslt.org/common"
+                extension-element-prefixes="func exslt"
+                exclude-result-prefixes="func exslt i l k"
                 version="1.0">
 
 <!-- ********************************************************************
      ******************************************************************** -->
 
 <!-- ==================================================================== -->
-<!-- Derived from Jeni Tennison's work in the HTML case -->
+<!-- The "english" method derived from Jeni Tennison's work. -->
+<!-- The "kosek" method contributed by Jirka Kosek. -->
+<!-- The "kimber" method contributed by Eliot Kimber of Innodata Isogen. -->
 
+<!-- These keys used primary in all methods -->
 <xsl:key name="letter"
          match="indexterm"
          use="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/>
 
 <xsl:key name="see-also"
          match="indexterm[seealso]"
-         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, seealso)"/>
+         use="concat(&primary;, &sep;, 
+                     &secondary;, &sep;, 
+                     &tertiary;, &sep;, seealso)"/>
 
 <xsl:key name="see"
          match="indexterm[see]"
-         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, see)"/>
+         use="concat(&primary;, &sep;, 
+                     &secondary;, &sep;, 
+                     &tertiary;, &sep;, see)"/>
+
+
+<!-- The following key is used in the kimber indexing method.
+     To use this method, either copy this key to a
+     customization layer, or xsl:import common/autoidx.xsl. -->
+<!--
+<xsl:key name="k-group"
+         match="indexterm"
+         use="k:getIndexGroupKey(&lang;, &primary;)"/>
+-->
+
 
 <xsl:template name="generate-index">
   <xsl:param name="scope" select="(ancestor::book|/)[last()]"/>
 
+  <xsl:choose>
+    <xsl:when test="$index.method = 'kosek'">
+      <xsl:call-template name="generate-kosek-index">
+        <xsl:with-param name="scope" select="$scope"/>
+      </xsl:call-template>
+    </xsl:when>
+    <xsl:when test="$index.method = 'kimber'">
+      <xsl:call-template name="generate-kimber-index">
+        <xsl:with-param name="scope" select="$scope"/>
+      </xsl:call-template>
+    </xsl:when>
+
+    <xsl:otherwise>
+      <xsl:call-template name="generate-english-index">
+        <xsl:with-param name="scope" select="$scope"/>
+      </xsl:call-template>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+      
+<xsl:template name="generate-english-index">
+  <xsl:param name="scope" select="NOTANODE"/>
+
   <xsl:variable name="role">
     <xsl:if test="$index.on.role != 0">
       <xsl:value-of select="@role"/>
   </xsl:variable>
 
   <xsl:variable name="terms"
-                select="//indexterm[count(.|key('letter',
-                                                translate(substring(&primary;, 1, 1),
-                                                          &lowercase;,
-                                                          &uppercase;))[&scope;][1]) = 1
-                                    and not(@class = 'endofrange')]"/>
+                select="//indexterm
+                        [count(.|key('letter',
+                          translate(substring(&primary;, 1, 1),
+                             &lowercase;,
+                             &uppercase;))
+                          [&scope;][1]) = 1
+                          and not(@class = 'endofrange')]"/>
 
   <xsl:variable name="alphabetical"
                 select="$terms[contains(concat(&lowercase;, &uppercase;),
                                         substring(&primary;, 1, 1))]"/>
 
-  <xsl:variable name="others" select="$terms[not(contains(concat(&lowercase;,
-                                                 &uppercase;),
-                                             substring(&primary;, 1, 1)))]"/>
+  <xsl:variable name="others" select="$terms[not(contains(
+                                        concat(&lowercase;,
+                                        &uppercase;),
+                                        substring(&primary;, 1, 1)))]"/>
   <fo:block>
     <xsl:if test="$others">
       <xsl:call-template name="indexdiv.title">
           <xsl:with-param name="scope" select="$scope"/>
           <xsl:with-param name="role" select="$role"/>
           <xsl:with-param name="type" select="$type"/>
-          <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
+          <xsl:sort select="translate(&primary;, &lowercase;, 
+                            &uppercase;)"/>
         </xsl:apply-templates>
       </fo:block>
     </xsl:if>
 
     <xsl:apply-templates select="$alphabetical[count(.|key('letter',
                                  translate(substring(&primary;, 1, 1),
-                                           &lowercase;,&uppercase;))[&scope;][1]) = 1]"
-                         mode="index-div">
+                                           &lowercase;,&uppercase;))
+                                           [&scope;][1]) = 1]"
+                         mode="index-div-english">
       <xsl:with-param name="scope" select="$scope"/>
       <xsl:with-param name="role" select="$role"/>
       <xsl:with-param name="type" select="$type"/>
   </fo:block>
 </xsl:template>
 
-<xsl:template match="indexterm" mode="index-div">
+<xsl:template name="generate-kosek-index">
+  <xsl:param name="scope" select="NOTANODE"/>
+
+  <xsl:variable name="vendor" select="system-property('xsl:vendor')"/>
+  <xsl:if test="contains($vendor, 'libxslt')">
+    <xsl:message terminate="yes">
+      <xsl:text>ERROR: the 'kosek' index method does not </xsl:text>
+      <xsl:text>work with the xsltproc XSLT processor.</xsl:text>
+    </xsl:message>
+  </xsl:if>
+
+
+  <xsl:if test="not(function-available('exslt:node-set'))">
+    <xsl:message terminate="yes">
+      <xsl:text>ERROR: the 'kosek' index method requires the </xsl:text>
+      <xsl:text>exslt:node-set() function. Use a processor that </xsl:text>
+      <xsl:text>has it, or use a different index method.</xsl:text>
+    </xsl:message>
+  </xsl:if>
+
+  <xsl:if test="not(function-available('i:group-index'))">
+    <xsl:message terminate="yes">
+      <xsl:text>ERROR: the 'kosek' index method requires the&#xA;</xsl:text>
+      <xsl:text>index extension functions be imported:&#xA;</xsl:text>
+      <xsl:text>  xsl:import href="common/autoidx-ng.xsl"</xsl:text>
+    </xsl:message>
+  </xsl:if>
+
+  <xsl:variable name="role">
+    <xsl:if test="$index.on.role != 0">
+      <xsl:value-of select="@role"/>
+    </xsl:if>
+  </xsl:variable>
+
+  <xsl:variable name="type">
+    <xsl:if test="$index.on.type != 0">
+      <xsl:value-of select="@type"/>
+    </xsl:if>
+  </xsl:variable>
+
+  <xsl:variable name="terms"
+                select="//indexterm[count(.|key('group-code',
+                                          i:group-index(&primary;))
+                                          [&scope;][1]) = 1
+                                and not(@class = 'endofrange')]"/>
+  <fo:block>
+    <xsl:apply-templates select="$terms" mode="index-div-kosek">
+      <xsl:with-param name="scope" select="$scope"/>
+      <xsl:with-param name="role" select="$role"/>
+      <xsl:with-param name="type" select="$type"/>
+      <xsl:sort select="i:group-index(&primary;)" data-type="number"/>
+    </xsl:apply-templates>
+  </fo:block>
+</xsl:template>
+
+
+<xsl:template name="generate-kimber-index">
+  <xsl:param name="scope" select="NOTANODE"/>
+
+  <xsl:variable name="vendor" select="system-property('xsl:vendor')"/>
+  <xsl:if test="not(contains($vendor, 'SAXON '))">
+    <xsl:message terminate="yes">
+      <xsl:text>ERROR: the 'kimber' index method requires the </xsl:text>
+      <xsl:text>Saxon version 6 XSLT processor.</xsl:text>
+    </xsl:message>
+  </xsl:if>
+
+  <xsl:if test="not(function-available('k:getIndexGroupKey'))">
+    <xsl:message terminate="yes">
+      <xsl:text>ERROR: the 'kimber' index method requires the </xsl:text>
+      <xsl:text>Innodata Isogen &#x0A;Java extensions for </xsl:text>
+      <xsl:text>internationalized indexes. &#x0A;Install those </xsl:text>
+      <xsl:text>extensions, or use a different index method.&#x0A;</xsl:text>
+      <xsl:text>For more information, see:&#x0A;</xsl:text>
+      <xsl:text>http://www.innodata-isogen.com/knowledge_center/tools_downloads/i18nsupport</xsl:text>
+    </xsl:message>
+  </xsl:if>
+
+  <xsl:if test="not(function-available('i:group-index'))">
+    <xsl:message terminate="yes">
+      <xsl:text>ERROR: the 'kimber' index method requires the&#xA;</xsl:text>
+      <xsl:text>index extension functions be imported:&#xA;</xsl:text>
+      <xsl:text>  xsl:import href="common/autoidx-ng.xsl"</xsl:text>
+    </xsl:message>
+  </xsl:if>
+
+  <xsl:variable name="role">
+    <xsl:if test="$index.on.role != 0">
+      <xsl:value-of select="@role"/>
+    </xsl:if>
+  </xsl:variable>
+
+  <xsl:variable name="type">
+    <xsl:if test="$index.on.type != 0">
+      <xsl:value-of select="@type"/>
+    </xsl:if>
+  </xsl:variable>
+
+  <xsl:variable name="terms"
+                select="//indexterm[count(.|key('k-group',
+                   k:getIndexGroupKey(&lang;, &primary;))
+                   [&scope;][1]) = 1
+                   and not(@class = 'endofrange')]"/>
+
+  <xsl:variable name="alphabetical"
+                select="$terms[not(starts-with(
+                k:getIndexGroupKey(&lang;, &primary;),
+                '#NUMERIC'
+                ))]"/>
+
+  <xsl:variable name="others"
+                select="$terms[starts-with(
+                k:getIndexGroupKey(&lang;, &primary;),
+                '#NUMERIC'
+                )]"/>
+
+  <fo:block>
+    <xsl:if test="$others">
+      <xsl:call-template name="indexdiv.title">
+        <xsl:with-param name="titlecontent">
+          <xsl:call-template name="gentext">
+            <xsl:with-param name="key" select="'index symbols'"/>
+          </xsl:call-template>
+        </xsl:with-param>
+      </xsl:call-template>
+
+      <fo:block>
+        <xsl:apply-templates select="$others"
+                             mode="index-symbol-div">
+          <xsl:with-param name="scope" select="$scope"/>
+          <xsl:with-param name="role" select="$role"/>
+          <xsl:with-param name="type" select="$type"/>
+          <xsl:sort lang="&lang;"
+              select="k:getIndexGroupSortKey(&lang;,
+                      k:getIndexGroupKey(&lang;, &primary;))"/>
+        </xsl:apply-templates>
+      </fo:block>
+    </xsl:if>
+
+    <xsl:apply-templates select="$alphabetical"
+                         mode="index-div-kimber">
+      <xsl:with-param name="scope" select="$scope"/>
+      <xsl:with-param name="role" select="$role"/>
+      <xsl:with-param name="type" select="$type"/>
+      <xsl:sort lang="&lang;"
+             select="k:getIndexGroupSortKey(&lang;,
+                     k:getIndexGroupKey(&lang;, &primary;))"/>
+    </xsl:apply-templates>
+  </fo:block>
+
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-div-english">
   <xsl:param name="scope" select="."/>
   <xsl:param name="role" select="''"/>
   <xsl:param name="type" select="''"/>
 
   <xsl:variable name="key"
-                select="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/>
+                select="translate(substring(&primary;, 1, 1),
+                         &lowercase;,&uppercase;)"/>
 
   <xsl:if test="key('letter', $key)[&scope;]
                 [count(.|key('primary', &primary;)[&scope;][1]) = 1]">
       </xsl:if>
       <fo:block xsl:use-attribute-sets="index.entry.properties">
         <xsl:apply-templates select="key('letter', $key)[&scope;]
-                                     [count(.|key('primary', &primary;)[&scope;][1])=1]"
+                                     [count(.|key('primary', &primary;)
+                                     [&scope;][1])=1]"
                              mode="index-primary">
           <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
           <xsl:with-param name="scope" select="$scope"/>
   </fo:block>
 </xsl:template>
 
+<xsl:template match="indexterm" mode="index-div-kosek">
+  <xsl:param name="scope" select="."/>
+  <xsl:param name="role" select="''"/>
+  <xsl:param name="type" select="''"/>
+
+  <xsl:variable name="key"
+                select="i:group-index(&primary;)"/>
+
+  <xsl:variable name="lang">
+    <xsl:call-template name="l10n.language"/>
+  </xsl:variable>
+
+  <xsl:if test="key('group-code', $key)[&scope;]
+                [count(.|key('primary', &primary;)[&scope;][1]) = 1]">
+    <fo:block>
+      <xsl:call-template name="indexdiv.title">
+        <xsl:with-param name="titlecontent">
+          <xsl:choose>
+            <xsl:when test="$key = 0">
+              <xsl:call-template name="gentext">
+                <xsl:with-param name="key" select="'index symbols'"/>
+              </xsl:call-template>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:value-of select="i:group-letter($key)"/>
+            </xsl:otherwise>
+          </xsl:choose>
+        </xsl:with-param>
+      </xsl:call-template>
+      <fo:block>
+        <xsl:apply-templates select="key('group-code', $key)[&scope;]
+                                     [count(.|key('primary', &primary;)
+                                     [&scope;][1])=1]"
+                             mode="index-primary">
+          <xsl:sort select="&primary;" lang="{$lang}"/>
+          <xsl:with-param name="scope" select="$scope"/>
+          <xsl:with-param name="role" select="$role"/>
+          <xsl:with-param name="type" select="$type"/>
+        </xsl:apply-templates>
+      </fo:block>
+    </fo:block>
+  </xsl:if>
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-div-kimber">
+  <xsl:param name="scope" select="."/>
+  <xsl:param name="role" select="''"/>
+  <xsl:param name="type" select="''"/>
+
+  <xsl:variable name="key"
+          select="k:getIndexGroupKey(&lang;, &primary;)"/>
+
+  <xsl:variable name="label"
+          select="k:getIndexGroupLabel(&lang;, $key)"/>
+
+  <xsl:if test="key('k-group', $label)[&scope;]
+                [count(.|key('primary', &primary;)[&scope;][1]) = 1]">
+    <fo:block>
+      <xsl:call-template name="indexdiv.title">
+        <xsl:with-param name="titlecontent">
+          <xsl:value-of select="$label"/>
+        </xsl:with-param>
+      </xsl:call-template>
+      <fo:block>
+        <xsl:apply-templates select="key('k-group', $key)[&scope;]
+                            [count(.|key('primary', &primary;)[&scope;]
+                            [1])=1]"
+                             mode="index-primary">
+          <xsl:sort select="&primary;" lang="&lang;"/>
+          <xsl:with-param name="scope" select="$scope"/>
+          <xsl:with-param name="role" select="$role"/>
+          <xsl:with-param name="type" select="$type"/>
+        </xsl:apply-templates>
+      </fo:block>
+    </fo:block>
+  </xsl:if>
+</xsl:template>
+
+
 <xsl:template match="indexterm" mode="index-primary">
   <xsl:param name="scope" select="."/>
   <xsl:param name="role" select="''"/>