Skip to content

apparatus

Christian Lück edited this page Oct 8, 2024 · 11 revisions

Critical Apparatus

These XSLT packages are there for the critical apparatus:

  • xsl/common/libentry.xsl: functions for generating data structures that represent an apparatus entry
  • xsl/common/libapp2.xsl: base package that provides templates, modes and functions for printing one or multiple critical apparatus. In parts these components are abstract.
  • xsl/html/libapp2[c].xsl: generate one or multiple critical apparatus for HTML output, deriving and overriding xsl/common/libapp2.xsl
  • xsl/latex/libapp2[c].xsl: generate one or multiple critical apparatus for LaTeX output, deriving and overriding xsl/common/libapp2.xsl

Having the packages in xsl/common/ is the key for providing similar functions for different output formats.

Generator approach

It may be obvious, to merge templates for generating the critical apparatus into the mode, which produces the representation of the text (aka text mode). E.g., when the XSLT processor traverses the document in this text mode and it visits an app element, then some HTML for representing the lemma and readings that make up the apparatus entry must be put out, for example some popup code. If we instead want an apparatus after the main text, we would traverse the text a second time with an apparatus mode for generating the apparatus, a third time for generating the editorial notes, etc. Let's call all this the classical approach. E.g., the TEI CAT (TEI Critical Apparatus Toolbox) follows this approach (cf. its stylesheet).

The approach of the SEED TEI Transformations is different:

  1. It first runs a function, that generates a data structure, from which a critical apparatus can be build. This generator function is at the heart of the generator approach. It is fed with context (the document or a part of it) and an arbitrary XPath expression, that determines which elements are to be represented in a critical apparatus. If multiple critical apparatus are required, the function can be called with different XPath expressions, so that each generated apparatus data structure covers a certain domain or regard of text criticism.
  2. Such a data structure can then be consumed by a package for outputting the critical apparatus in HTML, LaTeX or some other format. Format-specific packages that derive from xsl/common/libapp2.xsl have templates for outputting the whole apparatus as a single block like needed for an apparatus at the end of the text referencing the text back by line number or back links; they also provide templates for hooking in a single entry at some inline location in the text, like needed for HTML popups or LaTeX footnotes; they also provide templates for hooking into the text a reference (link) to a apparatus entry printed elsewhere.

The advantages of the generator approach over the classical approach are obvious:

  • We can use the same XSLT code for generating different critical apparatus from the same document by feeding different XPath expressions to the generator function.
  • We can share a common code base for completely different representations of the apparatus, e.g., linked end- or footnotes, popups, line-based apparatus at the end of short texts; while we only need a handful of special named templates for hooking into the main text or for outputting the whole apparatus at once.
  • Thus, we can add features to a common code base and simply opt out in projects that do not want them by means of the XPath expression fed to the generator function.

So the benefits are in the domains of (i) code sharing, aka the DRY principle, (ii) separation of concerns, and (iii) configuration-driven development.

Technical Definition of Apparatus

We call apparatus each note-like paratext, that references a portion of the text by repeating some words like so lemma] or similar and optionally by a link, line number or the like. Thus, editorial notes, that reference the text not only by a footnote mark (or link), but also with lemma], are technically an apparatus.

E.g., in ALEA's Edition of the works of Ibn Nubatah al-Misri, we have – technically seen – two apparatus. 1. the proper critical apparatus presenting the varietatis lectionis of the text, and 2. the editiorial notes. We use the same functions, modes and templates for both of them. Only the XPath expressions passed to the generator function are different.

In an other use case with apparatus entries in HTML popups, we use all the components for generating an apparatus, but override the template generating the lemma] output to not print the lemma at all.––It's still an apparatus :-) Thus, take the technical definition as rule of thumb or a specific––albeit potential––difference to plain footnotes.

Usage

Generator function

The ternary generator function app:apparatus-entries#3 is defined in xsl/common/libapp.xsl.

app:apparatus-entries(context as node()*, app-entries-xpath as xs:string, type as xs:integer) as map(*)*

The third parameter is a integer serving as an identifier for the apparatus. E.g., you could use 1 for your first apparatus, 2 for the second etc. An integer is used, since integer comparison is much faster than string comparison.

It returns a sequence of mappings, where each mapping represents an apparatus entry as a data structure. This data structure is generated by seed:mk-entry-map#3 from app/common.libentry.xsl.

For convenience, xsl/common/libapp2.xsl/ and all the packages deriving it provide a unary function app:apparatus-entries#1 that uses a reasonable predefined XPath for generating the apparatus entries and uses 1 as the apparatus identifier:

app:apparatus-entries(context as node()*) as map(*)*

This function chooses an XPath depending which method a variant encoding is defined in the TEI header in variantEncoding/@method and variant/Encoding/@location.

Building blocks for different representations

The data structure generated by the generator function can be passed to named templates that serve as building blocks for different representations of a critical apparatus.

We distinguish three general classes of represenations:

  • block: the apparatus entries are output all together as a block, e.g. after the main text or even an extra document
  • inline: the apparatus entries must be inserted one by one at different positions in the main text
  • linked forms where a link to a certain apparatus entry is inserted inline in the text and the entries are all output together somewhere else as a block.

The inline and linked representations require some hooks in the mode producing the main text. libtext.xsl provides these hooks and calls the named template text:inline-marks or text:inline-alternatives in them. You can redefine it using one of libapp.xsl named templates which extract the right apparatus entry from the data structure by evaluating the context.

Block

Line-based apparatus

This type of output is suited for short texts like poems with the apparatus under the poem referencing passages in the text by line number.

An example can be found in xsl/projects/alea/html/diwan.xsl.

The sequence of maps generated by the generator function can directly be consumed by the template for outputting the apparatus:

<xsl:variable name="apparatus-entries" as="map(*)*" visibility="public" select="app:apparatus-entries(root())"/>
<xsl:call-template name="app:line-based-apparatus-block">
   <xsl:with-param name="entries" select="$apparatus-entries"/>
</xsl:call-template>

Inline

HTML Popup Apparatus

This type of output is inlined in the main text.

In HTML, offering popups with apparatus entries is this type.

The inlining is done by redefining a named template that libtext.xsl defines: app:inline-alternatives.

The data structure generated by the generator function must be converted to a mapping first: app:apparatus-entries($CONTEXT, $THE_XPATH, $INT_ID) => seed:note-based-apparatus-nodes-map(true()).

An example can be found in xsl/html/prose-with-popups.xsl. Here are the relevant parts:

  <xsl:use-package
    name="https://scdh.zivgitlabpages.uni-muenster.de/tei-processing/transform/xsl/html/libapp2.xsl"
    package-version="1.0.0">
    <xsl:accept component="*" names="*" visibility="public"/>
    <xsl:accept component="variable" names="app:popup-css" visibility="final"/>
    <xsl:accept component="mode" names="seed:lemma-text-nodes" visibility="public"/>
  </xsl:use-package>

  <!-- generate the entries -->
  <xsl:variable name="prose:apparatus-entries" as="map(xs:string, map(*))" visibility="public"
    select="app:apparatus-entries(/) => seed:note-based-apparatus-nodes-map(true())"/>

  <xsl:use-package
    name="https://scdh.zivgitlabpages.uni-muenster.de/tei-processing/transform/xsl/html/libprose.xsl"
    package-version="1.0.0">
    <xsl:accept component="mode" names="*" visibility="public"/>

    <xsl:override>
      <xsl:template name="text:inline-marks">
        <xsl:call-template name="app:inline-alternatives">
          <xsl:with-param name="entries" select="map:merge($prose:apparatus-entries)"/>
        </xsl:call-template>
      </xsl:template>
    </xsl:override>
  </xsl:use-package>
LaTeX Footnote Apparatus

An example can be found in xsl/project/alea/latex/prose.xsl.

Linked

HTML Endnotes

An example can be found in xsl/project/alea/html/prose.xsl.

Implementation Details and How to Extend

Modes

Generator

The generator function gets an XPath that is applied to the context. The result is a sequence of elements, for which there will be an apparatus entry. To get the lemma, which the entry is related to, each one of these elements is passed to the dispatcher mode.

  • app:lemma-text-nodes-dspt is a dispatcher for various element types. The templates have to select nodes that go into the lemma. Typically they apply the rules from seed:lemma-text-nodes on them.
  • seed:lemma-text-nodes is for extracting the text nodes from the base text which the apparatus entry is on. They are important for determining the lemma, repeated in the apparatus entry, and for grouping entries, that are on the same text passage.

Output

  • app:reading-dspt is for the entries after the lemma (readings, etc.). It serves as a dispatcher for different types of entries. All templates should leave it again to get the text of the reading etc.

  • app:reading-text is for printing the text of a reading etc. Typically it is entred from a template in the mode apparatus-reading, defined in xsl/common/librend.xsl, see librend.

  • app:reading-text-pre: hook

  • app:reading-text-post: hook

  • app:reading-annotation is for adding (automatically generated) notes to an apparatus entry, e.g. when or is nested in an apparatus entry, we may want to add information from the @reason attribute to the entry.

  • app:reading: unused?

Named Templates

The named templates with visibility abstract in xsl/common/libapp.xsl are the building blocks for output.

Example extension

Say, we want to add support for <supplied>, to be more precise: <supplied>, if not contained in <choice>.

To xsl/common/libapp.xsl we add to the dispatcher mode:

    <!-- supplied -->
    <xsl:template mode="app:lemma-text-nodes-dspt" match="supplied[not(parent::choice)]">
        <xsl:apply-templates mode="seed:lemma-text-nodes"/>
    </xsl:template>

Since <supplied> quiete simply needs its text content to be repeated in the entry lemma, nothing special is required for seed:lemma-text-nodese.

To the outputting package like xsl/html/libapp2c.xsl we also only have to add to the dispatcher mode:

            <xsl:template mode="app:reading-dspt" match="supplied">
                <span class="reading supplied">
                    <span class="static-text" data-i18n-key="supplied">&lre;supplied&pdf;</span>
                </span>
                <xsl:if test="position() ne last()">
                    <span class="apparatus-sep" style="padding-left: 4px" data-i18n-key="rdgs-sep"
                        >;</span>
                </xsl:if>
            </xsl:template>

We also need in hook in the mode for the main text. So in xsl/html/libtext.xsl we add a template that calls the named template text:inline-marks (and other hooks)

<xsl:template match="supplied[not(parent::choice)]" mode="text:text>
  <xsl:apply-templates mode="text:hook-ahead" select="."/>
  <span class="supplied">
    <xsl:call-template name="text:class-attribute"/>
    <xsl:apply-templates mode="text:hook-before" select="."/>
    <xsl:apply-templates select="@* | node()"/>
    <xsl:apply-templates mode="text:hook-after" select="."/>
  </span>
  <xsl:apply-templates mode="text:hook-behind" select="."/>
  <xsl:call-template name="text:inline-marks"/>
</xsl:template>

Sigla

For modularity reasons, outputting the sigla is done by the named template app:sigla. It simply outputs the contents of @wit.

You can override this this template. In the following example, wit:sigla from xsl/latex/libwit.xsl is used, which get's sigla from an external witness catalogue:

  <!-- optional: the URI of the projects central witness catalogue -->
  <xsl:param name="wit-catalog" as="xs:anyURI?" select="()"/>

  <xsl:variable name="witnesses" as="element()*">
    <xsl:choose>
      <xsl:when test="empty($wit-catalog)">
        <xsl:sequence select="//sourceDesc//witness[@xml:id]"/>
      </xsl:when>
      <xsl:otherwise>
        <!-- a sequence from external and local witnesses.
          We only use the ones with a siglum. -->
        <xsl:sequence select="
          (//sourceDesc//witness[@xml:id],
          doc(resolve-uri($wit-catalog, base-uri()))/descendant::witness[@xml:id])
          [descendant::abbr[@type eq 'siglum']]"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:use-package
    name="https://scdh.zivgitlabpages.uni-muenster.de/tei-processing/transform/xsl/latex/libwit.xsl"
    package-version="1.0.0">
    <xsl:override>
      <xsl:variable name="wit:witnesses" as="element()*" select="$witnesses"/>
    </xsl:override>
  </xsl:use-package>

  <xsl:use-package
    name="https://scdh.zivgitlabpages.uni-muenster.de/tei-processing/transform/xsl/latex/libapp2.xsl"
    package-version="1.0.0">
    <xsl:override>

      <!-- use libwit in apparatus -->
      <xsl:template name="app:sigla">
        <xsl:param name="wit" as="node()"/>
        <xsl:call-template name="wit:sigla">
          <xsl:with-param name="wit" select="$wit"/>
        </xsl:call-template>
      </xsl:template>

    </xsl:override>
  </xsl:use-package>

Internationalization

All separators and fixed texts from the critical apparatus like ] after the lemma, | between entries, om. for missing text in a reading, etc., can be changed without touching the XSLT pachages. It is taken from the locales in xsl/html/locales/*/translation.json which are loaded by libi18n.xsl and can simply be replaced by project-specific needs.

See libi18n.xsl!