I am trying to call a Java method in Saxon XSLT. I can successfully call methods such as File.renameTo(), but Files.copy() fails because of the enum.
Here's the XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:files="java:java.nio.file.Files" xmlns:path="java:java.nio.file.Path" xmlns:copyopt="java:java.nio.file.StandardCopyOption" exclude-result-prefixes="files path copyopt" version="3.0" expand-text="yes">
<xsl:template match="/">
<xsl:if test="files:copy(path:of(xs:anyURI('file:///from.txt')),path:of(xs:anyURI('file:///to.txt')),copyopt:REPLACE_EXISTING)"/>
</xsl:template>
</xsl:stylesheet>
The error is:
There is more than one method matching the function call Q{java:java.nio.file.Files}copy#3, and there is insufficient type information to determine which one should be used
Any suggestions in how to type the enum REPLACE_EXISTING properly?
Firstly, the message "XPST0017 There is more than one method matching the function call Q{java:java.nio.file.Files}copy#3, and there is insufficient type information to determine which one should be used" is a little misleading in this case: using the -TJ option reveals that none of the candidate methods has suitable types.
So I tried changing the call on Files.copy#3 to a call on Files.move#3, which is very similar but does not have the overload. With a bit of adjustment, the following stylesheet works:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:saxon="http://saxon.sf.net/"
xmlns:files="java:java.nio.file.Files" xmlns:path="java:java.nio.file.Path"
xmlns:copyopt="java:java.nio.file.StandardCopyOption"
exclude-result-prefixes="#all" version="3.0" expand-text="yes">
<xsl:template match="/" name="xsl:initial-template">
<saxon:do action="files:move(
path:of(xs:anyURI('file:///Users/.../temp/from1.txt')),
path:of(xs:anyURI('file:///Users/.../temp/from2.txt')),
copyopt:REPLACE_EXISTING())"/>
</xsl:template>
</xsl:stylesheet>
(I used saxon:do
here to force the extension function to be called despite the fact that its result is never used.)
So Saxon is handling the enum type and the varargs argument with copyopt:REPLACE_EXISTING()
successfully if the method call is unambiguous, but when it has to do detailed type analysis to work out which of the two methods to call, it's finding neither of them suitable. Looking at the code, that's because the type analysis doesn't consider varargs: it establishes that an argument of type CopyOptions
isn't assignable to the required type array of CopyOptions
and doesn't take into account that with varargs, the call would actually work.