Редактировать: Извините, теперь я понял, что я неправильно понял ваш вопрос.Я верю, что следующее более или менее то, что вы ищете:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="code" match="SO" use="plantCode" />
<xsl:key name="airports" match="SO" use="concat(airportofloading,' ',airportofunloading)" />
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="BC">
<BC>
<xsl:for-each select="SO[generate-id(.)=generate-id(key('code',plantCode))]">
<xsl:variable name="thisCode" select="plantCode"/>
<xsl:for-each select="../SO[generate-id() = generate-id(key('airports', concat(airportofloading,' ',airportofunloading))[plantCode = $thisCode][1])]">
<xsl:element name="plant">
<xsl:attribute name="name">
<xsl:value-of select="plantCode"/>
</xsl:attribute>
<xsl:for-each select="key('airports', concat(airportofloading,' ',airportofunloading))[plantCode = $thisCode]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</BC>
</xsl:template>
Это должно создать один элемент для каждой тройки { код завода , аэропорт загрузки , аэропорт загрузки }.Упомянутый элемент содержит все элементы для этой тройки.Я считаю, что это то, что вы хотели, или очень близко к этому, поэтому вы должны иметь возможность вносить любые необходимые изменения.