Project

Profile

Help

Bug #6236

closed

Expected XPathException but got AssertionError 'No current component'

Added by Philip Fearon 6 months ago. Updated 5 months ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Internals
Sprint/Milestone:
-
Start date:
2023-10-31
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
12, trunk
Fix Committed on Branch:
12, trunk
Fixed in Maintenance Release:
Platforms:
.NET, Java

Description

With Saxon 10.9 and Saxon 12.0, (HE or PE) , with the attached (new-context.zip) Java and XSLT we get an AssertionError instead of the expected XPathException which was thrown in previous Saxon versions (10.5 for example). Here is the output with Saxon 10.9:

saxon product version: 10.9
local param name: always-assume-indentation
local param name: is-indented
java.lang.AssertionError: No current component
        at net.sf.saxon.expr.GlobalVariableReference.evaluateVariable(GlobalVariableReference.java:119)
        at net.sf.saxon.expr.GlobalVariableReference.evaluateVariable(GlobalVariableReference.java:26)
        at net.sf.saxon.expr.VariableReference.iterate(VariableReference.java:568)
        at net.sf.saxon.expr.Expression.effectiveBooleanValue(Expression.java:890)
        at net.sf.saxon.expr.OrExpression.effectiveBooleanValue(OrExpression.java:137)
        at net.sf.saxon.expr.BooleanExpression.evaluateItem(BooleanExpression.java:174)
        at net.sf.saxon.expr.BooleanExpression.evaluateItem(BooleanExpression.java:27)
        at net.sf.saxon.expr.Expression.iterate(Expression.java:872)
        at net.sf.saxon.expr.instruct.GlobalVariable.getSelectValue(GlobalVariable.java:661)
        at net.sf.saxon.expr.instruct.GlobalVariable.actuallyEvaluate(GlobalVariable.java:745)
        at net.sf.saxon.expr.instruct.GlobalParam.evaluateVariable(GlobalParam.java:92)
        at net.sf.saxon.expr.instruct.GlobalParam.evaluateVariable(GlobalParam.java:101)
        at com.deltaxml.app.App.run(App.java:48)

The AssertionError is thrown when we attempt to evaluate a specific 'is-indented' parameter that requires a context node as part of an 'or' expression. If we change the expression by just keeping the right-hand operand of the 'or' expression, we get the expected XPathException.

The main Java function is:

    public void run() throws SaxonApiException, XPathException {
        Processor proc = new Processor(false);
        System.out.println("saxon product version: " + proc.getSaxonProductVersion());
        XsltCompiler xsltCompiler = proc.newXsltCompiler();
        compiledExecutable = xsltCompiler.compile(new StreamSource(new File("new-context/src/resources/test.xsl")));
        loadedExecutable = compiledExecutable.load();

        Controller controller = loadedExecutable.getUnderlyingController();
        controller.initializeController(new GlobalParameterSet());
        controller.preEvaluateGlobals(controller.newXPathContext());
        Iterator<GlobalParam> gps = controller.getExecutable().getGlobalParameters().values().iterator();


        while (gps.hasNext()) {
            GlobalParam gp= gps.next();
            String localName = gp.getVariableQName().getLocalPart();
            System.out.println("local param name: " + localName);
            gp.evaluateVariable(controller.newXPathContext());      
          }
    }

Here's the XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                version="3.0">

  <xsl:output method="xml" indent="yes"/>
  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:param name="always-assume-indentation" as="xs:boolean" select="false()"/> 

  <xsl:param name="is-indented" as="xs:boolean"
    select="$always-assume-indentation or exists(/*[text()])"/>

  <xsl:template match="/*" mode="#all">
    <xsl:copy>
      <xsl:attribute name="is-indented" select="$is-indented"/>
      <xsl:apply-templates select="@*, node()" mode="#current"/>
    </xsl:copy>
  </xsl:template>
 
</xsl:stylesheet>


Files

new-context.zip (11 KB) new-context.zip simple repro Philip Fearon, 2023-10-31 16:30
Actions #1

Updated by Michael Kay 6 months ago

You're using internal APIs so there's always a bit of a risk of changes between releases. Having said that, though, I think that what you're doing should work. We have some very similar internal paths that call preEvaluateGlobals, notably when running with -T tracing, because evaluating globals lazily results in a very confusing trace output.

The problem here arises when you try to evaluate one global variable (or param) which references another. The "other" variable could in principle have been overridden in another package, and the concept of a "current component" is used to decide which package's variables should be used; if there is no current component then there is no way of deciding. Because we're evaluating global variables directly, rather than via a recognised entry point to the transformation (such as an initial template or function) there is no current component on this path.

I think the regression is probably because we introduced more careful checking to avoid NPEs when there is no current component. In this particular case there is only one package, therefore no risk of ambiguity, so a less careful approach would probably succeed.

Actions #2

Updated by Michael Kay 6 months ago

In fact XsltController.preEvaluateGlobals() does nothing (for some reason...), so you can take that out of your code.

I think that a workaround is to change the call on evaluateVariable() to

gp.evaluateVariable(controller.newXPathContext(), gp.getDeclaringComponent());

(You could also, of course, use the same XPathContext object for all variables, and you could set the context item on it if you don't want the failure).

I'll investigate whether var.evaluateVariable(context) should be invoking var.evaluateVariable(context, var.getDeclaringComponent) rather tha var.evaluateVariable(context, null) as it does at the moment.

Actions #3

Updated by Michael Kay 6 months ago

  • Category set to Internals
  • Status changed from New to Resolved
  • Assignee set to Michael Kay
  • Priority changed from Low to Normal
  • Applies to branch 12, trunk added
  • Fix Committed on Branch 12, trunk added
  • Platforms .NET added

I've changed evaluateVariable(XPathContext) in both GlobalVariable and GlobalParam to set the variable itself as the current component if no other current component is available, to satisfy the case where the variable evaluation is effectively the initial entry point to the transformation.

Actions #4

Updated by Philip Fearon 5 months ago

Thanks for the feedback on the sample code. The code the sample is based on is quite dated because it's just used for one rather obscure feature, so needs an overhaul anyway.

Actions #5

Updated by O'Neil Delpratt 5 months ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 12.4 added

Bug fix applied in the Saxon 12.4 maintenance release

Please register to edit this issue

Also available in: Atom PDF