Reputation: 35
starting with this XML (to be imported in Access):
<?xml version="1.0" encoding="UTF-8"?>
<ITEM>
<PRODUCT_CODE TYPE="EPSON">V11H106040JA</PRODUCT_CODE>
<PRODUCT_CODE TYPE="EAN">8715946168340</PRODUCT_CODE>
<DESCRIPTION>EMP-73 VIDEOPROJECTOR</DESCRIPTION>
<QUANTITY TYPE="MINQTY" UNIT="PCE">20.0000000000</QUANTITY>
<QUANTITY TYPE="MAXQTY" UNIT="PCE">20.0000000000</QUANTITY>
<QUANTITY TYPE="MINORDQTY" UNIT="PCE">0</QUANTITY>
<PRICE TYPE="DIRECT">2000.0000</PRICE>
<PRICE TYPE="INDIRECT" />
<PRICE TYPE="FINAL" />
<CURRENCY>EUR</CURRENCY>
<CATEGORY TYPE="ONE1">51</CATEGORY>
</ITEM>
and this XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ITEM">
<xsl:copy>
<xsl:for-each select="*">
<xsl:if test="@*">
<xsl:element name="{@*}"><xsl:value-of select="."/>
</xsl:element>
</xsl:if>
</xsl:for-each>
<xsl:copy-of select="*[not(@*)]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I got this:
<?xml version="1.0" encoding="UTF-8"?>
<ITEM>
<EPSON>V11H106040JA</EPSON>
<EAN>8715946168340</EAN>
<MINQTY>20.0000000000</MINQTY>
<MAXQTY>20.0000000000</MAXQTY>
<MINORDQTY>0</MINORDQTY>
<DIRECT>2000.0000</DIRECT>
<INDIRECT/>
<FINAL/>
<ONE1>51</ONE1>
<DESCRIPTION>EMP-73 VIDEOPROJECTOR</DESCRIPTION>
<CURRENCY>EUR</CURRENCY>
</ITEM>
But, if I change the XML at row 13 as follows
<CATEGORY TYPE="1">51</CATEGORY>
(TYPE attribute became a number) I get a conversion error "cannot apply stylesheet", WHY?!? How should I change my XSLT to get the following result?
<CATEGORY-1>51</CATEGORY-1>
Upvotes: 1
Views: 640
Reputation: 7385
You are making the attribute value the name of the new element, but XML element names can not start with a number. So you would have to detect this and prepend the previous element name, like you suggested.
Try this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ITEM">
<xsl:copy>
<xsl:for-each select="*">
<xsl:if test="@*">
<xsl:choose>
<xsl:when test="number(substring(@*[1], 1, 1)+1)">
<!-- when attribute value starts with number -->
<xsl:element name="{concat(name(.), '-', @*)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{@*}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:for-each>
<xsl:copy-of select="*[not(@*)]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Fiddle: http://xsltransform.net/94AbWBW/1
Upvotes: 3