Given this XML
<Xml> <Thing id="1" > <Foo id="11" parentId="12"/> <Foo id="12"/> </Thing> <Thing id="2" parentId="1" /> <Thing id="3" parentId="2" /> <Thing id="4"> <Foo id="11" parentId="15"/> <Foo id="12" parentId="14"/> <Foo id="13" parentId="11"/> <Foo id="14" parentId="15"/> <Foo id="15"/> </Thing> </Xml>
I want to grab every collection of siblings, and assemble them into their own hierarchy.
Every "Thing" node with a parentId value, should nest under the corresponding Thing node. Every "Foo" node with a parentId value, should nest under the corresponding Foo node -- but only within its siblings. The example has two sets of Foo siblings.
I'm trying to create this:
<Xml> <Thing id="1" > <Foo id="12"> <Foo id="11" parentId="12"/> </Foo> <Thing id="2" parentId="1" > <Thing id="3" parentId="2" /> </Thing> </Thing> <Thing id="4" > <Foo id="14" parentId="12"> <Foo id="12" parentId="14"/> </Foo> <Foo id="15"> <Foo id="11" parentId="15"> <Foo id="13" parentId="11"/> </Foo> </Foo> </Thing> </Xml>
This example comes close: How can I use XSLT 1.0 to add structure to a non-heirarchal XML file?
I've used the identity template to retain all nodes and attributes. Then I want an overriding template to match on all nodes that have a sibling (following or preceding) such that the sibling's @parentId value equals my @id value. The closest I could come was hard coding an id/parentId value to match on.
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output indent="yes"/> <!-- override identity rule with template to match on a node who has siblings, where sibling/@parentId == ./@id --> <xsl:template match="node()[@id='1' and (preceding-sibling::*[@parentId = 1] or following-sibling::*[@parentId = 1])]"> <captured> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </captured> </xsl:template> <!-- identity rule --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
I can't see how to grab the current nodes @id value to use in the predicate of the Xpath matching siblings based on parentId value.
And then I want to nest the current nodes siblings underneath it, where the siblings @ParentId equals my @id.