I have the following XML. It contains books and references. Some references trace back to Book 1, e.g. Book 4 refers to Book 3 which refers to Book 1.
<?xml version="1.0" encoding="UTF-8"?>
<sandbox>
<book xml:id="h1">
<name>Book 1</name>
</book>
<book xml:id="h2">
<name>Book 2</name>
</book>
<book xml:id="h3">
<name>Book 3</name>
<ref target="#h1"/>
</book>
<book xml:id="h4">
<name>Book 4</name>
<ref target="#h3"/>
</book>
</sandbox>
I wrote the following XSLT that enriches the code by tracing back the references to the original source and adding an according textual statement:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:sandbox="sandbox.org"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:function name="sandbox:trace">
<xsl:param name="target"/>
<xsl:choose>
<xsl:when test="document($target)/ref">
<xsl:value-of select="sandbox:trace(document($target)/ref/@target)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="document($target)/name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:template match="ref">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:text>This book refers to </xsl:text>
<xsl:value-of select="sandbox:trace(@target)"/>
<xsl:text>!</xsl:text>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
It produces the desired output:
<?xml version="1.0" encoding="UTF-8"?>
<sandbox>
<book xml:id="h1">
<name>Book 1</name>
</book>
<book xml:id="h2">
<name>Book 2</name>
</book>
<book xml:id="h3">
<name>Book 3</name>
<ref target="#h1">This book refers to Book 1!</ref>
</book>
<book xml:id="h4">
<name>Book 4</name>
<ref target="#h3">This book refers to Book 1!</ref>
</book>
</sandbox>
My question: Is this a "good" way or are the more appropriate solutions for this task?