[xsl] Enabling extension to counting of instances

Subject: [xsl] Enabling extension to counting of instances
From: Eliot Kimber <ekimber@xxxxxxxxxxxx>
Date: Fri, 08 Jan 2010 09:08:24 -0600
In the DITA Open Toolkit one can deploy plugins that contribute new modules
to a base set of XSLT transforms where the plugins typically provide support
for new (specialized markup).

In many cases, the specialized markup needs to participate in base business
logic by being added to arbitrary checks that represent some semantic type
that is specific to the business logic where an element's mapping to that
semantic type has to made explicitly.

For example, in the context of generating print from DITA content, to
determine chapter numbers you count the references from the DITA map that
happen to represent chapters, where the determination of what is or isn't a
"chapter reference" is arbitrary (meaning that the XSLT plugin for a given
set of specialized reference elements has to say "tag X is a chapter
reference" where tag X is unknown to the base chapter numbering logic and
there's no way to infer from the markup itself that a given reference is or
is not a chapter reference).

The plugin can't simply override the numbering logic because that would
break other plugins deployed to same Toolkit instance. Rather, plugins need
to be able to contribute to the numbering logic so that all chapters are
counted correctly.

My design challenge then is to determine what is the best way to enable this
sort of unilateral contribution to things like numbering logic. In
particular, typical code using <xsl:number/> with @count and @from won't
work because there's no obvious way to extend the specification of what to
count and what to count from.

The only directly-provided XSLT extension mechanism I can think of is to use
modes where elements contribute nodes to a sequence that is then used for
either counting or doing a boolean check.

For example, to count chapter references you would have a mode
"isChapterRef" and then use it like so:

<xsl:variable name="chapterRefs"
  as="element()*"
>
  <xsl:apply-templates mode="isChapterRef"
   select="$map//*[contains(@class, ' map/topicref ')]"/>
</xsl:variable/>

Where a typical isChapterRef template would be:

<xsl:template mode="isChapterRef"
  match="*[contains(@class, ' pubmap-d/chapterref ')]"
>
 <xsl:sequence select="."/>
</xsl:template>

So that the resulting value of $chapterRefs would be a list of elements that
have declared themselves to be chapter references.

The $chapterRefs list can then be used for counting, boolean checks, etc.

My question: is there a more efficient way to provide this sort of
extensible arbitrary-type-to-semantic-type mapping?

Thanks,

Eliot

-- 
Eliot Kimber
Senior Solutions Architect
"Bringing Strategy, Content, and Technology Together"
Main: 610.631.6770
www.reallysi.com
www.rsuitecms.com

Current Thread