Мне нужно определить преобразование xslt, которое может выполнять так называемые
"многопроходное преобразование".
Нет необходимости использовать многопроходную обработку здесь .
Это короткое и простое преобразование:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ot1">
<gt1 a="ot1"><xsl:value-of select="@a2"/></gt1>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="ot2">
<gt2 a="ot2" b="{@a3}"/>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному документу XML :
<t1>
<t2 a1="v1">
<ot1 a2="v2" />
<ot2 a3="v3">
<t3 a5="v4">
<ot1 a2="v5" />
</t3>
</ot2>
</t2>
</t1>
дает желаемый, правильный результат :
<t1>
<t2 a1="v1">
<gt1 a="ot1">v2</gt1>
<gt2 a="ot2" b="v3"/>
<t3 a5="v4">
<gt1 a="ot1">v5</gt1>
</t3>
</t2>
</t1>
ОБНОВЛЕНИЕ : ОП обновил вопрос тем, что, по его мнению, требует многопроходной обработки - это все еще не так.
Вот краткое и простое решение нового вопроса, снова за один проход :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ot1">
<gt2 a="ot2" b="gtv{substring-after(name(), 'ot')}">
<gt1 a="ot1"><xsl:value-of select="@a2"/></gt1>
</gt2>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="ot2">
<gt2 a="ot2" b="{@a3}"/>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование применяется к вновь предоставленному исходному документу XML:
<t1>
<t2 a1="v1">
<ot1 a2="v2" />
<ot2 a3="v3">
<t3 a5="v4">
<ot1 a2="v5" />
</t3>
</ot2>
</t2>
</t1>
снова желаемый, правильный результат выдается :
<t1>
<t2 a1="v1">
<gt2 a="ot2" b="gtv1">
<gt1 a="ot1">v2</gt1>
</gt2>
<gt2 a="ot2" b="v3"/>
<t3 a5="v4">
<gt2 a="ot2" b="gtv1">
<gt1 a="ot1">v5</gt1>
</gt2>
</t3>
</t2>
</t1>
UPDATE2 : Поскольку ОП просит рефакторинга своего текущего кода, и, в частности, ему нужно лучше выразить этот отрывок:
<xsl:for-each select="child::*">
<xsl:element name="{name()}">
<xsl:copy-of select="@*|node()" />
</xsl:element>
</xsl:for-each>
вот один очевидный рефакторинг - просто замените вышеприведенное на :
<xsl:apply-templates/>
После этой модификации полный код становится :
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common" version="1.0"
exclude-result-prefixes="exslt">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="ot1|ot2">
<xsl:variable name="thisResult">
<xsl:apply-templates select="." mode="impl" />
</xsl:variable>
<xsl:apply-templates select=
"exslt:node-set($thisResult)" />
</xsl:template>
<xsl:template match="ot1" mode="impl">
<ot2 a3="gtv1">
<gt1 a="ot1">
<xsl:value-of select="@a2" />
</gt1>
</ot2>
</xsl:template>
<xsl:template match="ot2" mode="impl">
<gt2 a="ot2" b="{@a3}">
<xsl:apply-templates/>
</gt2>
</xsl:template>
</xsl:stylesheet>
и при применении к последнему предоставленному исходному XML-документу :
<t1>
<t2 a1="v1">
<ot1 a2="v2" />
<ot2 a3="v3">
<t3 a5="v4">
<ot1 a2="v5" />
</t3>
</ot2>
</t2>
</t1>
желаемый результат получен :
<t1>
<t2 a1="v1">
<gt2 a="ot2" b="gtv1">
<gt1 a="ot1">v2</gt1>
</gt2>
<gt2 a="ot2" b="v3">
<t3 a5="v4">
<gt2 a="ot2" b="gtv1">
<gt1 a="ot1">v5</gt1>
</gt2>
</t3>
</gt2>
</t2>
</t1>