Skip to content

Commit

Permalink
Merge pull request #461 from ndw/gloss-453-458
Browse files Browse the repository at this point in the history
Improve support for automatic glossaries.
  • Loading branch information
ndw committed Jan 29, 2024
2 parents 6b2a2d2 + 292a100 commit f600ceb
Show file tree
Hide file tree
Showing 30 changed files with 1,034 additions and 168 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,17 @@ class TestGenerator {
.withEnvironments(['default'])
.withStylesheet("${uBuildDir}/xslt/presentation.xsl")

testEnvironments.create('glossary-collection')
.withParameters([
'glossary-collection': "${fProjectDir}/src/test/resources/glosscollection.xml"])

testConfigurations.create('unwrapped').withEnvironments(['unwrap'])
testConfigurations.create('transclude').withEnvironments(['transclude'])
testConfigurations.create('local').withEnvironments(['local'])
testConfigurations.create('colors').withEnvironments(['colors'])
testConfigurations.create('ptoc').withEnvironments(['ptoc'])
testConfigurations.create('a11y').withEnvironments(['a11y'])
testConfigurations.create('glossary-collection').withEnvironments(['glossary-collection'])

def regexList = []
['fit\\.': 'fit',
Expand All @@ -149,6 +154,8 @@ class TestGenerator {
'ptoc\\.': 'ptoc',
'mediaobject\\.005': 'a11y',
'presentation\\.': 'presentations',
'glossary\\.00[1,2,3,4,5,6]': 'glossary-collection', // Not 7, 8, or 9!
'glossary\\.01': 'glossary-collection',
].each { entry ->
Pattern pat = ~"^.*${entry.key}.*\$"
regexList.add(new Tuple(pat, testConfigurations.find(entry.value)))
Expand Down
2 changes: 1 addition & 1 deletion properties.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ ext {
docbookVersion = '5.2CR5'
publishersVersion = '5.2CR5'

saxonVersion = '11.5'
saxonVersion = '12.4'
saxonGroup = 'net.sf.saxon'
saxonEdition = 'Saxon-HE'
//saxonGroup = 'com.saxonica'
Expand Down
71 changes: 71 additions & 0 deletions src/guide/xml/ch03.xml
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,77 @@ This most closely reproduces the numbering from the 1.x stylesheets.</para>

</section>

<section>
<title>Using glossaries</title>

<para>There are essentially two ways to manage glossaries: you can
author them by hand, or you can build them automatically from a
collection of glossary entries.</para>

<para>If you build them by hand, if you put <tag>glossary</tag> elements containing
<tag>glossentry</tag> elements, etc. in your document, then you have complete control.
What you put in your document is what will be formatted and published.</para>

<para>If you compose them from glossary collections, only the terms used in your document
(in <tag>glossterm</tag> or <tag>firstterm</tag> elements) will appear in the glossary.
The glossary collections can be managed internally or externally.
If multiple definitions appear in the glossary collections, only the first definition
is included.</para>

<para>The best way to explain automatic glossaries is to use an example. Let's assume that you
have marked the two terms <emphasis role="bold">Apple</emphasis> and <emphasis role="bold"
>Pear</emphasis> in your document, so that your automatic glossary should ultimately contain
exactly two entries for these two terms. Create a <code>glossary</code> with
<code>@role='auto'</code> in your document. We call this the <emphasis>internal</emphasis>
glossary.</para>
<itemizedlist>
<listitem>
<para>If your internal glossary has three entries for <emphasis>Apple</emphasis>,
<emphasis>Jackfruit</emphasis> and <emphasis>Pear</emphasis>, you will end up with a
glossary in the generated document that has only the two entries for
<emphasis>Apple</emphasis> and <emphasis>Pear</emphasis>. There will be no entry for
<emphasis>Jackfruit</emphasis>, since there is no corresponding <code>glossterm</code>
or <code>firstterm</code> in the main part of your text.</para>
</listitem>
<listitem>
<para>You can also use external glossaries for this task, which can be referenced by the use
of the <parameter>glossary-collection</parameter> transformation parameter, or the
<code>db</code> processing instruction with a <code>glossary-collection</code> pseudo
attribute. You can leave the internal, automatic glossary completely empty. As long as
there are entries for <emphasis>Apple</emphasis> and <emphasis>Pear</emphasis> in one of
your external gloassries, you will end up with these two entries in the generated
glossary, no matter how much more entries the external glossaries may contain.</para>
</listitem>
<listitem>
<para>You can use the internal, automatic glossary in conjunction with external glossaries.
In this case, entries from the internal glossary take precedence over entries for the same
term from external glossaries. Lets say you have entries for <emphasis>Apple</emphasis>
and <emphasis>Pear</emphasis> among others in your external glossary, and also an
<code>glossentry</code> for <emphasis>Apple</emphasis> in your internal glossary. In
this case you will end up with a glossary which contains two entries, one for
<emphasis>Apple</emphasis> with the specific definition taken from the internal
glossary, and one for <emphasis>Pear</emphasis> from the external glossary, which may be a
more general definition.</para>
</listitem>
</itemizedlist>

<para>Schematron rules can help manage the glossary. The
<function>f:glossentries</function> function (defined in
<filename>standalone-functions.xsl</filename> in the xslTNG install
directory) has been designed so that it can be integrated into
Schematron independently of the xslTNG stylesheets. You can use it to
check whether a corresponding <code>glossentry</code> exists for a
<code>glossterm</code> or <code>firstterm</code> while you are still
writing. Corresponding Schematron schemas are not yet part of the
xslTNG framework.</para>

<simplesect>
<title>Caveats</title>
<para>The use of <code>glossdiv</code> is not supported for automatic glossaries, all
of the entries will appear in a flat list.</para>
</simplesect>
</section>

<section xml:id="different">
<title>Creating something completely different</title>

Expand Down
33 changes: 33 additions & 0 deletions src/guide/xml/ref-functions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,39 @@ to construct the divisions in an index.</para>
</refsection>
</refentry>

<refentry xml:id="f_glossentries">
<?db filename='f_glossentries'?>
<refmeta>
<refentrytitle>f:glossentries</refentrytitle>
<refmiscinfo>{http://docbook.org/ns/docbook/functions}glossentries#1</refmiscinfo>
<refmiscinfo>{http://docbook.org/ns/docbook/functions}glossentries#2</refmiscinfo>
</refmeta>
<refnamediv>
<refname>f:glossentries</refname>
<refpurpose>Returns a list of all glossentries for a term</refpurpose>
<refclass>function</refclass>
</refnamediv>
<refsection>
<title>Description</title>
<para>Returns all <code>glossentry</code> elements that are targeted by <code>$term</code>,
which must either by a <code>glossterm</code> or a <code>firstterm</code> element. The
internal glossary of the input document is always taken into account. </para>
<para>In the form with only one argument, external glossaries are also taken into account if
they are designated in the input document with a <code>&lt;?db
glossary-collection='<replaceable>URIs</replaceable>'?></code> processing instruction.
In the form with two arguments, you can specify a list of URIs of the external
glossaries.</para>

<para>When there is more than one <code>glossentry</code> found, the result sequence will
start with entries from the internal glossary, if any.</para>
<para>The functions design allows its use indepentend from the xslTNG stylesheets. You can, for
example, integrate it in a Schematron rule that checks whether every <code>glossterm</code>
has exactly one corresponding <code>glossentry</code> while authoring your document. That`s
why the function can't use the <parameter>glossary-collection</parameter> transformation
parameter. </para>
</refsection>
</refentry>

<refentry xml:id="f_highlight-verbatim">
<?db filename="f_highlight-verbatim"?>
<refmeta>
Expand Down
27 changes: 23 additions & 4 deletions src/guide/xml/ref-params.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1979,23 +1979,42 @@ across many documents. If
<parameter>glossary-collection</parameter> points to a
glossary, the stylesheets will automatically populate glossary
entries in the document being transformed.</para>

<para>To achieve this:</para>

<orderedlist>
<listitem>
<para>Create a shared glossary and store it somewhere.</para>
</listitem>
<listitem>
<para>In the document you’re transforming, add an empty <code>glossary</code> with
<code>@role='auto'</code>.</para>
</listitem>
<listitem>
<para>In the document you’re transforming, add an empty <code>glossary</code> with
<code>@role='auto'</code>.</para>
</listitem>
<listitem>
<para>Run your
transformation with <parameter>glossary-collection</parameter> set
to the URI of that document.
</para>
</listitem>
</orderedlist>

<para>The stylesheets will copy referenced entries into your document before processing it.</para>

<para>You may specify per-document glossary collections with the
<literal>db</literal>
<indexterm>
<primary>db processing instruction</primary>
</indexterm> processing instruction using the
<literal>glossary-collection</literal>
<indexterm>
<primary>db processing instruction</primary>
<secondary>glossary-collection pseudo-attribute</secondary>
</indexterm> pseudo-attribute. This must appear in the root element of
your main document. If per-document glossary collections are provided,
they are processed in the order provided before the global
collection.</para>
<para>If multiple definitions for the same term appear in a glossary collection, only
the first term is used.</para>
</refsection>
</refentry>

Expand Down
28 changes: 28 additions & 0 deletions src/guide/xml/ref-variables.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1733,5 +1733,33 @@ used for a cross-reference. See <xref linkend="gentext"/>.</para>
</refsection>
</refentry>

<refentry xml:id="v_pi-db-attributes-are-uris">
<?db filename="v_pi-db-attributes-are-uris"?>
<refmeta>
<refentrytitle>$v:pi-db-attributes-are-uris</refentrytitle>
<refmiscinfo>{http://docbook.org/ns/docbook/variables}pi-db-attributes-are-uris</refmiscinfo>
</refmeta>
<refnamediv>
<refname>$v:pi-db-attributes-are-uris</refname>
<refpurpose>Controls which “db” processing instruction pseudo-attributes are URIs</refpurpose>
<refclass>variable</refclass>
</refnamediv>
<refsection>
<title>Description</title>
<para>The <link linkend="pi_db">“db” processing instruction</link> can be used to provide
configuration values within a document. For example:</para>

<programlisting><![CDATA[<?db xlink-style='inline' glossary-collection='../gcollection.xml'?>]]></programlisting>

<para>In this example, <code>xlink-style</code> is just a string value, but
<code>glossary-collection</code> is a URI.
When the value in question is a URI, it must be made absolute against the base URI
of the processing instruction on which it occurs. The <varname>v:pi-db-attributes-are-uris</varname>
variable determines which pseudo-attributes are considered URIs. Their values are made absolute
when the processing instruction is parsed.</para>

</refsection>
</refentry>

</reference>

2 changes: 1 addition & 1 deletion src/guide/xsl/common.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
|$param_xsl//xsl:variable[@name=$dname]"/>

<xsl:if test="count($decl) != 1">
<xsl:message select="count($decl), ': ', $dname"/>
<xsl:message select="'DECL:', count($decl), ': ', $dname"/>
</xsl:if>

<fieldsynopsis>
Expand Down
85 changes: 5 additions & 80 deletions src/main/xslt/modules/functions.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
xmlns:db="http://docbook.org/ns/docbook"
xmlns:err="http://www.w3.org/2005/xqt-errors"
xmlns:f="http://docbook.org/ns/docbook/functions"
xmlns:fp="http://docbook.org/ns/docbook/functions/private"
xmlns:l="http://docbook.org/ns/docbook/l10n"
Expand All @@ -16,6 +17,8 @@
exclude-result-prefixes="array db f fp l m map mp v vp xs"
version="3.0">

<xsl:include href="../standalone-functions.xsl"/>

<xsl:key name="id" match="*" use="@xml:id"/>
<xsl:key name="genid" match="*" use="generate-id(.)"/>

Expand Down Expand Up @@ -409,41 +412,11 @@
<xsl:sequence select="f:generate-id($node, false())"/>
</xsl:function>

<xsl:function name="f:pi" as="xs:string?" visibility="public">
<xsl:param name="context" as="node()?"/>
<xsl:param name="property" as="xs:string"/>
<xsl:sequence select="f:pi($context, $property, ())"/>
</xsl:function>

<xsl:function name="f:pi" as="xs:string*" visibility="public">
<xsl:param name="context" as="node()?"/>
<xsl:param name="property" as="xs:string"/>
<xsl:param name="default" as="xs:string*"/>

<xsl:choose>
<xsl:when test="empty($context)">
<xsl:sequence select="$default"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="fp:pi-from-list(($context/processing-instruction('db'),
root($context)/processing-instruction('db')),
$property, $default)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>

<xsl:function name="fp:pi-from-list" as="xs:string*">
<xsl:param name="pis" as="processing-instruction()*"/>
<xsl:param name="property" as="xs:string"/>
<xsl:param name="default" as="xs:string*"/>

<xsl:variable name="value"
select="f:pi-attributes($pis)/@*[local-name(.) = $property]/string()"/>

<xsl:sequence select="if (empty($value))
then $default
else $value"/>
</xsl:function>

<xsl:function name="fp:css-properties" as="attribute()?">
<xsl:param name="context" as="element()?"/>
Expand Down Expand Up @@ -485,54 +458,6 @@
</xsl:if>
</xsl:function>

<xsl:function name="f:pi-attributes" as="element()?">
<xsl:param name="pis" as="processing-instruction()*"/>
<xsl:variable name="attributes"
select="fp:pi-attributes($pis, map { })"/>

<xsl:element name="pis" namespace="">
<xsl:for-each select="map:keys($attributes)">
<xsl:attribute name="{.}" select="map:get($attributes, .)"/>
</xsl:for-each>
</xsl:element>
</xsl:function>

<xsl:function name="fp:pi-attributes" as="map(*)?">
<xsl:param name="pis" as="processing-instruction()*"/>
<xsl:param name="pimap" as="map(*)"/>

<xsl:choose>
<xsl:when test="empty($pis)">
<xsl:sequence select="$pimap"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="map" select="fp:pi-pi-attributes($pimap,
normalize-space($pis[1]))"/>
<xsl:sequence select="fp:pi-attributes(subsequence($pis, 2), $map)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>

<xsl:variable name="vp:pi-match"
select="'^.*?(\c+)=[''&quot;](.*?)[''&quot;](.*)$'"/>
<xsl:function name="fp:pi-pi-attributes" as="map(*)">
<xsl:param name="pimap" as="map(*)"/>
<xsl:param name="text" as="xs:string"/>

<xsl:choose>
<xsl:when test="matches($text, $vp:pi-match)">
<xsl:variable name="aname" select="replace($text, $vp:pi-match, '$1')"/>
<xsl:variable name="avalue" select="replace($text, $vp:pi-match, '$2')"/>
<xsl:variable name="rest" select="replace($text, $vp:pi-match, '$3')"/>
<xsl:sequence select="fp:pi-pi-attributes(map:put($pimap, $aname, $avalue),
$rest)"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="$pimap"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>

<xsl:function name="f:spaces" as="xs:string?">
<xsl:param name="length" as="item()*"/>

Expand Down Expand Up @@ -855,6 +780,6 @@
<xsl:sequence select="string-join($final-parts, '/')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>

</xsl:function>
</xsl:stylesheet>
4 changes: 4 additions & 0 deletions src/main/xslt/modules/variable.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
<xsl:variable name="v:as-json" select="map {'method':'json','indent':true()}"/>
<xsl:variable name="v:as-xml" select="map {'method':'xml','indent':true()}"/>

<xsl:variable name="v:pi-db-attributes-are-uris" as="xs:string*"
select="('glossary-collection', 'bibliography-collection',
'annotation-collection')"/>

<xsl:variable name="v:custom-localizations" as="document-node()?"
select="()"/>

Expand Down
Loading

0 comments on commit f600ceb

Please sign in to comment.