Я не знаю, будет ли это считаться элегантным, но с этим вводом:
<root>
<categories>
<category id="1" parent="0">Configurations</category>
<category id="11" parent="13">LCD Monitor</category>
<category id="12" parent="13">CRT Monitor</category>
<category id="13" parent="1">Monitors</category>
<category id="123" parent="122">Printer</category>
</categories>
<products>
<product>
<category>12</category>
</product>
<product>
<category>11</category>
</product>
</products>
</root>
Это XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<root>
<xsl:apply-templates select="//product"/>
</root>
</xsl:template>
<xsl:template match="product">
<product>
<path>
<xsl:call-template name="catwalk">
<xsl:with-param name="id"><xsl:value-of select="category"/>
</xsl:with-param>
</xsl:call-template>
</path>
</product>
</xsl:template>
<xsl:template name="catwalk">
<xsl:param name="id"/>
<xsl:if test="$id != '0'">
<xsl:call-template name="catwalk">
<xsl:with-param name="id"><xsl:value-of select="//category[@id = $id]/@parent"/>
</xsl:with-param>
</xsl:call-template>
<xsl:value-of select="//category[@id = $id]"/><xsl:text>/</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Даст вам этот вывод:
<?xml version="1.0" encoding="utf-8"?>
<root>
<product>
<path>Configurations/Monitors/CRT Monitor/
</path>
</product>
<product>
<path>Configurations/Monitors/LCD Monitor/
</path>
</product>
</root>
У путей по-прежнему есть дополнительный завершающий слеш, вам понадобится еще немного условного XSLT, чтобы слеш получался только тогда, когда вы не на первом уровне.
Крайне важно, чтобы иерархия категорий была правильной, иначе ваше преобразование может легко попасть в бесконечный цикл, который остановится только тогда, когда ему не хватит памяти. Если бы я реализовывал что-то подобное в реальной системе, у меня возникло бы желание добавить параметр в шаблон catWalk, который увеличивается при каждом вызове, и добавлять его в тест, чтобы он прекратил цикл после 10 вызовов независимо от того, был ли найден родитель .