i am new to XSLT and am wondering if it is possible to convert XML element and attribute names to camel case ?
My XML payload is like the below :
<?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>
Unfortunately i dont have anything to show as i am stumped on how to go about it .... thanks
CodePudding user response:
XSLT, direct approach
You can inline firstChar
variables, I've introduced them for readability.
<?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 2, named template for converting a string into camelCase
<?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>
Output
<?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>
CodePudding user response:
For XSLT 2/3 I would use the identity transformation plus templates matching element and attribute nodes that change the first letter using lower-case
:
<xsl:template match="*">
<xsl:element name="{prefix-from-QName(node-name())}{}{lower-case(substring(local-name(), 1, 1))}{substring(local-name(), 2)}">
<xsl:apply-templates select="@*, node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{prefix-from-QName(node-name())}{}{lower-case(substring(local-name(), 1, 1))}{substring(local-name(), 2)}" select="."/>
</xsl:template>