Project

Profile

Help

Bug #2435

closed

Equality fails due to type comparison

Added by Nick Evans over 8 years ago. Updated over 8 years ago.

Status:
Closed
Priority:
Normal
Category:
Schema-Aware processing
Sprint/Milestone:
Start date:
2015-08-04
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
9.6
Fix Committed on Branch:
9.6
Fixed in Maintenance Release:
Platforms:

Description

Consider the following XSD:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           targetNamespace="http://www.xpathtest.com/test"
           xmlns:test="http://www.xpathtest.com/test"
           elementFormDefault="qualified">
  <xs:element name="comparables">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="test:comparable" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="comparable">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="string" type="xs:string"/>
        <xs:element name="int" type="xs:integer"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

and the following instance:

<comparables xmlns="http://www.xpathtest.com/test">
  <comparable>
    <string>hello</string>
    <int>1</int>
  </comparable>
  <comparable>
    <string>hello</string>
    <int>1</int>
  </comparable>
</comparables>

If I run the following XPath expression using Saxon 9.6.0-4:

//test:comparable[1]/test:int eq //test:comparable[2]/test:int

it fails with the message "Cannot compare xs:integer to xs:integer". If I replace this expression with the following:

//test:comparable[1]/test:int*1 eq //test:comparable[2]/test:int*1

it returns "true" as expected. It seems that something is amiss in the way Saxon is handling the types of the expressions being compared.

Actions #1

Updated by Michael Kay over 8 years ago

  • Status changed from New to In Progress

It works for me on Saxon 9.6.0.6. Could you check it please on the latest release? I haven't been able to track down a specific bug fix.

I've added the test case to the QT3 test suite as prod-ValueComp/value-comparison-12.

Actions #2

Updated by Nick Evans over 8 years ago

Thanks for your response. I have just tried it on the latest (9.6.0-6) release but unfortunately still get the same error. This is how I am running the expression (I have just translated this from scala code, sorry if some errors have crept in):

Boolean licensedEdition = true;
Processor processor = new Processor(licensedEdition);
SchemaManager sm = processor.getSchemaManager();
//Load the xsd serialized as a string
sm.load(new StreamSource(new StringReader(xsd.toString())));
SchemaValidator sv = sm.newSchemaValidator();
XdmDestination xdmDest = new XdmDestination();
sv.setDestination(xdmDest);
//Load the instance serialized as a string
sv.validate(new StreamSource(new StringReader(xml.toString())));
String xpathExpr = "//test:comparable[1]/test:int eq //test:comparable[2]/test:int";
XPathCompiler comp = processor.newXPathCompiler();
comp.declareNamespace("test", "http://www.xpathtest.com/test");
XPathExecutable xpathExec = comp.compile(xpathExpr);
XPathSelector selector = xpathExec.load();
selector.setContextItem(xdmDest.getXdmNode());
Boolean result = selector.effectiveBooleanValue();
Actions #3

Updated by Michael Kay over 8 years ago

  • Category set to Schema-Aware processing
  • Assignee set to Michael Kay

OK, thanks, problem now reproduced. (I was previously running it from the XQuery command line and the XQuery API).

A note on this strange error message: at the deepest levels, a value comparison is evaluated by comparing two Java Comparables. The Comparable.compare() operation has no checked exceptions, and in general what you get back if you try to compare non-comparable objects is a ClassCastException. Saxon catches the ClassCastException several levels up, and produces this rather surreal message; the ClassCastException was probably from a completely different cause.

Actions #4

Updated by Michael Kay over 8 years ago

OK, the problem is that the XPathCompiler has not been declared schema-aware - you need to call compiler.setSchemaAware(true).

The expression has been compiled in non-schema-aware mode, which means that the code that's generated assumes that the operands to the value comparison will be strings; it tries to cast them to strings, gets a ClassCastException, and this results in the strange message.

There's a good reason why the default is NOT schema aware, which is that in the common case where documents are untyped, you can generate faster code if you know in advance that they will be untyped; generating schema-aware code for a case where it's not needed would incur unnecessary costs. (Conversely, of course, if the document is going to be schema-validated then it's useful to know that, as well).

Of course, what's wrong here is the diagnostics. If you've compiled the code without schema-awareness enabled, then Saxon ought to complain very clearly when you supply a schema-validated input document. I'll now look at what I can do to fix that.

The problem is specific to the XPath API; at this level, XSLT and XQuery behave differently.

Actions #5

Updated by Michael Kay over 8 years ago

  • Assignee changed from Michael Kay to O'Neil Delpratt
  • Found in version changed from 9.6.0-4 to 9.6

I have committed a patch on the 9.6 and 9.7 branches (with an incorrect commit message, sorry!). It changes XPathSelector.setContextItem() to make a check and report an error if the supplied context item is a node in a typed (schema-validated) document and the XPathCompiler used to compile the expression was not schema-aware.

Added JUnit test cases TestXPathCompiler/trySchemaAwareEquality.

Leaving the bug open and assigning to O'Neil to produce an equivalent patch on the .NET path.

Actions #6

Updated by Nick Evans over 8 years ago

Thanks very much for your quick analysis and solution! Making the XPathCompiler schema aware indeed solves the problem. And the improved error message will certainly help diagnosing this problem in the future.

Actions #7

Updated by O'Neil Delpratt over 8 years ago

  • Status changed from In Progress to Resolved
  • % Done changed from 0 to 100

Patch made to the .NET API

Actions #8

Updated by O'Neil Delpratt over 8 years ago

  • Status changed from Resolved to Closed
  • Fixed in version set to 9.6.0.7

Bug fix applied in the Saxon 9.6.0.7 maintenance release.

Actions #9

Updated by O'Neil Delpratt over 8 years ago

  • Applies to branch 9.6 added
  • Fix Committed on Branch 9.6 added
  • Fixed in Maintenance Release 9.6.0.7 added
Actions #10

Updated by O'Neil Delpratt over 8 years ago

  • Sprint/Milestone set to 9.6.0.7

Please register to edit this issue

Also available in: Atom PDF