This small post describes the process for upgrading xalan
-java
version to 2.7.1 to work compatible with Java 1.6
.
Xalan
-Java
is an XSLT
processor for transforming XML
documents into HTML, text, or other XML
document types.
The issues that needs to fix while upgrade XSL
to work with Java
JDK
1.6 and Xalan
2.7.1 will be discussed here and in this post we will look in to sample examples that help us to create XSL
’s to work compatible with these new version.
Please note that the problems identified here work well with Java
JDK
1.5. Therefore, these changes require only, if we want our XSL
to parse successfully with Java
JDK
1.6.
xsl:import
This element must appear as the first child node of xsl:stylesheet
or xsl:transform
. It should not appear in the end or middle of the stylesheet
. Otherwise it throws exception
“Error! xsl:import is not allowed in this position in the stylesheet!”
xsl:template
xsl:template
must either have name or match attribute. If the name attribute is omitted then there must be a match attribute. For example, the code
<xsl:template > <xsl:text> -- </xsl:text> </xsl:template>
throw
exceptions
“Fatal Error! java.lang.RuntimeException: ElemTemplateElement error: xsl:template requires either a name or a match attribute.”
The below code will execute successfully.
<xsl:template name="main"> <xsl:text> -- </xsl:text> </xsl:template>
xsl:value-of
xsl:value-of cannot be enclosed under xsl:text.For example, the code
<xsl:text> <xsl:value-of select="@name"/> </xsl:text>
will throw exception
“Error! xsl:value-of is not allowed in this position in the stylesheet!”
The code
stream
.Use StringBuffer/StringBuilder in XSL
XSL
Code such as
<xsl:variable name="allTableNames" select="java:java.lang.StringBuffer.new()" /> <xsl:variable name="void0" select="java:append($allTableNames, concat('', $toAppend))" />
throw exception
java.lang.IllegalArgumentException: argument type mismatch
and java.lang.NullPointerException
The reason is that the
org.apache.xalan.extensions.MethodResolver
picks a method whose argument types are not converted properly. This was noticed in the new versions of JVM
due to the order at which they return all methods available for a given class and the issue is still not resolved yet.
Further information can be refer to
https://issues.apache.org/jira/browse/XALANJ-2374
https://issues.apache.org/jira/browse/XALANJ-2315
I have replaced
StringBuilder
with Map to correctly transform the XSL.
XSL DTMNodeIterator
Consider the following XSL.<xsl:variable name="temp_core_alias_value"> <xsl:choose> <xsl:when test="'true'"> <xsl:text>, CASE WHEN </xsl:text><xsl:text>. </xsl:text> <xsl:text> IS NULL THEN </xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>,</xsl:text> <xsl:text>.</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="temp_core_alias" select="java:put($processedMap, $temp_core_alias_value, 'Test Value')"/> <xsl:variable name="hasValue" select="java:containsKey($processedMap, $temp_core_alias_value)"/> <xsl:if test="$hasValue = 'true'"> <xsl:text>Value exist in Map = </xsl:text> <xsl:value-of select="java:get($processedMap, $temp_core_alias_value)"/> </xsl:if> </xsl:variable> </xsl:variable>At this point, we might expect
java:containsKey($processedMap,$temp_core_alias_value)
to return true and the output of the above as “Value exist in Map = Test Value” But when transform using Xalan
-Java
2.7.1, the Map
return false
and therefore no output appear.
The reason is that the evaluating expression for the temp_core_alias_value variable would return
org.apache.xml.dtm.ref.DTMNodeIterator@e020c9 and therefore, the
contains
method of the Map
would always return false
regardless of the key
present.
We can transform
DTMNodeIterator
to normal String
form by concatenate an empty string
with temp_core_alias_value variable like the following
<xsl:variable name="temp_core_alias_value" select="concat('', $temp_core_alias_value)" />
Adding this line right before put in to the Map would result in the normal expected output.