将 xml 元素和属性名称更改为驼峰式

change xml element and attribute names to camelCase

我是 XSLT 的新手,想知道是否可以将 XML 元素和属性名称转换为驼峰式大小写?

我的 XML 负载如下所示:

<?xml version="1.0" encoding="utf8" ?>
<Output>
    <Error>
        <Status>0</Status>
        <Details>No errors</Details>
    </Error>
    <Synopsis>
        <Count>451</Count>
    </Synopsis>
    <BankAccounts>
        <BankAccount AcctNo="103" CustName="Frank" BalanceAmount="" Inactive="N" NoOfAccounts="1" >
            <Addresses>
                <Address>ABC</Address>
                <Address>XYZ</Address>
            </Addresses>
        </BankAccount>
        <BankAccount AcctNo="101" CustName="Jane" BalanceAmount="10005" Inactive="N" NoOfAccounts="1" >
            <Addresses>
                <Address>LMN</Address>
                <Address>QWE</Address>
            </Addresses>
        </BankAccount>
        
    </BankAccounts>
</Output>

不幸的是我没有任何东西可以展示,因为我不知道如何去做.... 谢谢

XSLT 1.0,直接方法

您可以内联 firstChar 变量,为了便于阅读,我介绍了它们。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="1.0">
    
    <xsl:output method="xml" indent="yes"/>
    
    <!--elements-->
    <xsl:template match="node()">
        
        <xsl:choose>
            
            <!--elements-->
            <xsl:when test="name() != ''">
                <xsl:variable name="firstChar" select="translate(substring(name(),1,1),'ABCDEFGHIJKLMNOPQRSTUWXYZ','abcdefghijklmnopqrstuwxyz')"/>
                <xsl:element name="{concat($firstChar, substring(name(),2))}">            
                    <xsl:apply-templates select="@*|node()"/>    
                </xsl:element>        
            </xsl:when>
            
            <!--values-->
            <xsl:otherwise>
                <xsl:copy-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
        
    </xsl:template>
    
    <!--attributes-->
    <xsl:template match="@*">
        <xsl:variable name="firstChar" select="translate(substring(name(),1,1),'ABCDEFGHIJKLMNOPQRSTUWXYZ','abcdefghijklmnopqrstuwxyz')"/>
        <xsl:attribute name="{concat($firstChar, substring(name(),2))}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
    
</xsl:stylesheet>

XSLT 1.0,用于将字符串转换为驼峰式命名模板

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="1.0">
    
    <xsl:output method="xml" indent="yes"/>
    
    <!--elements-->
    <xsl:template match="node()">
        
        <xsl:choose>
            
            <!--elements-->
            <xsl:when test="name() != ''">                
                
                <xsl:variable name="newName">
                    <xsl:call-template name="toCamelCase">
                        <xsl:with-param name="value" select="./name()"/>
                    </xsl:call-template>
                </xsl:variable>                
                
                <xsl:element name="{$newName}">            
                    <xsl:apply-templates select="@*|node()"/>    
                </xsl:element>        
            </xsl:when>
            
            <!--values-->
            <xsl:otherwise>
                <xsl:copy-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
        
    </xsl:template>
    
    <!--attributes-->
    <xsl:template match="@*">
        
        <xsl:variable name="newName">
            <xsl:call-template name="toCamelCase">
                <xsl:with-param name="value" select="./name()"/>
            </xsl:call-template>
        </xsl:variable>                
        
        <xsl:attribute name="{$newName}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
    
    <!--named template that converts a string into camel case-->
    <xsl:template name="toCamelCase">
        <xsl:param name="value"/>
        <xsl:variable name="firstChar" select="translate(substring($value,1,1),'ABCDEFGHIJKLMNOPQRSTUWXYZ','abcdefghijklmnopqrstuwxyz')"/>
        <xsl:value-of select="concat($firstChar, substring($value,2))"/>
    </xsl:template>
    
</xsl:stylesheet>

输出

<?xml version="1.0" encoding="UTF-8"?>
<output>
    <error>
        <status>0</status>
        <details>No errors</details>
    </error>
    <synopsis>
        <count>451</count>
    </synopsis>
    <bankAccounts>
        <bankAccount acctNo="103"
                   custName="Frank"
                   balanceAmount=""
                   inactive="N"
                   noOfAccounts="1">
            <addresses>
                <address>ABC</address>
                <address>XYZ</address>
            </addresses>
        </bankAccount>
        <bankAccount acctNo="101"
                   custName="Jane"
                   balanceAmount="10005"
                   inactive="N"
                   noOfAccounts="1">
            <addresses>
                <address>LMN</address>
                <address>QWE</address>
            </addresses>
        </bankAccount>
        
    </bankAccounts>
</output>

对于 XSLT 2/3,我将使用身份转换加上模板匹配元素和属性节点,这些节点使用 lower-case:

更改第一个字母
<xsl:template match="*">
  <xsl:element name="{prefix-from-QName(node-name())}{':'[prefix-from-QName(node-name(current()))]}{lower-case(substring(local-name(), 1, 1))}{substring(local-name(), 2)}" namespace="{namespace-uri()}">
    <xsl:apply-templates select="@*, node()"/>
  </xsl:element>
</xsl:template>

<xsl:template match="@*">
  <xsl:attribute name="{prefix-from-QName(node-name())}{':'[prefix-from-QName(node-name(current()))]}{lower-case(substring(local-name(), 1, 1))}{substring(local-name(), 2)}" namespace="{namespace-uri()}" select="."/>
</xsl:template>

在 XSLT 3 中,您可以通过声明 <xsl:mode on-no-match="shallow-copy"/>(作为 xsl:stylesheetxsl:transform 的顶级子项)将身份转换设置为基本模板,在 XSLT 2 中您需要拼写为

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>