Вот существующий код XML -источника и XSLT-преобразования, который восстанавливает всю цепочку взаимосвязей родитель-потомок. Алгоритм выполняет правильную работу, но необходимо учитывать новые дополнительные условия; плюс выходные "строковые" (или имена) значения должны принимать более формализованную, правильную форму.
======= базовый источник
<root>
<document ID-1="galaxyID" ID-2="NULL" ID-3="111" SHORTNAME="gal" NAME="Milky Way"/> <!-- this is parent's node -->
<document ID-1="starID" ID-2="galaxyID" ID-3="222" SHORTNAME="st" NAME="Sun"/> <!-- this is subparent -->
<document ID-1="planetID" ID-2="starID" ID-3="333" SHORTNAME="pl" NAME="Earth"/> <!-- this is subparent -->
<document ID-1="africaID" ID-2="planetID" ID-3="aaa" SHORTNAME="сont" NAME="Africa"/> <!-- child-1 -->
<document ID-1="australiaID" ID-2="planetID" ID-3="bbb" SHORTNAME="сont" NAME="Australia"/> <!-- child-2 -->
<document ID-1="eurasiaID" ID-2="planetID" ID-3="ccc" SHORTNAME="сont" NAME="Eurasia"/> <!-- child-3 -->
<document ID-1="antarcticaID" ID-2="planetID" ID-3="ddd" SHORTNAME="сont" NAME="Antarctica"/> <!-- child-4 -->
</root>
======= = базовый xslt
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:key name="ref" match="document" use="@ID-1"/>
<xsl:template match="document">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="key('ref', @ID-2)" mode="att"/>
</xsl:copy>
</xsl:template>
<xsl:template match="document" mode="att">
<xsl:param name="pos" select="count(@*) + 1"/>
<xsl:attribute name="attr-{$pos}">
<xsl:value-of select="@NAME"/>
</xsl:attribute>
<xsl:apply-templates select="key('ref', @ID-2)" mode="att">
<xsl:with-param name="pos" select="$pos + 1"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
======== базовый выход
<?xml version="1.0" encoding="utf-16"?>
<root>
<document ID-1="galaxyID" ID-2="NULL" ID-3="111" SHORTNAME="gal" NAME="Milky Way" />
<document ID-1="starID" ID-2="galaxyID" ID-3="222" SHORTNAME="st" NAME="Sun" attr-6="Milky Way" />
<document ID-1="planetID" ID-2="starID" ID-3="333" SHORTNAME="pl" NAME="Earth" attr-6="Sun" attr-7="Milky Way" />
<document ID-1="africaID" ID-2="planetID" ID-3="aaa" SHORTNAME="сont" NAME="Africa" attr-6="Earth" attr-7="Sun" attr-8="Milky Way" />
<document ID-1="australiaID" ID-2="planetID" ID-3="bbb" SHORTNAME="сont" NAME="Australia" attr-6="Earth" attr-7="Sun" attr-8="Milky Way" />
<document ID-1="eurasiaID" ID-2="planetID" ID-3="ccc" SHORTNAME="сont" NAME="Eurasia" attr-6="Earth" attr-7="Sun" attr-8="Milky Way" />
<document ID-1="antarcticaID" ID-2="planetID" ID-3="ddd" SHORTNAME="сont" NAME="Antarctica" attr-6="Earth" attr-7="Sun" attr-8="Milky Way" />
</root>
https://xsltfiddle.liberty-development.net/ncntCSJ/3
взаимосвязь схема
============================ НОВЫЕ ЦЕЛИ ========== ==================
1- Дополнительное условие внутри рекурсии
Наряду с каждым добавлением цикла проверка того, что каждый сравниваемый элемент имеет:
2 - коррекция вывода строки
2.1 Конкатенация имен
Рекурсия образует целостную цепочку сущностей, поэтому их строковое объяснение - «Имена» могут быть объединены. Существует 2 уровня конкатенации:
a) конкатенация в пределах одного уровня [SHORTNAME] + [.] + [NAME] (конкатенация в одном элементе).
<EXAMPLE SHORTNAME="pl" NAME="Earth"/> --->> <EXAMPLE FULLNAME="pl. Earth"/>
b) сцепление между уровнями
<EXAMPLE FULLNAME="gal. Milky Way, st. Sun, pl. Earth, сont. Eurasia"/> <!-- note additional commas and dots -->
2.2 Номенклатура ограниченных выходных атрибутов в зависимости от уровней иерархии
В существующем XSLT-коде Переходные атрибуты с «именами» формируются случайным образом динамически c (подсчитывает номер позиции атрибута внутри элемента). В реальной ситуации постфикс цифри c может вырасти до третьей дюжины. Поэтому для улучшения ситуации может быть полезно реализовать ограниченный диапазон динамически генерируемых входящих атрибутов, привязанных только к числу уровней иерархии. Например:
<EXAMPLE LEVEL-1="gal. Milky Way" LEVEL-2="st. Sun" LEVEL-3="pl.
Earth" LEVEL-4="сont. Eurasia"/>
2.3 RANK (атрибут)
RANK является последней контрольной точкой. Все восстановленные цепочки должны быть упорядочены по атрибуту RANK (он может совпадать с собственной рекурсией, но иногда нет. В любом случае атрибут RANK имеет более высокий приоритет. (Это правило также показано в предполагаемом выводе).
====== ИСТОЧНИК ЗАДАЧ
<root>
<document ID-1="galaxyID" ID-2="NULL" ID-3="111" SHORTNAME="gal" NAME="Milky Way" STATUS="0" RANK="1"/>
<document ID-1="starID" ID-2="galaxyID" ID-3="222" SHORTNAME="st" NAME="Sun" STATUS="0" RANK="3"/>
<document ID-1="planetID" ID-2="starID" ID-3="333" SHORTNAME="pl" NAME="Earth" STATUS="0" RANK="6"/>
<document ID-1="africaID" ID-2="planetID" ID-3="aaa" SHORTNAME="сont" NAME="Africa" STATUS="0" RANK="8"/>
<document ID-1="australiaID" ID-2="planetID" ID-3="bbb" SHORTNAME="сont" NAME="Australia" STATUS="0" RANK="8"/>
<document ID-1="eurasiaID" ID-2="planetID" ID-3="ccc" SHORTNAME="сont" NAME="Eurasia" STATUS="0" RANK="9"/>
<document ID-1="antarcticaID" ID-2="planetID" ID-3="ddd" SHORTNAME="сont" NAME="Antarctica" STATUS="0" RANK="5"/>
<!--note RANK! (higher than parent's "Earth" rank. So in the output they are switching )-->
<document ID-1="atlantisID" ID-2="planetID" ID-3="zzz" SHORTNAME="is" NAME="Atlantis" STATUS="2" NULL-ATTRIBUTE="some-value" RANK="8"/>
</root>
====== ПРЕДПОЛАГАЕМЫЙ ВЫХОД ЗАДАЧИ
<!-- ORDER NOTE:- not "continent-planet-star-galaxy" but "galaxy-star-planet-continent" -->
<root>
<document ID-1="galaxyID" ID-2="NULL" ID-3="111" SHORTNAME="gal" NAME="Milky Way" STATUS="0" RANK="1"
FULLNAME="gal. Milky Way"
LEVEL-1="gal. Milky Way"/>
<document ID-1="starID" ID-2="galaxyID" ID-3="222" SHORTNAME="st" NAME="Sun" STATUS="0" RANK="3"
FULLNAME="gal. Milky Way, st. Sun"
LEVEL-1="gal. Milky Way" LEVEL-2="st. Sun"/>
<document ID-1="planetID" ID-2="starID" ID-3="333" SHORTNAME="pl" NAME="Earth" STATUS="0" RANK="6"
FULLNAME="gal. Milky Way, st. Sun, pl. Earth"
LEVEL-1="gal. Milky Way" LEVEL-2="st. Sun" LEVEL-3="pl. Earth"/>
<document ID-1="africaID" ID-2="planetID" ID-3="aaa" SHORTNAME="сont" NAME="Africa" STATUS="0" RANK="8"
FULLNAME="gal. Milky Way, st. Sun, pl. Earth, cont. Africa"
LEVEL-1="gal. Milky Way" LEVEL-2="st. Sun" LEVEL-3="pl. Earth" LEVEL-4="cont. Africa"/>
<document ID-1="australiaID" ID-2="planetID" ID-3="bbb" SHORTNAME="сont" NAME="Australia" STATUS="0" RANK="8"
FULLNAME="gal. Milky Way, st. Sun, pl. Earth, cont. Australia"
LEVEL-1="gal. Milky Way" LEVEL-2="st. Sun" LEVEL-3="pl. Earth" LEVEL-4="cont. Australia"/>
<document ID-1="eurasiaID" ID-2="planetID" ID-3="ccc" SHORTNAME="сont" NAME="Eurasia" STATUS="0" RANK="9"
FULLNAME="gal. Milky Way, st. Sun, pl. Earth, cont. Eurasia"
LEVEL-1="gal. Milky Way" LEVEL-2="st. Sun" LEVEL-3="pl. Earth" LEVEL-4="cont. Eurasia"/>
<document ID-1="antarcticaID" ID-2="planetID" ID-3="ddd" SHORTNAME="сont" NAME="Antarctica" STATUS="0" RANK="5"
FULLNAME="gal. Milky Way, st. Sun, cont. Antarctica, pl. Earth"
LEVEL-1="gal. Milky Way" LEVEL-2="st. Sun" LEVEL-3="cont. Antarctica" LEVEL-4="pl. Earth"/>
<!--note! Earth and Antarctica switching because of RANK-->
<document ID-1="atlantisID" ID-2="planetID" ID-3="zzz" SHORTNAME="is" NAME="Atlantis" STATUS="2" NULL-ATTRIBUTE="some-value" RANK="8" />
<!-- nothing happens because of STATUS and NULL-ATTRIBUTE-->
</root>
вопрос какой код XSLT может быть применен для этого?