i have to duplicate the xml payload into as many xml payloads based on a specific id, e.g., userid
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
<ns2:UserId>237</ns2:UserId>
</ns2:Details>
i need the output as
<ns2:Details>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
<ns2:Details>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>237</ns2:UserId>
</ns2:Details>
is this possible
Update: The below answer that was given is working fine, but there's a small catch I failed to mention. If the userid is the same and it's repeating, then the same xml payload should be displayed. For this I tried the following to get the unique elements of userid
<xsl:param name="userId" select="ns0:UserId[generate-id(.)=generate-id(key('k', ns0:UserId)[1])]"/>
but this is not working and also tried using above
..[generate-id(.)=generate-id(key('k', ns0:UserId)[1])]
at template level also it is not working
Am I missing something?
Update : i made a small modification to the above code, instead of working at xsl:param, i have used it at xsl:apply-template
before modification (provided as answer to me) <xsl:apply-templates select="//ns2:Details/ns2:UserId"/> after modification <xsl:apply-templates select="//ns2:Details/ns2:UserId[generate-id(.)=generate-id(key('myUserId', .)[1])]"/>
my mistake i was using ns2:userid instead of "."
full xsl code ---
<xsl:output method="xml" indent="yes"/> <xsl:key name="k" match="ns2:UserId" use="text()"/> <xsl:key name="myUserId" match="ns2:UserId" use="."/> <xsl:template match="/"> <ns2:Root> <xsl:apply-templates select="//ns2:Details/ns2:UserId[generate-id(.)=generate-id(key('myUserId', .)[1])]"/> </ns2:Root> </xsl:template>
<xsl:template match="//ns2:Details"> <xsl:param name="userId" select="ns2:UserId"/> <ns2:Details> <xsl:copy-of select="key('k', $userId)[1]"/> <!-- displays UserId values--> <xsl:copy-of select="./*[name() != 'ns2:UserId']"/> <!-- displays other values--> </ns2:Details> </xsl:template>
<xsl:template match="ns2:UserId"> <xsl:apply-templates select=".."> <xsl:with-param name="userId" select="."/> </xsl:apply-templates> </xsl:template>
Please, validate it. this too is working for me...
Duplicate XML schema definitionsImported XSD and WSDL files can contain duplicate XML element type schema definitions. At run time, these duplicate definitions are treated as different Java object types, even though they are referenced by the same business object type and namespace.
We first use the nodes function to convert from XML to relational data, then use value to get the text inside the Name node. We then put the result of the previous step into a CTE, and use a simple group by to get the value with multiple occurences.
Supposed XML:
<ns2:Details xmlns:ns2="ns2">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
<ns2:UserId>237</ns2:UserId>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="ns2"
>
<xsl:output method="xml" indent="yes"/>
<xsl:key name="k" match="ns2:UserId" use="text()"/>
<xsl:template match="/">
<root>
<xsl:apply-templates select="//ns2:Details/ns2:UserId[not(node() = preceding-sibling::node())]"/>
</root>
</xsl:template>
<xsl:template match="//ns2:Details">
<xsl:param name="userId" select="ns2:UserId"/>
<ns2:Details>
<xsl:copy-of select="key('k', $userId)[not(node() = preceding-sibling::node())]"/>
<xsl:copy-of select="./*[name() != 'ns2:UserId']"/>
</ns2:Details>
</xsl:template>
<xsl:template match="ns2:UserId">
<xsl:apply-templates select="..">
<xsl:with-param name="userId" select="."/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
Output XML:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:ns2="ns2">
<ns2:Details>
<ns2:UserId>46</ns2:UserId>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
</ns2:Details>
<ns2:Details>
<ns2:UserId>237</ns2:UserId>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
</ns2:Details>
</root>
This transformation (short, only two templates, no xsl:for-each
, no modes):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="ns">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kIdByVal" match="ns2:UserId" use="."/>
<xsl:template match="/">
<xsl:apply-templates select=
"ns2:Details/ns2:UserId
[generate-id()=generate-id(key('kIdByVal',.)[1])]
"/>
</xsl:template>
<xsl:template match="ns2:UserId">
<ns2:Details>
<xsl:copy-of select=
"../node()
[not(self::ns2:UserId
[not(generate-id()=generate-id(current()))])
]"/>
</ns2:Details>
</xsl:template>
</xsl:stylesheet>
when applied on this XML document (containing redundant ns2:UserId
elements):
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
<ns2:UserId>237</ns2:UserId>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
produces exactly the wanted, correct result:
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>237</ns2:UserId>
</ns2:Details>
Explanation: Muenchian grouping, xsl:copy-of
, use of current()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With