The backstory is that this is an old ColdFusion Application that is being upgraded to ColdFusion 11. I've already determined the subject error I'm now seeing is because XSLT 1.0 processors were allowed to ignore this error and "recover" by ignoring the xsl:attribute instruction. (Thank you ref Michael Kay.)
I can't quite wrap my brain around a solution, so here's some simplified code:
The XML
<?xml version="1.0" encoding="UTF-8"?>
<Organization>
<Subscriber>
<data>
<struct>
<var name='DEPENDENT'>
<array length='1'>
<struct>
<var name='PROVIDER'>
<struct>
<var name='PROVIDERCODE'>
<string>A4321</string>
</var>
<var name='TYPE'>
<string>Primary Care Provider</string>
</var>
</struct>
</var>
</struct>
</array>
</var>
</struct>
</data>
</Subscriber>
</Organization>
You may recognize this as old WDDX format. The XSLT below converts this ugly, deeply-nested format to a cleaner/simpler XML format.
The XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="var">
<xsl:choose>
<xsl:when test="translate(@name, 'TEX', 'tex') = 'text'">
<xsl:value-of select="./string"/>
</xsl:when>
<xsl:when test="translate(@name, 'TYPE', 'type') = 'type'">
<xsl:attribute name="type">
<xsl:value-of select="./string"/>
</xsl:attribute>
</xsl:when>
<xsl:when test="child::array">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{translate(@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="struct">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="array">
<xsl:param name="parentname" select="translate(../@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')"/>
<xsl:for-each select="struct">
<xsl:element name="{$parentname}">
<xsl:if test="./var[translate(@name, 'RELATIONSHPCD', 'relationshpcd') = 'relationshipcode']">
<xsl:attribute name="relationshipcode"><xsl:value-of select="./var[translate(@name, 'RELATIONSHPCD', 'relationshpcd') = 'relationshipcode']"/></xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</xsl:element>
</xsl:for-each>
</xsl:template>
<xsl:template match="string|number">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="boolean">
<xsl:value-of select="@value"/>
</xsl:template>
<xsl:template match="Subscriber">
<subscriber>
<xsl:apply-templates/>
</subscriber>
</xsl:template>
<xsl:template match="Organization">
<organization>
<xsl:apply-templates/>
</organization>
</xsl:template>
</xsl:stylesheet>
Unfortunately, the case of the WDDX name attributes is inconsistent, so the translate commands are there to address that, and unfortunately, make the code a bit more complex.
The Expected Output
<?xml version="1.0" encoding="UTF-8"?>
<organization>
<subscriber>
<dependent>
<provider type="Primary Care Provider">
<providercode>A4321</providercode>
</provider>
</dependent>
</subscriber>
</organization>
The Problem
The problem arises from the fact that, in the example above, the "providercode" could get added to the "provider" node before the "type" node gets encountered, resulting in the "attribute node cannot be created after the children of the containing element" error.o
Note that I've simplified the example above for clarity. There are roughly a half-dozen "var" nodes with specific "name" attributes that should be inserted as attributes while the others simple get added directly as nodes.
Any help in how to solve this would be greatly appreciated.
Thanks in advance.
Paul