Reputation: 53
As the below source XML Value/string element value has to be replace with target element value, Could some please help me out how to create the XSL to transform from source xml into target xml .Please.
<PricingResultsV6>
<subItems>
<SubItem>
<profiles>
<ProfileValues>
<values>
<strings>800210</strings>
<strings>THC</strings>
<strings>10.0</strings>
<strings>20.0</strings>
<strings>30.0</strings>
<strings>40.0</strings>
<strings>550.0</strings>
<strings>640.0</strings>
</values>
</ProfileValues>
</rofiles>
</SubItem>
</subItems>
</PricingResultsV6>
Target XML :
<CalculationOutput>
<PolicyNumber> 800210 </PolicyNumber>
<CommissionFactorMultiplier> THC </CommissionFactorMultiplier>
<PremiumValue>10.0</PremiumValue>
<SalesmanCommissionValue>20.0</SalesmanCommissionValue>
<ManagerCommissionValue>30.0</ManagerCommissionValue>
<GL_COR> 550.0</GL_COR>
<GL_OPO>640.0</GL_OPO>
</CalculationOutput>
Upvotes: 2
Views: 1344
Reputation: 52878
Ugh. I just answered the exact duplicate to this question.
Since both of my XSLT 1.0 examples and my XSLT 2.0 example are covered by Dimitre's and Kirill's answers, I'll add my XSLT 3.0 answer...
XML Input
<PricingResultsV6>
<subItems>
<SubItem>
<profiles>
<ProfileValues>
<values>
<strings>800210</strings>
<strings>THC</strings>
<strings>10.0</strings>
<strings>20.0</strings>
<strings>30.0</strings>
<strings>40.0</strings>
<strings>550.0</strings>
<strings>640.0</strings>
</values>
</ProfileValues>
</profiles>
</SubItem>
</subItems>
</PricingResultsV6>
XSLT 3.0 (tested with Saxon-EE 9.4)
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
exclude-result-prefixes="map">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vMap" select="map {
1:='PolicyNumber',
2:='CommissionFactorMultiplier',
3:='PremiumValue',
4:='SalesmanCommissionValue',
5:='ManagerCommissionValue',
7:='GL_COR',
8:='GL_OPO',
}"/>
<xsl:template match="ProfileValues">
<CalculationOutput>
<xsl:apply-templates select="values/strings"/>
</CalculationOutput>
</xsl:template>
<xsl:template match="strings[map:contains($vMap,position())]">
<xsl:element name="{map:get($vMap,position())}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
XML Output
<CalculationOutput>
<PolicyNumber>800210</PolicyNumber>
<CommissionFactorMultiplier>THC</CommissionFactorMultiplier>
<PremiumValue>10.0</PremiumValue>
<SalesmanCommissionValue>20.0</SalesmanCommissionValue>
<ManagerCommissionValue>30.0</ManagerCommissionValue>
<GL_COR>550.0</GL_COR>
<GL_OPO>640.0</GL_OPO>
</CalculationOutput>
Upvotes: 1
Reputation: 243529
This generic transformation allows separate (even in a different document or passed as external parameter) mapping between the strings
elements and the corresponding element name that must be generated:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" exclude-result-prefixes="my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:mapping>
<map key="1" value="PolicyNumber"/>
<map key="2" value="CommissionFactorMultiplier"/>
<map key="3" value="PremiumValue"/>
<map key="4" value="SalesmanCommissionValue"/>
<map key="5" value="ManagerCommissionValue"/>
<map key="7" value="GL_COR"/>
<map key="8" value="GL_OPO"/>
</my:mapping>
<xsl:variable name="vMaps" select="document('')/*/my:mapping/*"/>
<xsl:template match="values">
<CalculationOutput>
<xsl:apply-templates/>
</CalculationOutput>
</xsl:template>
<xsl:template match="strings">
<xsl:if test="position()=$vMaps/@key">
<xsl:variable name="vPos" select="position()"/>
<xsl:element name="{$vMaps[@key = $vPos]/@value}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<PricingResultsV6>
<subItems>
<SubItem>
<profiles>
<ProfileValues>
<values>
<strings>800210</strings>
<strings>THC</strings>
<strings>10.0</strings>
<strings>20.0</strings>
<strings>30.0</strings>
<strings>40.0</strings>
<strings>550.0</strings>
<strings>640.0</strings>
</values>
</ProfileValues>
</profiles>
</SubItem>
</subItems>
</PricingResultsV6>
the wanted, correct result is produced:
<CalculationOutput>
<PolicyNumber>800210</PolicyNumber>
<CommissionFactorMultiplier>THC</CommissionFactorMultiplier>
<PremiumValue>10.0</PremiumValue>
<SalesmanCommissionValue>20.0</SalesmanCommissionValue>
<ManagerCommissionValue>30.0</ManagerCommissionValue>
<GL_COR>550.0</GL_COR>
<GL_OPO>640.0</GL_OPO>
</CalculationOutput>
II. This solution can be made very efficient by using keys:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" exclude-result-prefixes="my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:mapping>
<map key="1" value="PolicyNumber"/>
<map key="2" value="CommissionFactorMultiplier"/>
<map key="3" value="PremiumValue"/>
<map key="4" value="SalesmanCommissionValue"/>
<map key="5" value="ManagerCommissionValue"/>
<map key="7" value="GL_COR"/>
<map key="8" value="GL_OPO"/>
</my:mapping>
<xsl:variable name="vMaps" select="document('')/*/my:mapping/*"/>
<xsl:key name="kValueByKey" match="@value" use="../@key"/>
<xsl:template match="values">
<CalculationOutput>
<xsl:apply-templates/>
</CalculationOutput>
</xsl:template>
<xsl:template match="strings">
<xsl:if test="position()=$vMaps/@key">
<xsl:variable name="vPos" select="position()"/>
<xsl:variable name="vCur" select="."/>
<xsl:for-each select="$vMaps/..">
<xsl:element name="{key('kValueByKey', $vPos)}">
<xsl:value-of select="$vCur"/>
</xsl:element>
</xsl:for-each>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Reputation: 56182
Use:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="//values">
<CalculationOutput>
<PolicyNumber>
<xsl:value-of select="strings[1]"/>
</PolicyNumber>
<CommissionFactorMultiplier>
<xsl:value-of select="strings[2]"/>
</CommissionFactorMultiplier>
<PremiumValue>
<xsl:value-of select="strings[3]"/>
</PremiumValue>
<SalesmanCommissionValue>
<xsl:value-of select="strings[4]"/>
</SalesmanCommissionValue>
<ManagerCommissionValue>
<xsl:value-of select="strings[5]"/>
</ManagerCommissionValue>
<GL_COR>
<xsl:value-of select="strings[7]"/>
</GL_COR>
<GL_OPO>
<xsl:value-of select="strings[8]"/>
</GL_OPO>
</CalculationOutput>
</xsl:template>
</xsl:stylesheet>
Input:
<PricingResultsV6>
<subItems>
<SubItem>
<profiles>
<ProfileValues>
<values>
<strings>800210</strings>
<strings>THC</strings>
<strings>10.0</strings>
<strings>20.0</strings>
<strings>30.0</strings>
<strings>40.0</strings>
<strings>550.0</strings>
<strings>640.0</strings>
</values>
</ProfileValues>
</profiles>
</SubItem>
</subItems>
</PricingResultsV6>
Output:
<CalculationOutput>
<PolicyNumber>
800210
</PolicyNumber>
<CommissionFactorMultiplier>
THC
</CommissionFactorMultiplier>
<PremiumValue>
10.0
</PremiumValue>
<SalesmanCommissionValue>
20.0
</SalesmanCommissionValue>
<ManagerCommissionValue>
30.0
</ManagerCommissionValue>
<GL_COR>
550.0
</GL_COR>
<GL_OPO>
640.0
</GL_OPO>
</CalculationOutput>
Upvotes: 2