I am trying to write some XSLT that groups the XML data based on certain keyed fields. These fields include some static fields as well as the potential of additional fields.
Data Example:
<ReportResult>
<ReportHeader>
<Header>Device Serial #</Header>
<Header>Device Type</Header>
<Header>Site ID</Header>
<Header>Site Name</Header>
<Header>Operation</Header>
<Header>Option1</Header>
<Header>Option 4</Header>
</ReportHeader>
<ReportData>
<DataEntity>
<kbserno>31513766</kbserno>
<DeviceProductDesc>ExampleProductName</DeviceProductDesc>
<SiteID>ExampleSiteID</SiteID>
<SiteName>ExampleSiteName</SiteName>
<OperationCodeDesc>Open</OperationCodeDesc>
<KeyholderOption />
<KeyholderOption />
</DataEntity>
<DataEntity>
<kbserno>31513766</kbserno>
<DeviceProductDesc>ExampleProductName</DeviceProductDesc>
<SiteID>ExampleSiteID</SiteID>
<SiteName>ExampleSiteName</SiteName>
<OperationCodeDesc>Open</OperationCodeDesc>
<KeyholderOption />
<KeyholderOption />
</DataEntity>
</ReportData>
</ReportResult>
As it stands, I have code that groups based on the kbserno
, SiteID
, and OperationCodeDesc
:
<xsl:for-each select="//DataEntity[generate-id(.) = generate-id(key('keyActivitySummary', concat(kbserno,'+',SiteID,'+',OperationCodeDesc))[1])]">
<xsl:variable name="lngKbserno"><xsl:value-of select="kbserno" /></xsl:variable>
<xsl:variable name="lngSite"><xsl:value-of select="SiteID" /></xsl:variable>
<xsl:variable name="lngOperation"><xsl:value-of select="OperationCodeDesc" /></xsl:variable>
<!-- Select all the entries that belong to that group -->
<!--Create template to create select statement below dynamically based on groupingheaders-->
<xsl:variable name="GroupList" select="//DataEntity[kbserno=$lngKbserno and
OperationCodeDesc=$lngOperation and
SiteID=$lngSite]" />
<xsl:for-each select="$GroupList[1]/*">
<!-- Do stuff to the grouping -->
</xsl:for-each>
</xsl:for-each>
Basically, I need to add it such that when KeyholderOption tags are present in the date (as in the data given), the date is additionally grouped on the first KeyholderOption present in each data entity, the second KeyholderOption present, etc.
Additionally, the values in these KeyholderOption entities can be NULL (as shown). However, all entities will have the same number of these entries (ie if an entity has 2 KeyholderOptions, then all entities will have 2).
I have just tried adding KeyholderOption to the key in the code above, but that just results in none of the data being output properly.
This would be the first transform to add the element. Then you can use the Muenchian grouping method for the second transform and get rid of the key, if needed. Play with the key to get it how you want it.
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="DataEntity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<xsl:element name="key">
<xsl:value-of select="concat(kbserno, '^^')"/>
<xsl:value-of select="concat(SiteID, '^^')"/>
<xsl:value-of select="concat(OperationCodeDesc, '^^')"/>
<xsl:for-each select="KeyholderOption">
<xsl:value-of select="concat(., '^^')"/>
</xsl:for-each>
</xsl:element>
</xsl:copy>
</xsl:template>