Вы можете добиться с помощью этого метода XSLT-1.0 Muenchian Grouping . Если вы ищете на SO, вы найдете много примеров. Применяя этот метод, ваша таблица стилей может выглядеть следующим образом (я добавил гипотетический элемент <root>
вокруг исходного XML, чтобы сделать его правильно сформированным ):
xsl:key
и выражение select
внешнего xsl:for-each
реализуют мюнхенскую группировку . Внутренняя часть цикла должна быть своего рода , требующей объяснения.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="id" match="item" use="properties/property[@attribute-id='parent']" />
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each select="item[generate-id() = generate-id(key('id',properties/property[@attribute-id='parent'])[1])]">
<item id="{parent}">
<childs>
<xsl:for-each select="key('id',properties/property[@attribute-id='parent'])">
<child id="{@id}" />
</xsl:for-each>
</childs>
</item>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Если вы можете использовать XSLT-2.0 или выше, вы можете использовать xsl:for-each-group
следующим образом:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each-group select="item" group-by="properties/property[@attribute-id='parent']">
<item id="{parent}">
<childs>
<xsl:for-each select="current-group()">
<child id="{@id}" />
</xsl:for-each>
</childs>
</item>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Это немного проще, но делает то же самое.
Его выход в обоих случаях:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item id="">
<childs>
<child id="100"/>
<child id="101"/>
<child id="103"/>
</childs>
</item>
<item id="">
<childs>
<child id="102"/>
<child id="104"/>
</childs>
</item>
</root>
Это не совсем то, что вы хотите, но я думаю, что последние child
идентификаторы вашего примера неверны.