Support #2738


string-join implementation always uses XPath 3.1 implementation

Added by Stuart Barker about 8 years ago. Updated over 1 year ago.

XPath conformance
Start date:
Due date:
% Done:


Estimated time:
Legacy ID:
Applies to branch:
Fix Committed on Branch:
9.7, trunk
Fixed in Maintenance Release:


The change history for 9.6 to 9.7 states that:

"The function fn:string-join now accepts any sequence of atomic values in its first argument: for example the result of fn:string-join(1 to 5) is "1 2 3 4 5". Because of internal constraints, Saxon has implemented this change regardless of the requested XPath version."

This seems to imply that the implementation of the function is no longer compliant with earlier versions of XPath. And indeed, using 9.7 instead of 9.6, our tool fails a public conformance case that expects a type error when the items in the sequence are type xs:integer rather than xs:string.

We are looking to upgrade in order to incorporate memory improvements made for We cannot do this if we lose compliance with XPath 2.0.

I have set the priority to high as a combination of this bug and bug 2723 has left us unable to release a new version of our tool that is now due.

Related issues

Copied to Saxon - Support #5965: string-join implementation always uses XPath 3.1 implementationClosedMichael Kay2016-05-09

Actions #1

Updated by Stuart Barker about 8 years ago

As further background it is worth recording that we have upgraded to 9.6 (from 9.3) as it incorporates fixes for and an issue related to the handling of the totalDigits schema facet. These issues had directly impacted one of our clients.

We do not particularly need any major new features of 9.6 and our processor only requires XPath 2.0 compliance.

Actions #2

Updated by Michael Kay about 8 years ago

Thanks, that's interesting input.

I had been rather assuming that since the level of forwards compatibility between XPath 2.0, 3.0, and 3.1 is very high, we could start to think about dropping support for 2.0 once 3.1 becomes a Recommendation. Perhaps I need to think again.

The reason for string-join being the way it is is that we currently define the signatures of built-in functions in static data. We can define different subsets of the functions for each Configuration, but the current mechanism doesn't currently allow two different Configurations to have different signatures for the same function (or for the signature to depend on configuration settings). I would like to fix this but it's not trivial.

In addition the APIs for selecting a version of XPath or XQuery cause a lot of confusion, so I was hoping that by moving everything forward to 3.1 (eventually) we could make life a lot simpler for users.

Actions #3

Updated by Stuart Barker about 8 years ago

Thanks for the quick response.

Unfortunately we are bound to XPath 2.0 - it is used by the XBRL International Fomula specifications (see and they are very unlikely to move to XPath 3.0. If you aren't able to carry on supporting 2.0 (either in the form of future releases, or by porting bug fixes and performance improvements back to one or more earlier 2.0-compliant releases) then we would probably have to use a different processor.

In this case would it be possible to add an evaluation-time type check to the implementation of string-join, so that you could leave the signature the same?

We are looking again at 9.5 as it fixes the bugs we encountered in 9.3 but wouldn't have this one or bug 2736, and hopefully would not be as affected by bug 2723.

Actions #4

Updated by Michael Kay about 8 years ago

A well-known problem. W3C specs have generally been moving away from "fixed-version" references to other specs and towards "open-version" references, e.g. referencing "Unicode 4.0 or later". There have been too many of these problems, e.g. XSLT 1.0 referencing JDK 1.1.8 which is now pretty well unobtainable, even as a specification. Even where the specs appear to mandate a specific version, implementors have been taking a pragmatic approach in cases where a new version is both backwards compatible and easier to obtain.

There are a few details where edge-case conformance with an old spec becomes really difficult. An example is ensuring that if XSD 1.1 support is not enabled, string-to-double conversion rejects "+INF", which is the only value accepted by XSD 1.1 xs:double that is not also accepted by XSD 1.0. The contortions needed in the code to allow this edge case to be configurable are simply not worth the extra complexity, given that the only benefit is tick-box compliance. I think the string-join example falls into the same category.

I did look at special-casing the string-join issue with a run-time check, but that's not the way Saxon type checking works. At compile time, code is generated to do any necessary type checking or conversion based on the function signature. By the time the supplied value reaches the implementation of the function, it will already have been converted and we don't know what the original supplied value was.

Actions #5

Updated by Michael Kay about 8 years ago

  • Category set to XPath conformance
  • Status changed from New to Resolved
  • Assignee set to Michael Kay
  • Priority changed from High to Normal
  • Applies to branch 9.8 added
  • Fix Committed on Branch 9.7, 9.8 added

This is very difficult to fix in a satisfactory way in 9.7 because the signatures of built-in functions are held in static data and it is not possible to pick up different signatures for different functions.

For 9.8 I have implemented a long-awaited redesign to the function library mechanism that allows multiple sets of built-in functions, from which we can select when building a static context; this allows different signatures to be used for the same function depending on the language level supported for a particular query or stylesheet. This change resolves the issue for 9.8 (confirmed by passing QT3 test case fn-string-join-27 when the test driver is run with -lang:XP20).

For 9.7 I have implemented a kludge: in the list of function signatures we add a function "_STRING-JOIN_2.0" with the same implementation as string-join, but with a different required type for the first argument; and in SystemFunctionLibrary.bind() we redirect calls to string-join to this pseudo-function _string-join_2.0 when appropriate.

Actions #6

Updated by O'Neil Delpratt about 8 years ago

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

Bug fixed in maintenance release

Actions #7

Updated by O'Neil Delpratt about 7 years ago

  • Fix Committed on Branch trunk added
  • Fix Committed on Branch deleted (9.8)
Actions #8

Updated by O'Neil Delpratt about 7 years ago

  • Applies to branch deleted (9.8)
Actions #9

Updated by Johan Walters over 1 year ago

On Saxon 9.9 (EE), the issue seems to have returned. The exact same usecase (XBRL conformance suite), expects XPTY0004 when using string-join() on non-string items, when having set the language version on XPathCompiler to 2.0. Looking at XPath20FunctionSet, it uses the same StringJoin.class as the XPath31FunctionSet, allowing any_atomc_type. Is the XPath 2.0 signature for string-join() dropped again, or am I missing something?

Kind regards,

Johan Walters

Actions #10

Updated by Johan Walters over 1 year ago

  • Copied to Support #5965: string-join implementation always uses XPath 3.1 implementation added
Actions #11

Updated by Michael Kay over 1 year ago

  • Description updated (diff)

We made a conscious decision to drop the requirement for 100% XPath 2.0 conformance in cases where the only difference would be to raise an error for run-time conditions that XPath 3.1 allows but XPath 2.0 does not. This is documented at!conformance/xpath20

The example of string-join() accepting non-string arguments is given as a specific example.

We felt that the only adverse impact would be on people (like yourself) running conformance tests. Sorry for the inconvenience.

Please register to edit this issue

Also available in: Atom PDF