简体   繁体   中英

Wrap last unique element based on Attribute in XSLT

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>

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM