Input xml file:
<a key="777">
<desc key="1" attr1="# {../@key}" attr2="{@key} #" attr3="555" title="{@attr2}">
<b attr3="444">
<slot key="2" attr3="333" attr4="{../../@attr3}" title="{../../@attr3}+{../@attr3}-{@attr3}" >
<val key="3">
<fix key="4" title11="{../../@key} {../@key}" title="{@key}+{@title11}" >
<c></c>
</fix>
</val>
<numb key="5" title12="z{@key}z in {@key}" title="{@title12}+{@key}" titlew="{@title}+{@title12}">
</numb>
</slot>
</b>
</desc>
</a>
The curly brackets indicate the XPath to the attribute, instead of which you must substitute the value of the attribute along this XPath, for example, instead of {@key} and {../@key}, the value of the key attribute of the current node is substituted. The file after XSLT1.0 transformation should look like this:
<a key="777">
<desc key="1" attr1="# 777" attr2="1 #" attr3="555" title="1 #">
<b attr3="444">
<slot key="2" attr3="333" attr4="555" title="555+444-333">
<val key="3">
<fix key="4" title11="2 3" title="4+2 3">
<c />
</fix>
</val>
<numb key="5" title12="z5z in 5" title="z5z in 5+5" titlew="z5z in 5+5+z5z in 5" />
</slot>
</b>
</desc>
</a>
Now this is the XSLT1.0 transformation file:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{name()}">
<xsl:call-template name="expand">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:attribute>
</xsl:template>
<xsl:template name="expand">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '{@')">
<xsl:value-of select="substring-before($text, '{')"/>
<xsl:variable name="name" select="substring-before(substring-after($text, '{@'), '}')" />
<xsl:call-template name="expand">
<xsl:with-param name="text" select="../@*[name()=$name]"/>
</xsl:call-template>
<xsl:call-template name="expand">
<xsl:with-param name="text" select="substring-after($text, '}')"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($text, '{../@') ">
<xsl:value-of select="substring-before($text, '{')"/>
<xsl:variable name="name" select="substring-before(substring-after($text, '{../@'), '}')" />
<xsl:call-template name="expand">
<xsl:with-param name="text" select="../../@*[name()=$name]"/>
</xsl:call-template>
<xsl:call-template name="expand">
<xsl:with-param name="text" select="substring-after($text, '}')"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($text, '{../../@') ">
<xsl:value-of select="substring-before($text, '{')"/>
<xsl:variable name="name" select="substring-before(substring-after($text, '{../../@'), '}')" />
<xsl:call-template name="expand">
<xsl:with-param name="text" select="../../../@*[name()=$name]"/>
</xsl:call-template>
<xsl:call-template name="expand">
<xsl:with-param name="text" select="substring-after($text, '}')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Xml file after transformation:
<a key="777">
<desc key="1" attr1="# 777" attr2="1 #" attr3="555" title="1 #">
<b attr3="444">
<slot key="2" attr3="333" attr4="555" title="333+333-333">
<val key="3">
<fix key="4" title11="3 3" title="4+3 3">
<c />
</fix>
</val>
<numb key="5" title12="z5z in 5" title="z5z in 5+5" titlew="z5z in 5+5+z5z in 5" />
</slot>
</b>
</desc>
</a>
The error is that if the same attribute names are specified in the attribute value of the input file node, for example, in the Slot tag of the title attribute in curly braces three times @attr3, then the same values are substituted for the curly braces:
<slot key="2" ... title="333+333-333">
And it should be like this:
<slot key="2" ... title="555+444-333">
Where is the mistake?