xsl-list
[Top] [All Lists]

modes and temp trees (was Re: [xsl] grouping + global variable (?))

2004-08-14 13:49:55
I'm sorry to take up so much bandwidth on this (and thanks in advance for the continued patience; I promise not to make a habit of it), but I'm still stuck on figuring this out.

I took Wendell's suggestion and reworked the modes, and changed the previous "phase-2" mode and made it default. The bibliography generation now works beautifully and I've gotten things much better modularized. But I can't get the citation mode to work. Much of the time, I'm sending Saxon into an infinite loop trying to figure it out!

Again taking my simple example doc (at bottom), how do I modify the below stylesheet to correctly use the temporary tree for both the bibliography AND the citation modes? I need to get it to where this simple template (near the bottom) works:

<xsl:template match="mods:mods" mode="citation">
  <xsl:apply-templates select="mods:name" mode="citation"/>
  <xsl:value-of select="mods:year"/>
  <xsl:apply-templates select="mods:key"/>
</xsl:template>

The mods:key and mods:year elements are the ones created in the intermediate step, and the same expressions work fine in the bibliography mode. Currently I end up with output like this, where the year and suffix get dropped:

(<a href="#one">Doe</a>; <a href="#two">Doe</a>; <a href="#three">Doe, Jones and Smith</a>)

I'm also still unclear on how I should be properly controlling namespaces across these different modes.

Bruce

===  xsl ===

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:xs="http://www.w3.org/2001/XMLSchema";
                xmlns:xdt="http://www.w3.org/2003/11/xpath-datatypes";
                xmlns:str="http://example.org/xslt/functions";
                xmlns:db="http://docbook.org/docbook-ng";
                xmlns:mods="http://www.loc.gov/mods/v3";
                xmlns="http://www.loc.gov/mods/v3";
                xmlns:cs="http://www.silmaril.ie/bibliox/v1";
                xmlns:bib="http://www.example.org/bib";
                xmlns:xhtml="http://www.w3.org/1999/xhtml";
                exclude-result-prefixes="xs xdt str db mods xhtml cs bib"
                version="2.0">

<xsl:output method="xhtml" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="bibref" match="mods:mods" use="@ID" />

<!-- begin configuration options -->

<!-- biborder template simply determines the order of processing -->

<xsl:template name="biborder">
  <xsl:apply-templates select="mods:titleInfo"/>
  <xsl:apply-templates select="mods:originInfo"/>
  <xsl:apply-templates select="mods:relatedItem"/>
  <xsl:apply-templates select="mods:location"/>
</xsl:template>

<xsl:variable name="reftype">
  <xsl:choose>
    <xsl:when test="not[mods:relatedItem[(_at_)type='host']]">
      <xsl:text>book</xsl:text>
    </xsl:when>
    <xsl:when
test="mods:relatedItem[(_at_)type='host']/mods:originInfo/mods: issuance='continuing'">
      <xsl:text>article</xsl:text>
    </xsl:when>
    <xsl:when
test="mods:relatedItem[(_at_)type='host']/mods:originInfo/mods: issuance='monographic'">
      <xsl:text>chapter</xsl:text>
    </xsl:when>
  </xsl:choose>
</xsl:variable>

<!-- long list of punctuation variables -->

<xsl:variable name="title-before">
  <xsl:choose>
    <xsl:when test="$reftype='chapter'">
      <xsl:text>“</xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <xsl:text></xsl:text>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:variable name="title-after">
  <xsl:choose>
    <xsl:when test="$reftype='chapter'">
      <xsl:text>”</xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <xsl:text></xsl:text>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:variable name="creator-before">
  <xsl:text></xsl:text>
</xsl:variable>

<xsl:variable name="creator-after">
  <xsl:text> </xsl:text>
</xsl:variable>

<xsl:variable name="year-before">
  <xsl:text>(</xsl:text>
</xsl:variable>

<xsl:variable name="year-after">
  <xsl:text>) </xsl:text>
</xsl:variable>

<xsl:variable name="origin-before">
  <xsl:text>(</xsl:text>
</xsl:variable>

<xsl:variable name="origin-after">
  <xsl:text>)</xsl:text>
</xsl:variable>

<xsl:variable name="volume-before">
  <xsl:text>v.</xsl:text>
</xsl:variable>

<xsl:variable name="volume-after">
  <xsl:text></xsl:text>
</xsl:variable>

<xsl:variable name="issue-before">
  <xsl:text>, </xsl:text>
</xsl:variable>

<xsl:variable name="issue-after">
  <xsl:text></xsl:text>
</xsl:variable>

<xsl:variable name="location-before">
  <xsl:text>available from: </xsl:text>
</xsl:variable>

<xsl:variable name="location-after">
  <xsl:text>, </xsl:text>
</xsl:variable>

<xsl:variable name="genre-before">
  <xsl:text>, </xsl:text>
</xsl:variable>

<xsl:variable name="genre-after">
  <xsl:text></xsl:text>
</xsl:variable>

<xsl:variable name="place-before">
  <xsl:text></xsl:text>
</xsl:variable>

<xsl:variable name="place-after">
  <xsl:text>:</xsl:text>
</xsl:variable>

<xsl:variable name="publisher-before">
  <xsl:text></xsl:text>
</xsl:variable>

<xsl:variable name="publisher-after">
  <xsl:text></xsl:text>
</xsl:variable>

<!-- end configuration options -->

<xsl:template match="/">
  <html xmlns="http://www.w3.org/1999/xhtml";>
    <head>
      <xsl:apply-templates select="db:info"/>
      <style type="text/css">
        body { font-family: georgia, sans; font-size: 11px; line-height: 15px;}
#content { width: 500px; position: center; margin: auto; margin-top: 40px; }
        a { text-decoration: none; color: black; }
        a:hover { background: #F3FCC0; }
      </style>
    </head>
    <body>
      <div id="content">
        <xsl:apply-templates/>
      </div>
    </body>
  </html>
</xsl:template>

<xsl:template match="db:info">
  <xsl:apply-templates select="db:title"/>
</xsl:template>

<xsl:template match="db:section">
  <div class="section">
    <xsl:apply-templates/>
  </div>
</xsl:template>

<xsl:template match="db:section/db:info">
  <h4>
    <xsl:value-of select="db:title"/>
  </h4>
</xsl:template>

<xsl:template match="db:para">
  <p>
    <xsl:apply-templates/>
  </p>
</xsl:template>

<xsl:template match="db:bibliography">
  <div id="bibliography">
    <h3>References</h3>
    <xsl:apply-templates/>
  </div>
</xsl:template>

<!-- MODS stuff -->

<xsl:function name="bib:grouping-key" as="xs:string">
  <xsl:param name="bibref" as="element(mods:mods)" />
  <xsl:value-of separator=";">
    <xsl:for-each select="$bibref/mods:name">
      <xsl:value-of
        select="string-join((mods:namePart[(_at_)type = 'family'],
                   mods:namePart[(_at_)type = 'given']), ',')" />
    </xsl:for-each>
  </xsl:value-of>
</xsl:function>

<!-- first create a temporary tree -->
<!-- NOTE: If I remove the bib mode on the apply-templates below,
Saxon appears to go into an infinite loop -->
<xsl:template match="mods:modsCollection">
  <xsl:variable name="temp">
    <xsl:apply-templates select="." mode="processed-bibrefs"/>
  </xsl:variable>
  <xsl:apply-templates select="$temp" mode="bibliography"/>
</xsl:template>

<!-- next, group, sort, and generate year and suffix elements from
raw biblist to create a processed biblist -->
<xsl:template match="mods:modsCollection" mode="processed-bibrefs">
  <xsl:copy>
    <xsl:variable name="bibref" select="mods:mods" />
    <xsl:for-each-group select="$bibref" group-by="bib:grouping-key(.)">
      <xsl:sort select="current-grouping-key()"/>
      <xsl:for-each-group select="current-group()"
                group-by="xs:integer(substring(mods:originInfo/mods:dateIssued|
                mods:relatedItem/mods:part/mods:date,1,4))">
        <xsl:sort select="current-grouping-key()" />
        <xsl:variable name="year" as="xs:integer"
                select="current-grouping-key()"/>
        <xsl:variable name="first" as="xs:boolean" select="position() = 1" />
        <xsl:for-each select="current-group()">
          <mods ID="{(_at_)ID}">
            <year>
              <xsl:value-of select="current-grouping-key()"/>
            </year>
            <xsl:if test="last() > 1">
              <key type="year-suffix">
                <xsl:number value="position()" format="a"/>
              </key>
            </xsl:if>
            <xsl:copy-of select="*"/>
          </mods>
        </xsl:for-each>
      </xsl:for-each-group>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

<!-- take processed biblist and run templates on them in bib mode -->
<xsl:template match="mods:modsCollection" mode="bibliography">
  <xsl:apply-templates select="mods:mods" mode="bibliography"/>
</xsl:template>

<xsl:template match="mods:mods" mode="bibliography">
  <p class="bibref" id="{(_at_)ID}">
    <span class="creator">
      <xsl:apply-templates select="mods:name" mode="bibliography"/>
    </span>
    <xsl:apply-templates select="mods:year"/>
    <xsl:apply-templates select="mods:titleInfo" mode="bibliography"/>
    <xsl:apply-templates select="mods:originInfo" mode="bibliography"/>
    <xsl:apply-templates select="mods:relatedItem" mode="bibliography"/>
    <xsl:apply-templates select="mods:location" mode="bibliography"/>
  </p>
</xsl:template>

<xsl:template match="mods:name" mode="bibliography">
  <xsl:apply-templates select="mods:namePart"/>
  <xsl:choose>
    <xsl:when test="position() = last()" />
    <xsl:when test="position() = last() - 1"> and </xsl:when>
    <xsl:otherwise>, </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="mods:namePart[(_at_)type='given']">
  <xsl:apply-templates/>
  <xsl:text> </xsl:text>
</xsl:template>

<xsl:template match="mods:namePart[(_at_)type='family']">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="mods:year">
  <span class="year">
    <xsl:value-of select="$year-before"/>
    <xsl:apply-templates/>
<!-- we can access newly creatod key element to append suffix -->
    <xsl:apply-templates select="../mods:key"/>
    <xsl:value-of select="$year-after"/>
  </span>
</xsl:template>

<xsl:template match="mods:key">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="mods:titleInfo" mode="bibliography">
  <span class="title">
    <xsl:value-of select="$title-before"/>
    <xsl:apply-templates select="mods:title"/>
    <xsl:apply-templates select="mods:subTitle"/>
    <xsl:value-of select="$title-after"/>
  </span>
</xsl:template>

<xsl:template match="mods:title">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="mods:subTitle">
  <xsl:text>: </xsl:text>
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="mods:originInfo" mode="bibliography">
  <xsl:if test="mods:place">
    <span class="origin">
      <xsl:value-of select="$origin-before"/>
      <xsl:apply-templates select="mods:place"/>
      <xsl:apply-templates select="mods:publisher"/>
      <xsl:value-of select="$origin-after"/>
    </span>
  </xsl:if>
</xsl:template>

<xsl:template match="mods:place">
  <xsl:value-of select="$place-before"/>
  <xsl:apply-templates/>
  <xsl:value-of select="$place-after"/>
</xsl:template>

<xsl:template match="mods:publisher">
  <xsl:value-of select="$publisher-before"/>
  <xsl:apply-templates/>
  <xsl:value-of select="$publisher-after"/>
</xsl:template>

<!-- begin citation processing; something's wrong with the modes -->

<xsl:template match="db:citation">
  <xsl:text>(</xsl:text>
  <xsl:apply-templates/>
  <xsl:text>)</xsl:text>
</xsl:template>

<xsl:template match="db:biblioref">
  <xsl:variable name="idref" select="@linkend"/>
  <xsl:variable name="bibref" select="//mods:mods[(_at_)ID=$idref]"/>
  <xsl:for-each-group select="$bibref" group-by="bib:grouping-key(.)">
    <xsl:sort select="current-grouping-key()"/>
    <xsl:for-each-group select="current-group()"
group-by="xs:integer(substring(mods:originInfo/mods:dateIssued|
                        mods:relatedItem/mods:part/mods:date,1,4))">
      <xsl:sort select="current-grouping-key()"/>
      <xsl:for-each select="current-group()">
        <a>
          <xsl:attribute name="href">
            <xsl:value-of select="concat('#',@ID)"/>
          </xsl:attribute>
          <xsl:apply-templates select="." mode="citation" />
          <xsl:if test="position() != last()">, </xsl:if>
        </a>
      </xsl:for-each>
    </xsl:for-each-group>
  </xsl:for-each-group>
  <xsl:if test="position() != last()">; </xsl:if>
</xsl:template>

<xsl:template match="mods:name" mode="citation">
  <xsl:apply-templates select="mods:namePart[(_at_)type='family']"/>
  <xsl:choose>
    <xsl:when test="position() = last()" />
    <xsl:when test="position() = last() - 1"> and </xsl:when>
    <xsl:otherwise>, </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="mods:mods" mode="citation">
  <xsl:apply-templates select="mods:name" mode="citation"/>
  <xsl:value-of select="mods:year"/>
  <xsl:apply-templates select="mods:key"/>
</xsl:template>

</xsl:stylesheet>

=== input ===

<?xml version="1.0" encoding="utf-8"?>
<article xmlns="http://docbook.org/docbook-ng";>
  <info>
    <title>Test</title>
  </info>
  <section>
    <info>
      <title>Introduction</title>
    </info>
    <para>Some citations: <citation><biblioref linkend="one"/><biblioref
    linkend="two"/><biblioref linkend="three"/></citation></para>
  </section>
  <bibliography>
    <modsCollection xmlns="http://www.loc.gov/mods/v3";>
      <mods ID="one">
        <name type="personal">
          <namePart type="given">John</namePart>
          <namePart type="family">Doe</namePart>
          <role>
            <roleTerm type="text">author</roleTerm>
          </role>
        </name>
        <titleInfo>
          <title>Some Title</title>
        </titleInfo>
        <originInfo>
          <dateIssued>1999</dateIssued>
        </originInfo>
      </mods>
      <mods ID="two">
        <name type="personal">
          <namePart type="given">John</namePart>
          <namePart type="family">Doe</namePart>
          <role>
            <roleTerm type="text">author</roleTerm>
          </role>
        </name>
        <titleInfo>
          <title>Another Title</title>
        </titleInfo>
        <originInfo>
          <dateIssued>1999</dateIssued>
        </originInfo>
      </mods>
      <mods ID="three">
        <name type="personal">
          <namePart type="given">John</namePart>
          <namePart type="family">Doe</namePart>
          <role>
            <roleTerm type="text">author</roleTerm>
          </role>
        </name>
        <name type="personal">
          <namePart type="given">Jane</namePart>
          <namePart type="family">Jones</namePart>
          <role>
            <roleTerm type="text">author</roleTerm>
          </role>
        </name>
        <titleInfo>
          <title>Some Title</title>
        </titleInfo>
        <originInfo>
          <dateIssued>1999</dateIssued>
        </originInfo>
      </mods>
    </modsCollection>
  </bibliography>
</article>