Search code examples
xpathxsltant

ant.xslt/Xalan fails referencing namespaced nodes from an external file


In an .xsl file I want to use nodes from a separate file ("foo.xsd"). The .xsl file uses an explicit namespace prefix, the external file doesn't but rather relies on a default namespace. Their namespace URIs match up.

Reading in the nodes, with ant.xslt the following XPath expression results in an ArrayIndexOutOfBounds exception later

document('foo.xsd')/xsd:schema/xsd:*

while it works when removing the last reference to the namespace prefix

document('foo.xsd')/xsd:schema/*

Here is a minimal example that reproduces the issue. The transformation input file

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
   <element name="bar"/>
</schema>

and a transformation .xsl file

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  version="1.0">
  <xsl:variable name="nodeSet" select="document('foo.xsd')/xsd:schema/xsd:*[@name]"/>
    <xsl:template match="/xsd:schema/xsd:element">
      <xsl:value-of select="$nodeSet/@name"/>
   </xsl:template>
</xsl:stylesheet>

The referenced foo.xsd is just a copy of the input file, so in this cut down example I'm running over one instance of the file and reading in the other instance in the stylesheet.

Goold ol' xsltproc is extracting the right attribute value ("bar"). ant.xslt with the default processor (Xalan) throws an ArrayIndexOutOfBoundsException (I presume when looking for the colon insided the element name).The problem only arises when referencing nodeSet as in the <xsl:value-of> element.

The <xsl:template> matches in all cases, using prefixes.

My question is: Did I hit a bug in Xalan, or am I doing something generally wrong?

I'm aware of the various work-arounds concerning namespace prefixes, like using [local-name() = 'element'] and such, so please don't post answers in that vein. I'm looking for a general answer whether this should work (like, according to the specs).

Background Material

Stacktrace (part.) that hints at Xalan:

...
Caused by: javax.xml.transform.TransformerException: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 512
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:783)
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:370)
        at org.apache.tools.ant.taskdefs.optional.TraXLiaison.transform(TraXLiaison.java:201)
        at org.apache.tools.ant.taskdefs.XSLTProcess.process(XSLTProcess.java:870)
        ... 126 more
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 512
        at java.xml/com.sun.org.apache.xml.internal.utils.SuballocatedIntVector.elementAt(SuballocatedIntVector.java:441)
        at java.xml/com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase._firstch(DTMDefaultBase.java:523)
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl.access$200(SAXImpl.java:73)
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl$NamespaceChildrenIterator.next(SAXImpl.java:1431)
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.dom.CurrentNodeListIterator.setStartNode(CurrentNodeListIterator.java:158)
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.dom.StepIterator.setStartNode(StepIterator.java:97)
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.dom.StepIterator.setStartNode(StepIterator.java:97)
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.dom.DupFilterIterator.setStartNode(DupFilterIterator.java:97)
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.dom.CachedNodeListIterator.setStartNode(CachedNodeListIterator.java:57)
        at jdk.translet/die.verwandlung.test.topLevel()
        at jdk.translet/die.verwandlung.test.transform()
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(AbstractTranslet.java:624)
        at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:776)
        ... 129 more

Invokation is through Gradle via shell command gradlew mytask using the Gradle built-in Ant using its built-in ant.xslt task.

build.gradle:

tasks.register('mytask') {
    doLast {
        ant.xslt(
            baseDir: '.',
            in: 'input.xsd',
            out: 'out.xml',
            style: 'stylefile.xsl'
        )
    }
}

Solution

  • Your xslt/xml code is fine (works with Saxon). So it's either something in the way you're running the transformation, or it's a bug in the version of Xalan that you're using.

    Xalan shouldn't be throwing an ArrayIndexOutOfBounds exception anyway. It's presumably Xalan code on the stack trace?