Reputation: 1
How can I wrap last unique elements in XSLT
Input:
<main>
<level1>
<level2 ID="spa3" type="starpage_print" product-citation-id="Ia9572840aadb11e6aa049569ac37328a" productTypeId="1" pubId="7047" starDesc="Main" shortName="Cal.Rptr.3d" venueId="2055">Cal.Rptr.3d 281</level2>
</level1>
<level1>
<level2 ID="spa4" type="starpage_print" product-citation-id="Ia9572840aadb11e6aa049569ac37328a" productTypeId="1" pubId="7047" starDesc="Main" shortName="Cal.Rptr.3d" venueId="2055">Cal.Rptr.3d 282</level2>
</level1>
<level1>
<level2 ID="spb5" product-citation-id="Ia9572840aadb11e6aa049569ac37328a" productTypeId="1" pubId="7047" starDesc="Main" shortName="Cal.Rptr.3d" venueId="2055" type="starpage_print">Cal.Rptr.3d 283</level2>
</level1>
<level1>
<level2 ID="spb1" product-citation-id="Ia956b310aadb11e6aa049569ac37328a" productTypeId="1" pubId="4645" starDesc="Both" shortName="P.3d" venueId="2055" type="starpage_print">P.3d 1117</level2>
</level1>
<level1>
<level2 ID="spb2" product-citation-id="Ia956b310aadb11e6aa049569ac37328a" productTypeId="1" pubId="4645" starDesc="Both" shortName="P.3d" venueId="2055" type="starpage_print">P.3d 1118</level2>
</level1>
</main>
I need to find the last unique element based on pubId attribute. In this example there are 2 distinct pubId's 7047 and 4645. I need to find the last occurrence of this.
Expected output :
<main>
<level1>
<level2 ID="spa3" type="starpage_print" product-citation-id="Ia9572840aadb11e6aa049569ac37328a" productTypeId="1" pubId="7047" starDesc="Main" shortName="Cal.Rptr.3d" venueId="2055">Cal.Rptr.3d 281</level2>
</level1>
<level1>
<level2 ID="spa4" type="starpage_print" product-citation-id="Ia9572840aadb11e6aa049569ac37328a" productTypeId="1" pubId="7047" starDesc="Main" shortName="Cal.Rptr.3d" venueId="2055">Cal.Rptr.3d 282</level2>
</level1>
<level3>
<level1>
<level2 ID="spb5" product-citation-id="Ia9572840aadb11e6aa049569ac37328a" productTypeId="1" pubId="7047" starDesc="Main" shortName="Cal.Rptr.3d" venueId="2055" type="starpage_print">Cal.Rptr.3d 283</level2>
</level1>
</level3>
<level1>
<level2 ID="spb1" product-citation-id="Ia956b310aadb11e6aa049569ac37328a" productTypeId="1" pubId="4645" starDesc="Both" shortName="P.3d" venueId="2055" type="starpage_print">P.3d 1117</level2>
</level1>
<level3>
<level1>
<level2 ID="spb2" product-citation-id="Ia956b310aadb11e6aa049569ac37328a" productTypeId="1" pubId="4645" starDesc="Both" shortName="P.3d" venueId="2055" type="starpage_print">P.3d 1118</level2>
</level1>
</level3>
</main>
Upvotes: 0
Views: 38
Reputation: 167581
Assuming XSLT 2.0 you can identify the last item in a group defined by a key as follows:
<?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="2.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:key name="group" match="level2" use="@pubId"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="level1[level2[. is key('group', @pubId)[last()]]]">
<level3>
<xsl:copy-of select="."/>
</level3>
</xsl:template>
</xsl:stylesheet>
Using XSLT 1.0 you can use the same key but would need to write the last template as
<xsl:template match="level1[level2[generate-id() = generate-id(key('group', @pubId)[last()])]]">
<level3>
<xsl:copy-of select="."/>
</level3>
</xsl:template>
Upvotes: 1