问题
I have some frustratingly flat XML that looks like this:
<groups>
<group id="1" depth="1" />
<group id="2" depth="2" />
<group id="3" depth="2" />
<group id="4" depth="3" />
<group id="5" depth="2" />
<group id="6" depth="3" />
</groups>
The maximum value of depth
appears to be 5
.
Which I'd like to turn into XML that looks like this:
<groups>
<group id="1" depth="1">
<group id="2" depth="2">
</group>
<group id="3" depth="2">
<group id="4" depth="3">
</group>
</group>
<group id="5" depth="2">
<group id="6" depth="3">
</group>
</group>
</group>
</groups>
I think I need to use an xsl:key
and then for each parentDepth
match the following nodes that have depth = parentDepth + 1
until I reach a node with depth <= parentDepth
, but I'm unsure how to implement such a rule.
I suppose another logical approach might be to start from the "bottom" and find the most recent node that has depth = childDepth - 1
, but I'm unsure if that can even be achieved in XSLT.
I'm also unsure if this can be done recursively for each depth?
I'm using XSLT 1.0.
回答1:
I think I need to use an
xsl:key
and then for eachparentDepth
match the following nodes that havedepth = parentDepth + 1
No, you need to look at it in the opposite direction: let each child find its parent and learn its unique id, so it can be called by it.
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="child" match="group" use="generate-id(preceding-sibling::group[@depth=current()/@depth - 1][1])" />
<xsl:template match="/groups">
<xsl:copy>
<xsl:apply-templates select="group[@depth=1]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="group">
<group id="{@id}" depth="{@depth}">
<xsl:apply-templates select="key('child', generate-id())"/>
</group>
</xsl:template>
</xsl:stylesheet>
来源:https://stackoverflow.com/questions/40295763/converting-flat-hierarchy-to-nested-hierarchy-in-xslt-depth