xml - XSLT 1.0 build hierarchy from parent-child relationship -
i have following flat xml structure.
<customui > <elements> <tab id="1" parent="0"/> <tab id="-1" parent="0"/> <group id="-2" parent="-1"/> <group id="2" parent="1"/> <group id="11" parent="1"/> <menu id="-27" parent="-26"/> <menu id="-24" parent="-4"/> <menu id="-18" parent="-4"/> <menu id="-11" parent="-9"/> <menu id="-10" parent="-9"/> <menu id="-3" parent="-2"/> <menu id="3" parent="2"/> <menu id="10" parent="65"/> <menu id="12" parent="11"/> <menu id="16" parent="11"/> <menu id="18" parent="11"/> <menu id="25" parent="11" /> <menu id="29" parent="11"/> <menu id="46" parent="11"/> <menu id="74" parent="-3"/> <menu id="85" parent="11"/> <menu id="89" parent="2"/> <menu id="95" parent="2"/> <menu id="104" parent="2"/> <button id="-28" parent="-2"/> <button id="-25" parent="-24"/> <button id="-12" parent="-11"/> <button id="32" parent="29"/> <button id="26" parent="25"/> <button id="41" parent="18"/> <button id="66" parent="46"/> <button id="82" parent="74"/> <button id="86" parent="46"/> <button id="87" parent="89"/> <button id="90" parent="89"/> <button id="99" parent="89"/> <button id="58" parent="16"/> <button id="42" parent="18"/> <button id="47" parent="46"/> <button id="48" parent="46"/> <button id="33" parent="29"/> <!-- list continues --> </elements> </customui>
what build hierarchy using relationship between 'id' value , 'parent' value.
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:template match="@*|node()" name="identity"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="tab"> <xsl:variable name="controllerid" select="@id" as="xs:string"/> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <xsl:copy-of select="//*[@parent = $controllerid]"/> </xsl:copy> </xsl:template> <xsl:template match="group" name="group"> <xsl:variable name="controllerid" select="@id" as="xs:string"/> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <xsl:copy-of select="//*[@parent = $controllerid]"/> </xsl:copy> </xsl:template> <xsl:template match="menu" name="menu"> <xsl:variable name="controllerid" select="@id" as="xs:string"/> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <xsl:copy-of select="//*[@parent = $controllerid]"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
this have tried until not work.
any appreciated.
this bit crude, should work:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <!-- identity template --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="elements"> <xsl:copy> <xsl:for-each select="*"> <xsl:if test="not(../*[@id=current()/@parent])"> <xsl:apply-templates select="."/> </xsl:if> </xsl:for-each> </xsl:copy> </xsl:template> <xsl:template match="elements/*"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> <xsl:apply-templates select="../*[@parent = current()/@id]"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
the elements
template copies it, each element within it, applies templates if there no other sibling who's parent one; i.e. if data represents complete hierarchy, it'll root.
the second template applies in elements template, , copies as-is, includes other elements who's parent current one, recursively.
an alternative using keys might faster, have problems if there's more 1 elements
element:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:key name="elemsbyid" match="elements/*" use="@id"/> <xsl:key name="elemsbyparent" match="elements/*" use="@parent"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="elements"> <xsl:copy> <xsl:apply-templates select="*[not(key('elemsbyid',@parent))]"/> </xsl:copy> </xsl:template> <xsl:template match="elements/*"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> <xsl:apply-templates select="key('elemsbyparent',@id)"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
Comments
Post a Comment