Reputation: 5
I have an input xml in which I have to group the elements, convert the Currency format and remove the namespace to add new namespace. I have created 3 XSLT program for each operation mentioned and the end result is fine if executed separately one after the other by feeding output of the first to second XSLT. However, I would like to combine all the XSLT templates into single XSLT transformation document. When combined, I am not getting the desired output xml, instead each node was added with namespace and grouping is going out of control without formatting the currency format. Sample XML is:
<?xml version="1.0" encoding="UTF-8"?>
<ns1:Root_Users xmlns:ns1="http://test.com/Users">
<Users>
<Id>111</Id>
<Name>aaa</Name>
<Division>HR</Division>
<Salary>1000</Salary>
</Users>
<Users>
<Id>222</Id>
<Name>bbb</Name>
<Division>FD</Division>
<Salary>2000</Salary>
</Users>
<Users>
<Id>333</Id>
<Name>ccc</Name>
<Division>HR</Division>
<Salary>3000</Salary>
</Users>
<Users>
<Id>444</Id>
<Name>ddd</Name>
<Division>FD</Division>
<Salary>4000</Salary>
</Users>
<Users>
<Id>555</Id>
<Name>eee</Name>
<Division>IT</Division>
<Salary>5000</Salary>
</Users>
</ns1:Root_Users>
I have used following XSLT transform to achieve the output.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" method="xml" indent="yes"/>
<!-- Grouping the Users for each Division -->
<xsl:key name="GroupKey" match="Users" use="Division"/>
<xsl:template match="/*">
<Root_Users>
<xsl:apply-templates/>
</Root_Users>
</xsl:template>
<xsl:template match="Users[generate-id()=generate-id(key('GroupKey',Division)[1])]">
<Department name="{Division}">
<xsl:copy-of select="key('GroupKey',Division)"/>
</Department>
</xsl:template>
<xsl:template match="Users[not(generate-id()=generate-id(key('GroupKey',Division)[1]))]"/>
<!-- Converting Salary to Denmark Currency Format -->
<xsl:decimal-format name="DenmarkCurrencyFormat" grouping-separator="." decimal-separator=","/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//Salary">
<xsl:copy>
<xsl:value-of select="format-number(., 'kr ###.###.###,00', 'DenmarkCurrencyFormat')"/>
</xsl:copy>
</xsl:template>
<!-- Removing and Adding new Namespace to Root -->
<xsl:template match="/*">
<xsl:element name="{local-name()}" namespace="http://test.com/Department">
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<xsl:template match="text() | comment() | processing-instruction()">
<xsl:copy />
</xsl:template>
</xsl:stylesheet>
When applied to the input xml, I am getting following output xml:
<Root_Users xmlns="http://test.com/Department">
<Department xmlns="" name="HR">
<Users xmlns:ns1="http://test.com/Users">
<Id>111</Id>
<Name>aaa</Name>
<Division>HR</Division>
<Salary>1000</Salary>
</Users>
<Users xmlns:ns1="http://test.com/Users">
<Id>333</Id>
<Name>ccc</Name>
<Division>HR</Division>
<Salary>3000</Salary>
</Users>
</Department>
<Department xmlns="" name="FD">
<Users xmlns:ns1="http://test.com/Users">
<Id>222</Id>
<Name>bbb</Name>
<Division>FD</Division>
<Salary>2000</Salary>
</Users>
<Users xmlns:ns1="http://test.com/Users">
<Id>444</Id>
<Name>ddd</Name>
<Division>FD</Division>
<Salary>4000</Salary>
</Users>
</Department>
<Department xmlns="" name="IT">
<Users xmlns:ns1="http://test.com/Users">
<Id>555</Id>
<Name>eee</Name>
<Division>IT</Division>
<Salary>5000</Salary>
</Users>
</Department>
</Root_Users>
But the desired output is as mentioned below.
<Root_Users xmlns="http://test.com/Department">
<Department name="HR">
<Users>
<Id>111</Id>
<Name>aaa</Name>
<Division>HR</Division>
<Salary>kr 1.000,00</Salary>
</Users>
<Users>
<Id>333</Id>
<Name>ccc</Name>
<Division>HR</Division>
<Salary>kr 3.000,00</Salary>
</Users>
</Department>
<Department name="FD">
<Users>
<Id>222</Id>
<Name>bbb</Name>
<Division>FD</Division>
<Salary>kr 2.000,00</Salary>
</Users>
<Users>
<Id>444</Id>
<Name>ddd</Name>
<Division>FD</Division>
<Salary>kr 4.000,00</Salary>
</Users>
</Department>
<Department name="IT">
<Users>
<Id>555</Id>
<Name>eee</Name>
<Division>IT</Division>
<Salary>kr 5.000,00</Salary>
</Users>
</Department>
</Root_Users>
Please help me to get the desired xml. I am very close but not able to find what exactly causing the issue. Much appreciated for your pointers.
Upvotes: 0
Views: 219
Reputation: 3738
Your solution was on the right track - 2 primary things I noticed:
<xsl:decimal-format>
instruction needs to be at the top level.When this XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://test.com/Department"
version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:decimal-format
name="DenmarkCurrencyFormat"
grouping-separator="."
decimal-separator=","/>
<xsl:key
name="kUserByDivision"
match="Users"
use="Division"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<Root_Users>
<xsl:apply-templates
select="*[generate-id() =
generate-id(key('kUserByDivision', Division)[1])]"/>
</Root_Users>
</xsl:template>
<xsl:template match="Users">
<Department name="{Division}">
<xsl:for-each select="key('kUserByDivision', Division)">
<Users>
<xsl:apply-templates/>
</Users>
</xsl:for-each>
</Department>
</xsl:template>
<xsl:template match="Users/*">
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="Salary/text()">
<xsl:value-of
select="concat('kr ',
format-number(.,
'###.###,00',
'DenmarkCurrencyFormat'))"/>
</xsl:template>
</xsl:stylesheet>
...is applied against the provided XML:
<?xml version="1.0" encoding="UTF-8"?>
<ns1:Root_Users xmlns:ns1="http://test.com/Users">
<Users>
<Id>111</Id>
<Name>aaa</Name>
<Division>HR</Division>
<Salary>1000</Salary>
</Users>
<Users>
<Id>222</Id>
<Name>bbb</Name>
<Division>FD</Division>
<Salary>2000</Salary>
</Users>
<Users>
<Id>333</Id>
<Name>ccc</Name>
<Division>HR</Division>
<Salary>3000</Salary>
</Users>
<Users>
<Id>444</Id>
<Name>ddd</Name>
<Division>FD</Division>
<Salary>4000</Salary>
</Users>
<Users>
<Id>555</Id>
<Name>eee</Name>
<Division>IT</Division>
<Salary>5000</Salary>
</Users>
</ns1:Root_Users>
...the wanted result is produced:
<Root_Users xmlns="http://test.com/Department">
<Department name="HR">
<Users>
<Id>111</Id>
<Name>aaa</Name>
<Division>HR</Division>
<Salary>kr 1.000,00</Salary>
</Users>
<Users>
<Id>333</Id>
<Name>ccc</Name>
<Division>HR</Division>
<Salary>kr 3.000,00</Salary>
</Users>
</Department>
<Department name="FD">
<Users>
<Id>222</Id>
<Name>bbb</Name>
<Division>FD</Division>
<Salary>kr 2.000,00</Salary>
</Users>
<Users>
<Id>444</Id>
<Name>ddd</Name>
<Division>FD</Division>
<Salary>kr 4.000,00</Salary>
</Users>
</Department>
<Department name="IT">
<Users>
<Id>555</Id>
<Name>eee</Name>
<Division>IT</Division>
<Salary>kr 5.000,00</Salary>
</Users>
</Department>
</Root_Users>
Upvotes: 1