Bug #3732
closed
Component reference function df:class#2 is already bound
Applies to branch:
9.8, trunk
Fix Committed on Branch:
9.8, trunk
Fixed in Maintenance Release:
Description
This is a continuation of:
https://saxonica.plan.io/issues/3645
The error reported there still occurs, tested with both Saxon 9.8.0.8 and 9.8.0.11.
java.lang.AssertionError: **** Component reference function df:class#2 is already bound
at net.sf.saxon.expr.instruct.Actor.processComponentReference(Actor.java:146)
at net.sf.saxon.expr.instruct.Actor.allocateBindingSlotsRecursive(Actor.java:109)
at net.sf.saxon.expr.instruct.Actor.allocateBindingSlotsRecursive(Actor.java:112)
at net.sf.saxon.trans.SimpleMode$2.processRule(SimpleMode.java:955)
at net.sf.saxon.trans.SimpleMode.processRuleChain(SimpleMode.java:1153)
at net.sf.saxon.trans.SimpleMode.processRules(SimpleMode.java:1079)
at net.sf.saxon.trans.SimpleMode.processRules(SimpleMode.java:1067)
at net.sf.saxon.trans.SimpleMode.forceAllocateAllBindingSlots(SimpleMode.java:951)
at net.sf.saxon.trans.SimpleMode.allocateAllBindingSlots(SimpleMode.java:941)
at net.sf.saxon.style.PrincipalStylesheetModule.compile(PrincipalStylesheetModule.java:1401)
at net.sf.saxon.style.Compilation.compilePackage(Compilation.java:328)
at net.sf.saxon.style.StylesheetModule.loadStylesheet(StylesheetModule.java:258)
at net.sf.saxon.style.Compilation.compileSingletonPackage(Compilation.java:106)
at net.sf.saxon.s9api.XsltCompiler.compile(XsltCompiler.java:739)
at net.sf.saxon.jaxp.SaxonTransformerFactory.newTemplates(SaxonTransformerFactory.java:155)
at net.sf.saxon.jaxp.SaxonTransformerFactory.newTransformer(SaxonTransformerFactory.java:111)
at ro.sync.xml.transformer.TransformerCreator.createXSLTransformer(TransformerCreator.java:1613)
I will try to attach some samples.
Files
I attached my samples.
Transform the "flowers.ditamap" with the XSLT DITA-OT2.x\plugins\org.dita4publishers.epub\xsl\map2epubImpl.xsl
without extra parameters, using Saxon EE.
After you fix the exception, the transformation is not supposed to succeed, there are various files that the XSLT is trying to load that are missing because it's just an example taken from one of the DITA OT processing stages.
The samples are using imports such as
<xsl:import href="plugin:org.dita-community.common.mapdriven:xsl/dataCollection.xsl"/>
which appear to depend on a custom URIResolver or catalog.
So I added -catalog:DITA-OT2.x/catalog-dita.xml which triggered the failure.
The offending reference is at line 179 of DITA-OT2.x/plugins/org.dita4publishers.epub/xsl/map2epubNavImpl.xsl
This is in the match pattern of a simple template rule
<xsl:template mode="epubtrans:generate-nav-loa
epubtrans:generate-nav-loi
epubtrans:generate-nav-lot
epubtrans:generate-nav-lov
epubtrans:generate-nav-custom
epubtrans:generate-nav-landmarks
"
match="*[df:class(., 'map/map')]"
priority="-1"
>
<xsl:param name="doDebug" as="xs:boolean" tunnel="yes" select="false()"/>
<xsl:param name="navType" as="xs:string" tunnel="yes"/>
<li>Navigation type <xsl:value-of select="$navType"/> not implemented.</li>
</xsl:template>
whose main notable feature is that it appears in multiple modes.
The first attempt to allocate a binding slot for userFunctionCall#19310 is during allocateAllBindingSlots on mode generate-nav-custom. The second is while processing mode generate-nav-lot. Both modes are using the same Pattern object. It needs to have a separate copy for each mode so that different binding slots can be allocated.
(Note that the fix for bug #3645 prevented a Pattern being processed twice within the context of a single Mode. It didn't prevent it being processed twice for different Modes - nor should it, because different binding slots are needed in each Mode.)
- Category set to Internals
- Status changed from New to In Progress
- Assignee set to Michael Kay
- Priority changed from Low to Normal
The solution seems to be to copy the pattern while looping through the modes in XSLTemplate.register()
A side observation: these patterns using [df:class(., 'map/map')] as a predicate destroy all our attempts at optimizing the match patterns that were used in the DITA 1.0 stylesheets using contains(). The df:class function is
<xsl:function name="df:class" as="xs:boolean">
<xsl:param name="elem" as="element()"/>
<xsl:param name="classSpec" as="xs:string"/>
<!-- '\$" in the regex is a workaround for a bug in MarkLogic 3.x and for a common user
error, where trailing space in class= attribute is dropped.
-->
<xsl:variable name="normalizedClassSpec" as="xs:string" select="normalize-space($classSpec)"/>
<xsl:variable name="result"
select="matches($elem/@class,
concat(' ', $normalizedClassSpec, ' | ', $normalizedClassSpec, '$'))"
as="xs:boolean"/>
<xsl:sequence select="$result"/>
</xsl:function>
which no longer uses contains(), it now uses matches(), and moreover it uses matches() with a regular expression that is going to be recompiled on each call. It's a bit of a shame if this is only being done because of a bug in MarkLogic...
Thanks for the comment on the "df:class" function, I contacted the XSLT developer to let him know of the discussion.
- Status changed from In Progress to Resolved
- Applies to branch 9.8, trunk added
- Fix Committed on Branch 9.8, trunk added
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in Maintenance Release 9.8.0.12 added
Bug fix applied in the Saxon 9.8.0.12 maintenance release.
Please register to edit this issue
Also available in: Atom
PDF