Reputation: 2656
I got a nasty XML where nodes are not grouped what I want and I am trying to find a way to group them by provided <master_key>
in the node:
raw xml:
<root>
<zasoba>
<kod>388300-56</kod>
<description>50cm</description>
<master_key>388300MK</master_key>
<kategorie/>
</zasoba>
<zasoba>
<kod>388300-53</kod>
<description>53cm</description>
<master_key>388300MK</master_key>
<kategorie/>
</zasoba>
<zasoba>
<kod>388300MK</kod>
<description>Master</description>
<kategorie/>
</zasoba>
<zasoba>
<kod>388399-56</kod>
<description>56cm</description>
<master_key>388399MK</master_key>
<kategorie/>
</zasoba>
<zasoba>
<kod>388399-57</kod>
<description>57cm</description>
<master_key>388399MK</master_key>
<kategorie/>
</zasoba>
<zasoba>
<kod>388399MK</kod>
<description>Master 2</description>
<kategorie/>
</zasoba>
</root>
There, product variants are separated in individual elements, but I would like to move under the the master element (defined by master_key
) under a new element name <variant>
.
Output should be look like this:
<root>
<zasoba>
<kod>388300MK</kod>
<description>Master 2</description>
<kategorie/>
<variant>
<kod>388300-56</kod>
<description>50cm</description>
<master_key>388300MK</master_key>
<kategorie/>
</variant>
<variant>
<kod>388300-53</kod>
<description>53cm</description>
<master_key>388300MK</master_key>
<kategorie/>
</variant>
</zasoba>
<zasoba>
<kod>388399MK</kod>
<description>Master</description>
<kategorie/>
<variant>
<kod>388399-56</kod>
<description>56cm</description>
<master_key>388399MK</master_key>
<kategorie/>
</variant>
<variant>
<kod>388399-57</kod>
<description>57cm</description>
<master_key>388399MK</master_key>
<kategorie/>
</variant>
</zasoba>
</root>
Upvotes: 0
Views: 28
Reputation: 167716
Fortunately XPath is flexible enough to select the grouping population in the order you want and the grouping key with the value existing:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="root">
<xsl:copy>
<xsl:for-each-group select="zasoba[not(master_key)], zasoba[master_key]" group-by="(master_key, kod)[1]">
<xsl:copy>
<xsl:apply-templates/>
<xsl:apply-templates select="tail(current-group())"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="zasoba">
<variant>
<xsl:apply-templates/>
</variant>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/ejivdHb
Upvotes: 1