Re: [xsl] dynamically applying templates

Subject: Re: [xsl] dynamically applying templates
From: Bruce D'Arcus <bdarcus@xxxxxxxxxxxxx>
Date: Tue, 14 Sep 2004 14:45:52 -0400
On Sep 14, 2004, at 2:13 PM, Wendell Piez wrote:

<xsl:template match="cs:reftype">
  <xsl:param name="source"/>
  <xsl:apply-templates>
    <xsl:with-param name="source" select="."/>

In this case, what exactly is the parameter doing? Are you using this precisely to do the, as you later say, "jumping back and forth between the trees"? So here you're apply-templates to the cs:* elements, and elsewhere to mods:*?

Yes. I'm matching a node in your configuration (the reftype), since its organization and content will drive processing.

OK, am with you.


But I'm passing a reference back to the mods source so that it can be "jumped back to" anytime I need its data.

This is where I'm getting lost. How is this working? I see a param with a cs:reftype template, and then a select of that same element. Where is mods coming in here?


This way, not only the content, but also the structure of your cs:reftype can drive processing, without fancy tests.

And this is exactly what I need.


  </xsl:apply-templates>
</xsl:template>

<xsl:template match="cs:title">
  <xsl:param name="source"/>
  <!-- do your title thing here, grabbing data from
       $source (the mods source) as necessary -->
</xsl:template>

Here's I'm confused on the $source reference. Does this suggest I am using the source param and doing something like so?

<xsl:template match="cs:title">
  <xsl:param name="source"/>
  <!-- do your title thing here, grabbing data from
       $source (the mods source) as necessary -->
  <xsl:apply-templates select="mods:titleInfo">
    <xsl:with-param name="source" select="mods:mods"/>
  </xsl:apply-templates>
</xsl:template>

Presumably that would have to be


<xsl:apply-templates select="$source/mods:titleInfo"/>

Good; I figured that part out after sending the earlier note. So maybe the light is starting to dawn!


(And since here you're jumping back to the node in the source tree, you don't need to pass a parameter back -- certainly not one that binds a non-existent mods:mods child of the cs:title context node.)

Sorry, but I feel like a blind man here, and I need to understand it
better before I get farther.

It's a pretty sophisticated application of the XSLT processing model on two documents in tandem, so it's not easy to understand.


You have to start by assimilating the processing model itself, including the notions of context nodes, relative paths (including the default child:: axis), and template traversal. If your brain can't track what's happening as the processor traverses a single document, it's probably going to freeze up completely when you try to conceive of traversing two documents back-and-forth. But you have chosen to address a very ambitious requirement.

The last big hill to climb!


I think I find it hard to wrap my head around the context stuff; it's where I consistently get confused.

I'm suggesting, in effect, that you 'push' it from your configuration file.

Yes, I understand this, and it makes sense. It's just a challenge to hold it all together in the mind, as you say.


OK, I'm going to post it all below in the interest of bringing the thread to a quicker conclusion. If I can have this work and understand why, I should be able to figure out the rest, which would mean integrating the cs:* templates into the existing stylesheets, where I currently have templates that look like:

<xsl:template match="mods:modsCollection[$citation-class='author-year']" mode="bibliography">
...
<xsl:template>


and:

<xsl:template match="mods:titleInfo[not(@type='abbreviated')]" mode="full">
<span class="{if (../mods:relatedItem[@type = 'host'])
then 'title'
else 'title italic'}">
<xsl:apply-templates select="." mode="title-before"/>
<xsl:apply-templates select="mods:title"/>
<xsl:apply-templates select="mods:subTitle"/>
<xsl:apply-templates select="." mode="title-after"/>
</span>
</xsl:template>


==== xsl ====
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
		xmlns:xs="http://www.w3.org/2001/XMLSchema";
                xmlns:db="http://docbook.org/docbook-ng";
                xmlns:mods="http://www.loc.gov/mods/v3";
                xmlns="http://www.w3.org/1999/xhtml";
		xmlns:bib="http://xbiblio.sourceforge.net/xbib";
		xmlns:cs="http://xbiblio.sourceforge.net/xcs";
                exclude-result-prefixes="mods db bib xs cs">

<xsl:output method='xhtml' encoding='utf-8' indent='yes'/>

<xsl:strip-space elements="*"/>

<!-- read the external citation style file -->
<xsl:param name="citation-style" required="yes" as="xs:string" />

<xsl:variable name="styles" as="document-node()"
  select="doc(concat($citation-style, '.csl'))" />

<!-- set the citation class parameter (e.g. author-year) as specified in the style file -->
<xsl:param name="citation-class" select="$styles/cs:citationstyle/@class"/>


<xsl:variable name="style-citation" select="$styles/cs:citationstyle/cs:content/cs:citation"/>
<xsl:variable name="style-biblio" select="$styles/cs:citationstyle/cs:content/cs:bibliography"/>
<xsl:variable name="style-names" select="$styles/cs:citationstyle/cs:content/cs:names"/>
<xsl:variable name="style-terms" select="$styles/cs:citationstyle/cs:content/cs:terms"/>


<!--
So perhaps your calling template would select the appropriate
cs:reftype element in the config file to process:
-->
<xsl:template match="mods:mods">
<div>
<xsl:apply-templates select="$styles/cs:citationstyle/cs:content/cs:bibliography[@author-as- sort-order='yes']/cs:entry/cs:reftype">
<xsl:with-param name="source" select="."/>
</xsl:apply-templates>
</div>
</xsl:template>


<xsl:template match="cs:reftype">
<xsl:param name="source"/>
<xsl:apply-templates>
<xsl:with-param name="source" select="."/>
<!-- the parameter passing shouldn't be necessary w/ XSLT 2.0 'tunneling
parameters' -->
</xsl:apply-templates>
</xsl:template>


<xsl:template match="cs:title">
  <xsl:param name="source"/>
  <!-- do your title thing here, grabbing data from
       $source (the mods source) as necessary -->
  <xsl:apply-templates select="$source/mods:titleInfo" mode="bib"/>
</xsl:template>

<xsl:template match="mods:titleInfo" mode="bib">
  <span class="title">
    <xsl:apply-templates select="mods:title"/>
    <xsl:apply-templates select="mods:subTitle"/>
  </span>
</xsl:template>

<xsl:template match="cs:creator" mode="bib">
  <xsl:param name="source"/>
  <xsl:apply-templates select="$source/mods:name" mode="bib"/>
</xsl:template>

<xsl:template match="mods:name" mode="bib">
  <span class="creator">
    <xsl:apply-templates select="mods:name"/>
  </span>
</xsl:template>

</xsl:stylesheet>

==== config ====
<citationstyle xmlns="http://xbiblio.sourceforge.net/xcs";>
<content>
<bibliography author-as-sort-order="yes">
  <entry>
    <reftype name="book">
      <title font-style="italic" after=", "/>
      <creator/>
    </reftype>
  </entry>
</bibliography>
</content>
<citationstyle>

==== source ====

<doc>
<!-- this would normally be docbook ng; but keep it simple for now -->
   <mods xmlns="http://www.loc.gov/mods/v3";>
     <name type="personal">
        <namePart type="given">Jane</namePart>
        <namePart type="family">Doe</namePart>
     </name>
     <titleInfo>
        <title>Main Title</title>
        <subTitle>Subtitle</subTitle>
     </titleInfo>
   </mods>
</doc>

Current Thread