[xsl] how can I make non-tunnelling parameters tunnel through <xsl:next-match/>?

Subject: [xsl] how can I make non-tunnelling parameters tunnel through <xsl:next-match/>?
From: "Chris Papademetrious christopher.papademetrious@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 1 Jul 2022 14:24:32 -0000
Hello everyone,

The DITA Open Toolkit<https://www.dita-ot.org/> allows plugin stylesheets to
be incorporated into processing via <xsl:import>. To keep my plugin code
robust against future DITA-OT processing changes and other plugins, I call
<xsl:next-match> and postprocess the results where possible. And XSLT 3.0 with
shallow-copy moded templates make postprocessing pretty easy!

I'm hitting a case where the existing code passes non-tunneling parameters
from template A to B, with parameter defaults computed in template B. And when
I try to wedge my processing between A and B using <xsl:next-match>, I can't
get template B to properly receive parameters from A only when they're
passed.

For example, given the following XML input:


<?xml version="1.0" encoding="utf-8" ?>
<body>
  <note type="note">This is note 1.</note>
  <note type="caution">This is an important note 2.</note>
  <note type="unknown">This is some other note 3.</note>
</body>


and the original processing code:


<?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"; exclude-result-prefixes="#all"
version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <!-- A1 - default note -->
  <xsl:template match="note">
    <xsl:apply-templates select="." mode="B"/>
  </xsl:template>

  <!-- A2 - Caution note -->
  <xsl:template match="note[@type = 'caution']">
    <xsl:apply-templates select="." mode="B">
      <xsl:with-param name="title" select="'Caution'"/>
    </xsl:apply-templates>
  </xsl:template>

  <!-- A3 - fallback for unknown note types -->
  <xsl:template match="note[@type = 'unknown']">
    <xsl:apply-templates select="." mode="B">
     <xsl:with-param name="type" select="'note'"/>
    </xsl:apply-templates>
  </xsl:template>

  <!-- B -->
  <xsl:template match="*" mode="B">
    <xsl:param name="type" select="@type"/>
    <xsl:param name="title" select="'Note'"/>  <!-- this is actually
complicated string lookup code I don't want to replicate -->
    <span class="{$type}"><xsl:value-of select="$title"/>: <xsl:sequence
select="node()"/></span>
  </xsl:template>

</xsl:stylesheet>


then the result is as follows:


<?xml version="1.0" encoding="UTF-8"?><body>
  <span class="note">Note: This is note 1.</span>
  <span class="caution">Caution: This is an important note 2.</span>
  <span class="note">Note: This is some other note 3.</span>
</body>


The second element shows the "Caution" title computed in B, and the third
element shows the "note" type passed from A3.

But when I try to insert my own processing between A and B:


  <!-- B-prime -->
  <xsl:template match="*" mode="B" priority="10">  <!-- (priority emulates
<xsl:next-match>) -->
    <xsl:param name="type"/>
    <xsl:param name="title"/>
    <!-- ...post-processing... -->
    <xsl:next-match>
      <xsl:with-param name="type" select="$type"/>
      <xsl:with-param name="title" select="$title"/>
    </xsl:next-match>
  </xsl:template>


then note 1 and 2's type is empty because B-prime passes an empty sequence for
the "type" parameter that bypasses B's default value. And if I remove the
parameter stuff from B-prime, then the title for note 3 never gets through
B-prime.

How can I get sometimes-defined parameters passed through B-prime? Tunnelling
is the correct solution, but the A and B templates (which I can't modify) do
not define them as tunnelling parameters. I tried using <xsl:if> inside
<xsl:next-match/> to selectively pass defined parameters, but it isn't
allowed.

I want B-prime to be as ignorant as possible about the outside world, but
maybe that's not possible here.

Thanks!

-----
Chris Papademetrious
Tech Writer, Implementation Group
(610) 628-9718 home office
(570) 460-6078 cell

Current Thread