Paccus
Paccus

Reputation: 35

XSLT when attribute is a number

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

Answers (1)

fafl
fafl

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

Related Questions