Converting XML Node Names to Uppercase (XSLT 1.0)

2019-05-08 09:38发布

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>

2条回答
Animai°情兽
2楼-- · 2019-05-08 10:18

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.

查看更多
时光不老,我们不散
3楼-- · 2019-05-08 10:26

@empo 's solution is the one that can be used if the names consisted only of latin characters. If this isn't the case one can use a similar XSLT 2.0 transformation which replaces the translate() function in @empo's solution with the standard XPath 2.0 function upper-case().

Also, if you have just a few sylesheets, it may be much easier to modify the stylesheets themselves to handle mix-cased names:

That is:

Instead of

<xsl:template match="SOMENAME">

use:

 <xsl:template 
   match="*['SOMENAME' = translate(., $Lowercase, $Uppercase)]">
查看更多
登录 后发表回答