I am trying to create a nested XML document from a flat XML document as shown below. After searching here for other resources available on the network, it seems that the muenchain method may be the solution, however I struggle with its application to my situation.
The XML I need to translate takes the form:
<i> <item id="1" name="one" sub_id="10" sub_name="s1" detail_id="t1" detail_name="aaaa"/> <item id="1" name="one" sub_id="10" sub_name="s1" detail_id="t2" detail_name="bbb"/> <item id="1" name="one" sub_id="20" sub_name="s2" detail_id="t1" detail_name="ccc"/> <item id="1" name="one" sub_id="20" sub_name="s2" detail_id="t2" detail_name="ddd"/> <item id="2" name="two" sub_id="10" sub_name="s1" detail_id="t1" detail_name="eee"/> <item id="2" name="two" sub_id="10" sub_name="s1" detail_id="t2" detail_name="fff"/> <item id="2" name="two" sub_id="20" sub_name="s2" detail_id="t1" detail_name="ggg"/> <item id="2" name="two" sub_id="20" sub_name="s2" detail_id="t2" detail_name="hhh"/> <item id="3" name="three" /> <item id="4" name="four" sub_id="10" sub_name="s1" detail_id="t1" detail_name="mmm"/> <item id="4" name="four" sub_id="10" sub_name="s1" detail_id="t2" detail_name="nnn"/> <item id="4" name="four" sub_id="20" sub_name="s2" detail_id="t1" detail_name="ooo"/> <item id="4" name="four" sub_id="20" sub_name="s2" detail_id="t2" detail_name="ppp"/> </i>
I would like to convert this to XML in the following form:
<i> <item id="1" name="one" sub_items="true"> <sub_item sub_id="10" sub_name="s1"> <detail detail_id="t1" detail_name="aaaa"/> <detail detail_id="t2" detail_name="bbb"/> </sub_item> <sub_item sub_id="20" sub_name="s2"> <detail detail_id="t1" detail_name="ccc"/> <detail detail_id="t2" detail_name="ddd"/> </sub_item> </item> <item id="2" name="two" sub_items="true"> <sub_item sub_id="10" sub_name="s1"> <detail detail_id="t1" detail_name="eee"/> <detail detail_id="t2" detail_name="fff"/> </sub_item> <sub_item sub_id="20" sub_name="s2"> <detail detail_id="t1" detail_name="ggg"/> <detail detail_id="t2" detail_name="hhh"/> </sub_item> </item> <item id="3" name="three" sub_items="false"/> <item id="4" name="four" sub_items="true"> <sub_item sub_id="10" sub_name="s1"> <detail detail_id="t1" detail_name="mmm"/> <detail detail_id="t2" detail_name="nnn"/> </sub_item> <sub_item sub_id="20" sub_name="s2"> <detail detail_id="t1" detail_name="ooo"/> <detail detail_id="t2" detail_name="ppp"/> </sub_item> </item> </i>
From my research, I have the following XLST to do the conversion. I use the key method for the id attribute of the element. This does not group the data, repeating everything correctly for a given element identifier at each level, which makes sense given the key. So my problem is how can I select the nodes needed to output each level of the socket, do I need to use a different key operator?
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="indexes" match="i/item" use="@id"/> <xsl:template match="i"> <i> <xsl:for-each select="item[count(. | key('indexes',@id)[1]) = 1]" > <xsl:sort select="@id"/> <item> <xsl:attribute name="id"> <xsl:value-of select="@id"/> </xsl:attribute> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:attribute name="hasRows"> <xsl:value-of select="@id"/> </xsl:attribute> <xsl:for-each select="key('indexes',@id)"> <subitem> <xsl:attribute name ="sub_id"> <xsl:value-of select="@sub_id"/> </xsl:attribute> <xsl:attribute name ="sub_name"> <xsl:value-of select="@sub_name"/> </xsl:attribute> <xsl:for-each select="key('indexes',@id)"> <segment> <xsl:attribute name ="detail_id"> <xsl:value-of select="@detail_id"/> </xsl:attribute> <xsl:attribute name ="detail_name"> <xsl:value-of select="@detail_name"/> </xsl:attribute> </segment> </xsl:for-each> </subitem> </xsl:for-each> </item> </xsl:for-each> </i> </xsl:template> </xsl:stylesheet>
Is it also possible to populate the * sub_items * attribute with true when subitems / parts for an element exist and false when they do not?
Finally, to improve XSLT understanding / skills, can anyone recommend some good learning resources?
source share