'Using muenchian grouping to select distinct values in a subtree
I know how to do muenchian grouping but that normally is applied to a whole document (?).
Here I want to find distinct values in subtrees.
e.g.
<root>
<parent>
<child id="1"/>
<child id="1"/>
<child id="2"/>
</parent>
<parent>
<child id="2"/>
<child id="3"/>
<child id="3"/>
</parent>
</root>
I want to map to
<root>
<parent>
<child id="1"/>
<child id="2"/>
</parent>
<parent>
<child id="2"/>
<child id="3"/>
</parent>
</root>
If I try
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:key name="id_to_id" match="/root/parent/child" use="@id"/>
<xsl:template match="/root">
<root>
<xsl:for-each select="parent">
<parent>
<xsl:for-each select="child[generate-id() = generate-id(key('id_to_id',@id)[1])]">
<child id="{@id}"/>
</xsl:for-each>
</parent>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
then it does the key over the whole document and I get
<root>
<parent>
<child id="1" />
<child id="2" />
</parent>
<parent>
<child id="3" />
</parent>
</root>
Solution 1:[1]
heres another equally bizarre solution, still not sure this is very sensible, is there some sort of XPath parenthesis or something I can use?
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:key name="id_to_id" match="child" use="@id"/>
<xsl:template match="/root">
<root>
<xsl:for-each select="parent">
<parent>
<xsl:variable name="children">
<xsl:copy-of select="child"/>
</xsl:variable>
<xsl:for-each select="msxsl:node-set($children)/child[generate-id() = generate-id(key('id_to_id',@id)[1])]">
<child id="{@id}"/>
</xsl:for-each>
</parent>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
Solution 2:[2]
now without meunchian grouping (which isnt what I want, but its a nice declarative approach), not suitable for anything but small groups of siblings.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/root">
<root>
<xsl:for-each select="parent">
<parent>
<xsl:for-each select="child[not(@id = preceding-sibling::child/@id)]">
<child id="{@id}"/>
</xsl:for-each>
</parent>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MrD at KookerellaLtd |
| Solution 2 |
