Project

Profile

Help

ClassCastException Orphan cannot be cast to AtomicValue in ValueComparison.effectiveBooleanValue

Added by Kai Weber over 2 years ago

When evaluating the following simple equals-comparison in an XSLT stylesheet I get a ClassCastException: net.sf.saxon.tree.util.Orphan cannot be cast to net.sf.saxon.value.AtomicValue. I am using Saxon 10.5-PE.

XSLT statement triggering the exception:

<xsl:when test="string(.) = $converter.input.coverimage.file">

In ValueComparison.effectiveBooleanValue() the LhsExpression is evaluated to an object of type net.sf.saxon.value.StringValue, the right hand side evaluates to a net.sf.saxon.tree.util.Orphan object, which has the following properties:

kind: 3 nodeName: null options: 0 stringValue: "cover.jpg" treeInfo: [ GenericTreeInfo object ] typeAnnotation: null

So, the string values of left and right hand side are meant to be the same here ("cover.jpg"), yet the evaluation fails due to the ClassCastException. Is there anything need to change in my input XSLT in order to prevent this?

Here's the Java stacktrace:

[2021-08-23 13:12:52] [SEVERE ] [java.lang.ClassCastException] Schwerwiegender Fehler:
net.sf.saxon.tree.util.Orphan cannot be cast to net.sf.saxon.value.AtomicValue 
[2021-08-23 13:12:52] [FINE   ] java.lang.ClassCastException: net.sf.saxon.tree.util.Orphan cannot be cast to net.sf.saxon.value.AtomicValue
	at net.sf.saxon.expr.ValueComparison.effectiveBooleanValue(ValueComparison.java:361)
	at net.sf.saxon.expr.instruct.Choose.choose(Choose.java:966)
	at net.sf.saxon.expr.instruct.Choose.processLeavingTail(Choose.java:940)
	at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:142)
	at net.sf.saxon.expr.instruct.ForEach.lambda$processLeavingTail$0(ForEach.java:526)
	at net.sf.saxon.om.SequenceIterator.forEachOrFail(SequenceIterator.java:136)
	at net.sf.saxon.expr.instruct.ForEach.processLeavingTail(ForEach.java:526)
	at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:752)
	at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:142)
	at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:352)
	at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:298)
	at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:142)
	at net.sf.saxon.expr.instruct.DocumentInstr.evaluateItem(DocumentInstr.java:302)
	at net.sf.saxon.expr.instruct.DocumentInstr.evaluateItem(DocumentInstr.java:45)
	at net.sf.saxon.expr.instruct.Instruction.iterate(Instruction.java:365)
	at net.sf.saxon.expr.parser.Evaluator$11.evaluate(Evaluator.java:290)
	at net.sf.saxon.expr.LetExpression.eval(LetExpression.java:553)
	at net.sf.saxon.expr.LetExpression.processLeavingTail(LetExpression.java:737)
	at net.sf.saxon.expr.instruct.NamedTemplate.expand(NamedTemplate.java:264)
	at net.sf.saxon.expr.instruct.CallTemplate$CallTemplatePackage.processLeavingTail(CallTemplate.java:548)
	at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:478)
	at net.sf.saxon.trans.XsltController.applyTemplates(XsltController.java:661)
	at net.sf.saxon.s9api.AbstractXsltTransformer.applyTemplatesToSource(AbstractXsltTransformer.java:360)
	at net.sf.saxon.s9api.XsltTransformer.transform(XsltTransformer.java:349)
	at de.paginagmbh.commons.xslt.SaxonXsltTransformer.transform(SaxonXsltTransformer.java:336)
	at de.paginagmbh.parsx.Konverter.applications.helper.xslt.XsltHelper.runXsltTransformation(XsltHelper.java:56)
	at de.paginagmbh.parsx.Konverter.applications.EPUB.executeEpubGenerationXslt(EPUB.java:959)
	at de.paginagmbh.parsx.Konverter.applications.EPUB.doInBackground(EPUB.java:265)
	at de.paginagmbh.parsx.Konverter.applications.EPUB.doInBackground(EPUB.java:1)
	at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at javax.swing.SwingWorker.run(SwingWorker.java:334)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

Replies (6)

Please register to reply

RE: ClassCastException Orphan cannot be cast to AtomicValue in ValueComparison.effectiveBooleanValue - Added by Michael Kay over 2 years ago

Is this running in backwards-compatibility mode (version="1.0")?

Ideally we need a full repro because it's very likely to depend on details like this that aren't obviously relevant.

What should be happening in 2.0 mode is that the typeChecker (at compile time) automatically adds an atomisation step to both operands of "=". But in 1.0 mode, the logic is different (and more complex, and probably not as thoroughly tested...).

As a workaround to get you back on the road, try writing

<xsl:when test="string(.) = string($converter.input.coverimage.file)">

Michael Kay Saxonica

RE: ClassCastException Orphan cannot be cast to AtomicValue in ValueComparison.effectiveBooleanValue - Added by Kai Weber over 2 years ago

The stylesheets involved (main stylesheet and included ones) all have a version attribute with value "2.0", so there should be no reason to go into backwards-compatibility mode.

Sharing the full repo might not be an easy way to debug this, as it is embedded into a framework that requires some effort for setup and configuration. I'll see if I can craft a minimal sample to reproduce this in a more straightforward way. In the meantime I'll try your suggested fix in the XSLT source.

Best regards, Kai Weber

RE: ClassCastException Orphan cannot be cast to AtomicValue in ValueComparison.effectiveBooleanValue - Added by Michael Kay over 2 years ago

The next thing I would look at, if it's all version 2.0, is how the variable (or parameter?) converter.input.coverimage.file is declared and initialised. For some reason the type checker has incorrectly decided that atomisation isn't required.

RE: ClassCastException Orphan cannot be cast to AtomicValue in ValueComparison.effectiveBooleanValue - Added by Kai Weber over 2 years ago

I am coming back to this after a two-day hiatus...

The variable is declared as being assignable, I guess that could make a difference:

<xsl:variable name="converter.input.coverimage.file" select="''" as="xs:string"/>

This is then assigned later like this:

<saxon:assign name="converter.input.coverimage.file" xml:space="default">
	<xsl:call-template name="resolve_coverimage_filename">
		<xsl:with-param name="isbn-original" select="$converter.var.eISBN-original"/>
		<xsl:with-param name="isbn-clean" select="$converter.var.eISBN-ohne-alles"/>
	</xsl:call-template>
</saxon:assign>

Inside the template used for this assignment, neither params nor local variables are explicitly typed:

<xsl:template name="resolve_coverimage_filename">
	<xsl:param name="isbn-original" required="yes"/>
	<xsl:param name="isbn-clean" required="yes"/>
		
	<xsl:variable name="var">
		<xsl:choose>
			<xsl:when test="$epub.page.cover.image.name='{{eISBNmit}}'">
				<xsl:value-of select="$isbn-original"/>
			</xsl:when>
			<xsl:when test="$epub.page.cover.image.name='{{eISBNohne}}'">
				<xsl:value-of select="$isbn-clean"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$epub.page.cover.image.name"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>
	<xsl:value-of select="concat($epub.page.cover.image.prefix, $var, $epub.page.cover.image.suffix)"/>
</xsl:template>

Your suggested workaround with an extra string() call around the variable doesn't help, it gets optimized away, possibly because the variable is already declared with xs:string as its type anyway.

We are currently in a process of refactoring our codebase to get rid of saxon:assign and saxon:assignable anyway. Just in case we could "solve" our problem by refraining from assignability, would you still be interested in a reproducible example of the original exception for debugging purposes?

RE: ClassCastException Orphan cannot be cast to AtomicValue in ValueComparison.effectiveBooleanValue - Added by Kai Weber over 2 years ago

Sorry, my copy+paste of the variable declaration above was wrong, it was meant to be:

<xsl:variable name="converter.input.coverimage.file" select="''"  saxon:assignable="yes" as="xs:string"/>
    (1-6/6)

    Please register to reply