[Home] [By Thread] [By Date] [Recent Entries]

Subject: Re: Processor error
From: "Kurt Cagle kurt.cagle@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 27 Feb 2026 22:24:49 -0000
Try this:

The error occurs because the inline function inside fold-left closes over
the global variable $find-change-map, and some XSLT 3.0 processors (Saxon
in particular) have trouble with global variable references captured in
closures within named functions. The fix is to pass the map as a parameter
to cp:find-change-text instead of referencing it as a free variable:

<xsl:function name="cp:find-change-text" as="xs:string">
    <xsl:param name="text" as="xs:string"/>
    <xsl:param name="changes" as="map(xs:string, xs:string)"/>
    <xsl:sequence select="fold-left(map:keys($changes), $text,
        function($t, $key) { replace($t, $key, $changes($key)) })"/>
</xsl:function>

Then update the call sites:

<xsl:variable name="text"
select="cp:find-change-text(normalize-space(title),
$find-change-map)"/>

The root cause: when an inline function (the lambda passed to fold-left) is
defined inside a named xsl:function, the processor compiles it as an
anonymous function object. If that lambda captures a *global* variable by
reference, certain processors flag it as an already-bound component during
static analysis b the global binding and the closure binding conflict.
Passing the map explicitly as a parameter keeps everything in the local
call stack and avoids the closure capture entirely.

A secondary issue worth noting: in your templates you have <xsl:text>[
/Title ({$text}) </xsl:text> b those curly braces only trigger AVT
expansion inside attribute values, not inside xsl:text. With
expand-text="yes" on the stylesheet element you'd use {$text} directly in
text content, which your stylesheet does have, but wrapped in xsl:text the
expansion still won't fire. You likely want either bare text content
or <xsl:value-of
select="$text"/> there.


*Kurt Cagle*
Editor in Chief
The Cagle Report
kurt.cagle@xxxxxxxxx
443-837-8725 <http://voice.google.com/calls?a=nc,%2B14438378725>


On Fri, Feb 27, 2026 at 1:28b/PM rick@xxxxxxxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> Hi All,
>
>
>
> I am applying a stylesheet via Oxygen using Saxon-EE 9.9.1.7 and it
> processes without errors. When I run the same stylesheet in Adobe
> FrameMaker using SaxonEE9-8-0-7J, I get this error:
>
>
>
> **** Component reference function anon:f_18205168#2 is already bound
>
>
>
> When I remove this function, I donbt get the error:
>
>
>
>     <xsl:function name="cp:find-change-text" as="xs:string">
>         <xsl:param name="text"/>
>         <xsl:sequence select="*fold-left*(*map:keys*(*$find-change-map*),
> *$text*,
>             *function*(*$text*, *$key*) { *replace*(*$text*, *$key*,
> *$find-change-map*(*$key*)) })"/>
>     </xsl:function>
>
>
>
> Here is a partial input, followed by the stylesheet. I am outputting text.
>
>
>
> <?xml version="1.0" standalone="no"?>
> <map>
>     <chapter name="Chapter1TOC.fm" page="24">
>         <title>Chapter 1 Ethics and Professional Conduct</title>
>         <practice-notes>
>             <bookmark dest="G12.1038988">
>                 <title>? 1.1 Introduction</title>
>                 <bookmark dest="G12.1023242">
>                     <title>? 1.1:1 The Lawyerbs Creed</title>
>                 </bookmark>
>                 <bookmark dest="G12.1023245">
>                     <title>? 1.1:2 Notice of Grievance Process</title>
>                 </bookmark>
>             </bookmark>
>             <bookmark dest="G12.1023248">
>                 <title>? 1.2 Sources of Interpretation of Rules</title>
>             </bookmark>
>         </practice-notes>
>         <forms>
>             <bookmark name="Form1-1.fm" page="46">
>                 <title>Form 1-1 Letter Declining Representation</title>
>             </bookmark>
>             <bookmark name="Form1-2.fm" page="48">
>                 <title>Form 1-2 Letter Disclosing and Requesting Waiver of
> Potential Conflict with Current Client</title>
>             </bookmark>
>             <bookmark name="Form1-17.fm" page="123">
>                 <title>Form 1-17 Additional Clauses for Engagement
> Letters</title>
>                 <bookmark dest="G29.1726404">
>                     <title>Clause 1-17-1 Corporate Transparency Act</title>
>                 </bookmark>
>                 <bookmark dest="G29.1726774">
>                     <title>Clause 1-17-2</title>
>                 </bookmark>
>             </bookmark>
>         </forms>
>     </chapter>
> </map>
>
>
>
> <?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:cp="http://www.frameexpert.com/functions"
>     xmlns:map="http://www.w3.org/2005/xpath-functions/map"
>     exclude-result-prefixes="xs cp map"
>     version="3.0"
>     expand-text="yes">
>
>     <xsl:output method="text" indent="no"/>
>
>     <xsl:variable name="find-change-map" as="map(xs:string, xs:string)"
>         select="*map*{*'&#8212;'* : '&lt;emdash/>',
>                     *'&#8211;'* : '&lt;endash/>',
>                     *'&#8220;'* : '&lt;ldquote/>',
>                     *'&#8221;'* : '&lt;rdquote/>',
>                     *'&#8217;'* : '&lt;rsquote/>',
>                     *'&#167;'*  : '&lt;section/>' }"/>
>
>     <xsl:template match="/*map*">
>         <xsl:text>[ /PageMode /UseOutlines /DOCVIEW
> pdfmark&#x0A;</xsl:text>
>         <xsl:apply-templates/>
>     </xsl:template>
>
>     <xsl:template match="*indexes*">
>         <xsl:variable name="child-count" select="*count*(*index*)"/>
>         <xsl:text>[ /Title (INDEXES) /Count -</xsl:text>
>         <xsl:value-of select="*$child-count*"/><xsl:text> </xsl:text>
>         <!-- Color is black; style is bold. -->
>         <xsl:text>/*Color* [0 0 1] /*F* 2 /*Page* 0 /*OUT* </xsl:text>
>         <xsl:text>*pdfmark*&#x0A;</xsl:text>
>         <xsl:apply-templates/>
>     </xsl:template>
>
>     <xsl:template match="*chapter*|*index*">
>         <xsl:variable name="child-count" select="*count*(*bookmark*)"/>
>         <!-- Call the function to replace special characters with
> elements. -->
>         <xsl:variable name="text" select="*cp:find-change-text*(
> *normalize-space*(*title*))"/>
>         <xsl:text>[ /Title ({*$text*}) </xsl:text>
>         <!-- Reserved bookmarks get grey color. -->
>         <xsl:if test="*matches*(*$text*,'reserved$')">
>             <xsl:text>/Color [0.5 0.5 0.5] /F 0 </xsl:text>
>         </xsl:if>
>         <xsl:if test="*$child-count* > 0">
>             <xsl:text>/Count -</xsl:text><xsl:value-of select="
> *$child-count*"/><xsl:text> </xsl:text>
>         </xsl:if>
>         <xsl:text>/Page </xsl:text><xsl:value-of select="*if*(*@page*)
> *then* *@page* *else* 0"/><xsl:text> </xsl:text>
>         <xsl:text>/View [/XYZ -4 792 null] /OUT </xsl:text>
>         <xsl:text>pdfmark&#x0A;</xsl:text>
>         <xsl:apply-templates/>
>     </xsl:template>
>
>     <xsl:template match="*bookmark*">
>         <xsl:variable name="child-count" select="*count*(*bookmark*)"/>
>         <!-- Call the function to replace special characters with
> elements. -->
>         <xsl:variable name="text" select="*cp:find-change-text*(
> *normalize-space*(*title*))"/>
>         <xsl:text>[ /Title ({*$text*}) </xsl:text>
>         <!-- Reserved bookmarks get grey color. -->
>         <xsl:if test="*matches*(*$text*,'reserved$')">
>             <xsl:text>/Color [0.5 0.5 0.5] /F 0 </xsl:text>
>         </xsl:if>
>         <xsl:if test="*$child-count* > 0">
>             <xsl:text>/*Count* -</xsl:text><xsl:value-of select="
> *$child-count*"/><xsl:text> </xsl:text>
>         </xsl:if>
>         <xsl:if test="*@page*">
>             <xsl:text>/*Page* </xsl:text><xsl:value-of
select="*@page*"/><xsl:text>
> </xsl:text>
>         </xsl:if>
>         <xsl:if test="*@dest*">
>             <xsl:text>/Dest /{*@dest*} </xsl:text>
>         </xsl:if>
>         <xsl:text>/*OUT* *pdfmark*&#x0A;</xsl:text>
>         <xsl:apply-templates/>
>     </xsl:template>
>
>     <xsl:mode on-no-match="shallow-skip"/>
>
>     <xsl:function name="cp:find-change-text" as="xs:string">
>         <xsl:param name="text"/>
>         <xsl:sequence select="*fold-left*(*map:keys*(*$find-change-map*),
> *$text*,
>             *function*(*$text*, *$key*) { *replace*(*$text*, *$key*,
> *$find-change-map*(*$key*)) })"/>
>     </xsl:function>
>
> </xsl:stylesheet>
>
> Best regards,
>
> Rick
>
>
>
> Rick Quatro
>
> Carmen Publishing Inc.
>
> www.frameexpert.com
>
> rick@xxxxxxxxxxxxxxx
>
> 585-729-6746
>
>
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/1217935> (by
> email <>)

Current Thread
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member