Running XSLTprocessor under PHP 5.2.11, I’ve run into an odd bug and have been able to replicate it with the W3Schools XSLT demo as well.
This is the streamlined case, which still produces the bug.
My goal is to take hierarchically structured XML and “flatten” it to create a row structure.
Input:
<?xml version="1.0"?>
<profiles>
<Subrecipient>
<SubrecipientName>TESTING123</SubrecipientName>
<Service>
<ServiceName>BEFORE</ServiceName>
<area>BETWEEN</area>
<TypeDesc>AFTER</TypeDesc>
</Service>
</Subrecipient>
</profiles>
Stylesheet:
<?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="html"/>
<!--generally, don't output nodes that have no children -->
<xsl:template match="//*[not(*)]" />
<!-- except in "dataout" mode, namely when we're matching at a low level -->
<xsl:template match="//*[not(*)]" mode="dataout" >
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="Service">
<row>
<!--next line selects all childless children of ancestors -->
<xsl:apply-templates select="ancestor::*/child::*[not(*)]" mode="dataout" />
<xsl:apply-templates select="*[not(*)]" mode="dataout" />
</row>
</xsl:template>
</xsl:stylesheet>
Desired output (spacing for clarity):
<row><subrecipientname>TESTING123</subrecipientname>
<servicename>BEFORE</servicename>
<area>BETWEEN</area>
<typedesc>AFTER</typedesc>
</row>
Actual output (for instance, from the W3Schools XSLT demo linked above):
<row><subrecipientname>TESTING123</subrecipientname>
<servicename>BEFORE</servicename>
<area>
<typedesc>AFTER</typedesc>
</row>
I.e. the XSLT processes generates bad xml, omitting both the content and the closing tag for the “area” element. If I rename that element as “area_”, all is well.
I don’t know what XSLT processor W3Schools is using, so perhaps this is just a PHP XSLTprocessor bug, or there’s something deep (and wonderful?) about XSLT and XPATH I don’t understand.
I’ve got a workaround, but I’d prefer to understand what I’ve run into here. Thanks for any help.
Yes, this is correct; the main cause of this is that you are using
xsl:outputwith html method. With this, the processor is allowed to output non well formed documents. Theareatag is an HTML tag without end tag as many others likebrand so on. You can resolve your problem just be changing output method to XML.You may experience the same behavior with any XSLT 1.0 compliant processor (like Saxon 6.5).