Я думаю, что это можно сделать с помощью чистого решения XSLT.Я достиг этого, сначала определив ключ для каждого продукта ( StockSalesRec с Type of ''), для которого поиск является Reference Самая последняя предыдущая запись поставщика (a StockSalesRec с Типом из 'SH')
<xsl:key
name="Stock"
match="StockSalesRec[@Type=' ']"
use="(preceding-sibling::StockSalesRec[@Type='SH'])[last()]/Reference" />
Затем вы можете сопоставить на каждом узле поставщика, например,
<xsl:apply-templates select="StockSalesRec[@Type='SH']" />
И затем для каждого такого узла поставщика вы можете прочитать все записи Продукта, используя ранее определенный ключ
<xsl:apply-templates select="key('Stock', Reference)" />
Если все это указать, то вы получите ....
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key
name="Stock"
match="StockSalesRec[@Type=' ']"
use="(preceding-sibling::StockSalesRec[@Type='SH'])[last()]/Reference"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates select="StockSalesRec[@Type='SH']"/>
</xsl:copy>
</xsl:template>
<xsl:template match="StockSalesRec[@Type='SH']">
<supplier name="{Reference}">
<xsl:apply-templates select="key('Stock', Reference)"/>
</supplier>
</xsl:template>
<xsl:template match="StockSalesRec[@Type=' ']">
<product>
<xsl:apply-templates/>
</product>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Когда вы применяете это к вашему образцу XML, вывод будет следующим:
<root>
<supplier name="A Supplier">
<product>
<Reference>12345</Reference>
<StockNum>00001</StockNum>
<Description>Item description</Description>
</product>
<product>
<Reference>67890</Reference>
<StockNum>00002</StockNum>
<Description>Another description</Description>
</product>
</supplier>
</root>
Обратите внимание на использование преобразования идентификаторов при создании узла продукта, позволяя добавлять дополнительные дочерние элементы во входные данные.XML без необходимости менять XSLT.