Comparing 2 consecutive Rows of XML using XSLT -
hi trying compare 2 consecutive entries following xml.
<wd:report_data xmlns:wd="urn:com.workday.report/test"> <wd:report_entry> <wd:location_changes> <wd:employeeid>111111</wd:employeeid> <wd:countrycode>us</wd:countrycode> <wd:regioncode>rx</wd:regioncode> <wd:startdate>2013-07-01</wd:startdate> </wd:location_changes> <wd:location_changes> <wd:employeeid>111111</wd:employeeid> <wd:countrycode>us</wd:countrycode> <wd:regioncode>md</wd:regioncode> <wd:startdate>2009-09-14</wd:startdate> </wd:location_changes> <wd:location_changes> <wd:employeeid>111111</wd:employeeid> <wd:countrycode>us</wd:countrycode> <wd:regioncode>md</wd:regioncode> <wd:startdate>2009-10-14</wd:startdate> </wd:location_changes> <wd:location_changes> <wd:employeeid>111111</wd:employeeid> <wd:countrycode>us</wd:countrycode> <wd:regioncode>rx</wd:regioncode> <wd:startdate>2014-07-01</wd:startdate> </wd:location_changes> </wd:report_entry> </wd:report_data>
the output is:
employeeid|countrycode|regioncode|startdate "111111"|"us"|"rx"|"2014-07-01" "111111"|"us"|"md"|"2009-10-14" "111111"|"us"|"md"|"2009-09-14" "111111"|"us"|"rx"|"2013-07-01""
but expecting:
employeeid|countrycode|regioncode|startdate "111111"|"us"|"rx"|"2014-07-01" "111111"|"us"|"md"|"2009-10-14" "111111"|"us"|"rx"|"2013-07-01"
if there consecutive entry same combination "employeeid|regioncode", entry should not included. have used primary key make sure there no duplicate entry.
i using following xslt:
<?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" xmlns:wd="urn:com.workday.report/test" exclude-result-prefixes="xs" version="2.0"> <xsl:output method="text" omit-xml-declaration="yes"/> <!-- variables hold fillers - pipe, new line, double quotes --> <xsl:variable name="delimiter" select="'|'"/> <xsl:variable name="linefeed" select="'
'"/> <xsl:variable name="dquote">"</xsl:variable> <xsl:variable name="duplicate_key" match="wd:report_data/wd:report_entry/wd:location_changes" select="concat(wd:employeeid,'|',wd:regioncode)" /> <!--to remove duplicates--> <xsl:key name="primary_key" match="wd:report_data/wd:report_entry/wd:location_changes" use="concat(wd:employeeid,'|',wd:regioncode,'|',wd:startdate)" /> <xsl:template match="/"> <!-- header row begin --> <xsl:text>employeeid</xsl:text> <xsl:value-of select="$delimiter"/> <xsl:text>countrycode</xsl:text> <xsl:value-of select="$delimiter"/> <xsl:text>regioncode</xsl:text> <xsl:value-of select="$delimiter"/> <xsl:text>startdate</xsl:text> <xsl:value-of select="$linefeed"/> <!-- header row end --> <!-- data row starts --> <!-- parse each , every employee record --> <!--to reverse records , remove duplicates--> <xsl:for-each select="wd:report_data/wd:report_entry/wd:location_changes[generate-id()= generate-id(key('primary_key',concat(wd:employeeid,'|',wd:regioncode,'|',wd:startdate))[1])]"> <xsl:sort select="position()" data-type="number" order="descending"/> <xsl:call-template name="output"> <xsl:with-param name="unique_code"/> </xsl:call-template> </xsl:for-each> </xsl:template> <xsl:template name="output"> <xsl:param name="unique_code"/> <!-- data row begins --> <xsl:if test="$duplicate_key != concat(wd:employeeid,'|',wd:regioncode)"> <!-- #1 employeeid --> <xsl:value-of select="$dquote"/> <xsl:value-of select="wd:employeeid"/> <xsl:value-of select="$dquote"/> <xsl:value-of select="$delimiter"/> <!-- #2 countrycode --> <xsl:value-of select="$dquote"/> <xsl:value-of select="wd:countrycode"/> <xsl:value-of select="$dquote"/> <xsl:value-of select="$delimiter"/> <!-- #3 regioncode--> <xsl:value-of select="$dquote"/> <xsl:value-of select="wd:regioncode"/> <xsl:value-of select="$dquote"/> <xsl:value-of select="$delimiter"/> <!-- #4 startdate--> <xsl:value-of select="$dquote"/> <xsl:value-of select="wd:startdate"/> <xsl:value-of select="$dquote"/> <xsl:value-of select="$linefeed"/> </xsl:if> <!-- remove consecutive duplicates--> <xsl:variable name="duplicate_key"? match="wd:report_data/wd:report_entry/wd:location_changes" select="concat(wd:employeeid,'|',wd:regioncode)" /> <!-- data row end --> </xsl:template> </xsl:stylesheet>
the issue here not able remove consecutive duplicate
if there consecutive entry same combination "employeeid|regioncode", entry should not included.
unless i'm missing should able simplify process grouping adjacent wd:report_entry
(based on wd:employeeid
, wd:regioncode
) , processing last entry in group.
note: adjacent means "next to", unlike describe in comment "only consecutive duplicates need removed , adjacent duplicates need kept.".
xml input
<wd:report_data xmlns:wd="urn:com.workday.report/test"> <wd:report_entry> <wd:location_changes> <wd:employeeid>111111</wd:employeeid> <wd:countrycode>us</wd:countrycode> <wd:regioncode>rx</wd:regioncode> <wd:startdate>2013-07-01</wd:startdate> </wd:location_changes> <wd:location_changes> <wd:employeeid>111111</wd:employeeid> <wd:countrycode>us</wd:countrycode> <wd:regioncode>md</wd:regioncode> <wd:startdate>2009-09-14</wd:startdate> <!--remove--> </wd:location_changes> <wd:location_changes> <wd:employeeid>111111</wd:employeeid> <wd:countrycode>us</wd:countrycode> <wd:regioncode>md</wd:regioncode> <wd:startdate>2009-10-14</wd:startdate> <!--keep--> </wd:location_changes> <wd:location_changes> <wd:employeeid>111111</wd:employeeid> <wd:countrycode>us</wd:countrycode> <wd:regioncode>rx</wd:regioncode> <wd:startdate>2014-07-01</wd:startdate> </wd:location_changes> </wd:report_entry> </wd:report_data>
xslt 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xpath-default-namespace="urn:com.workday.report/test"> <xsl:output method="text"/> <xsl:strip-space elements="*"/> <xsl:template match="/*"> <xsl:text>employeeid|countrycode|regioncode|startdate
</xsl:text> <xsl:for-each-group select="report_entry/location_changes" group-adjacent="concat(employeeid,'|',regioncode)"> <xsl:sort select="position()" order="descending"/> <xsl:apply-templates select="current-group()[last()]"/> </xsl:for-each-group> </xsl:template> <xsl:template match="location_changes"> <xsl:value-of select="concat('"', string-join((employeeid,countrycode,regioncode,startdate),'"|"'), '"
')"/> </xsl:template> </xsl:stylesheet>
output
employeeid|countrycode|regioncode|startdate "111111"|"us"|"rx"|"2014-07-01" "111111"|"us"|"md"|"2009-10-14" "111111"|"us"|"rx"|"2013-07-01"
Comments
Post a Comment