Search code examples
xmlxslttranslate

Converting XML Node Names to Uppercase (XSLT 1.0)


I have many XSLT stylesheet(s) that transform some XML into a csv file. The XML files used are generated based on database column names which used to be converted automatically to UPPERCASE when the XML was being built - which can no longer be done (we are no using TSQL-FOR XML to build the XML). The column names are Generally a mixture of uppercase and lowercase letters. As all Stylesheets currently reference Uppercase column names, the XPath queries are failing.

Instead of going through ALL XSL stylesheets and manually changing the XPath queries to the case of the database column names - which would take most of this year(!) Is there any way to convert all the XML 'Tag' names to Uppercase, so you can use them in the document?

Any help is greatly appreciated!!

Thank You! Andrew

An example: The below will generate a csv file with the right about Of rows, but without any data, as the xslt is looking for "STRNAME", when it is stored in The XML as "strName" my XML:

<XMLWRAPPER>
   <STAFFTABLE>
      <ROW>
         <strName>Andrew</strName>
         <strSurname>Smith</strSurname>
         <intuserType>1</intUserType>
      </ROW>
      <ROW>
         <strName>Jackie</strName>
         <strSurname>collins</strSurname>
         <intuserType>2</intUserType>
      </ROW>
    </STAFFTABLE>
  </XMLWRAPPER>

and the xslt:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes"/>

<xsl:template match="/">"First Name","Surname","User type"<xsl:text>&#013;</xsl:text>

    <xsl:for-each select="/XMLWRAPPER/STAFFTABLE/ROW">
        <xsl:value-of select="STRNAME"/>,<xsl:value-of select="STRSURNAME"/>,<xsl:value-of select="INTUSERTYPE"/><xsl:text>&#013;</xsl:text>
     </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Solution

  • In XSLT 1.0 I would use the Identity Transformation and the translate() function:

    <xsl:stylesheet 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">
    
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="*">
            <xsl:element name="{
                translate(name(.),
                'abcdefghijklmnopqrstuvwxyz',
                'ABCDEFGHIJKLMNOPQRSTUVWXYZ')}">
                <xsl:apply-templates select="node()|@*"/>
            </xsl:element>
        </xsl:template>
    
    </xsl:stylesheet>
    

    This transform will "upper case" elements only, not the attributes. It is easy anyway extend it to attributes just by changing the match pattern of the second template to *|@*.


    As per the comments below and the specs, translate() function is not a sufficient solution for case conversion in all languages.