I have been trying my XSLT code in the online tool [XSLT 1.0 processor]:
http://www.freeformatter.com/xsl-transformer.html
Recently, I had to make use of xs:dateTime
and hence started using the tool that uses XSLT 2.0 processor,
http://xsltransform.net/
Now, when i was trying to solve a problem, i see that i get different output for the same input XML in these two processors. The code posted here is not the real code i am working on; this is to simulate the weird output i faced.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<book>
<title></title>
</book>
<phone>apple</phone>
</items>
XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes" />
<xsl:template match="/">
<items><xsl:apply-templates select="items/*" /></items>
</xsl:template>
<!-- ignore empty elements -->
<xsl:template match="*[not(normalize-space())]" />
<xsl:template match="book">
<newbook><xsl:apply-templates /></newbook>
</xsl:template>
<xsl:template match="title">
<newtitle><xsl:apply-templates /></newtitle>
</xsl:template>
<xsl:template match="phone">
<newphone><xsl:apply-templates /></newphone>
</xsl:template>
</xsl:stylesheet>
Output from http://xsltransform.net/
: [output 1]
<?xml version="1.0" encoding="UTF-8"?>
<items>
<newbook>
<newtitle/>
</newbook>
<newphone>apple</newphone>
</items>
Output from http://www.freeformatter.com/xsl-transformer.html
: [output 2]
<?xml version="1.0" encoding="UTF-8"?>
<items>
<newphone>apple</newphone>
</items>
Expected output XML is output 2
.
Any idea why this different output behavior?
note: I looked at another SO question: Generating two different outputs for the same XSL file?, but that is different.
Edit
To add more clarity on which tool produced which output:
http://xsltransform.net/
produced output 1
http://www.freeformatter.com/xsl-transformer.html
produced output 2
Update[02/10/2014] - regarding solution
Since the correct answer was first provided by Jim Garrison, that's marked as answer. However, there are other important points as well, as pointed out by others, Hence I am wrapping up all here.
<xsl:template match="*[not(normalize-space())]" />
The above template eliminates the empty nodes in both XSLT1 and XSLT2. Hence output 2 is correct
*Reason for getting output 1 from the tool - http://xsltransform.net/ :*
- As @michael.hor257k pointed out, there are two templates that matches the
<book>
element. - The tool was using Saxon-HE 9.5.1.3, and the output 1 behavior was probably a bug that was fixed in the latest maintenance release [@Michael Kay explained well in his answer]
- As @Ian Roberts mentioned in his answer, there is a concept of default priorities that are assigned to different types of templates.
Changing the template syntax to:
<xsl:template match="*[not(normalize-space())]" priority="2"/>
yields the same output in both the tools regardless of Saxon version, because we are explicitly defining the priority to the template.