Grouping XML nodes by attribute value in XSLT

Im brand new to xslt conversions, and I need help with one kind of conversion. I need to group all the nodes of a certain type with one of its attributes and list the parents of all the attributes. This is a kind of generalization of the use of certain things in a document. I will give a simplified example.
Input:

<root> <node name="node1"> <somechild child-id="1"> </node> <node name="node2"> <somechild child-id="2"> </node> <node name="node3"> <somechild child-id="1"> </node> <node name="node4"> <somechild child-id="2"> </node> <node name="node5"> <somechild child-id="3"> </node> </root> 

Desired conclusion:

 <root> <somechild child-id="1"> <is-child-of> <node name="node1" /> <node name="node3" /> </is-child-of> </somechild> <somechild child-id="2"> <is-child-of> <node name="node2" /> <node name="node4" /> </is-child-of> </somechild> <somechild child-id="3"> <is-child-of> <node name="node5" /> </is-child-of> </somechild> </root> 

The idea is that if it is the same element in many nodes, they have the same child identifier. I need to find everything that everyone uses. I found this question XSLT conversion to xml, grouping by key , which looks similar, but at the beginning there is a declaration of all authors, and I don’t have them, it is always just a child.

+7
source share
2 answers
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:key name="k" match="somechild" use="@child-id"/> <xsl:key name="n" match="node" use="somechild/@child-id"/> <xsl:template match="root"> <xsl:copy> <xsl:apply-templates select="//somechild[generate-id(.) = generate-id(key('k', @child-id))]"/> </xsl:copy> </xsl:template> <xsl:template match="somechild"> <xsl:copy> <xsl:apply-templates select="@*"/> <is-child-of> <xsl:apply-templates select="key('n', @child-id)"/> </is-child-of> </xsl:copy> </xsl:template> <xsl:template match="node"> <xsl:copy> <xsl:apply-templates select="@*"/> </xsl:copy> </xsl:template> <xsl:template match="@*"> <xsl:copy> <xsl:apply-templates select="@*"/> </xsl:copy> </xsl:template> </xsl:stylesheet> 

Output:

 <root> <somechild child-id="1"> <is-child-of> <node name="node1" /> <node name="node3" /> </is-child-of> </somechild> <somechild child-id="2"> <is-child-of> <node name="node2" /> <node name="node4" /> </is-child-of> </somechild> <somechild child-id="3"> <is-child-of> <node name="node5" /> </is-child-of> </somechild> </root> 
+5
source

Can you try the following approach?

 <!-- select the current child id to filter by --> <xsl:variable name="id" select="somechild/@child-id"/> <!-- select the nodes which have a somechild element with the child-id to look for --> <xsl:for-each select="/root//some-child[@child-id = $id]/.."> <!-- for each such node, do something --> </xsl:for-each> 
+1
source

All Articles