I would do this in 2 phases; First phase is to add the path to the Author
elements. Second phase to use the added path to produce the desired output.
This could be done in a single XSLT (2.0) by putting the new input with the path added in a variable, but this would cause memory issues with larger documents.
XML Input (input.xml)
<Library>
<Books>
<Book>
<ISBN>123</ISBN>
<Name>Book 1</Name>
<Author-Ref>/Library/Authors/Author[2]</Author-Ref>
</Book>
<Book>
<ISBN>425</ISBN>
<Name>Book 2</Name>
<Author-Ref>/Library/Authors/Author[1]</Author-Ref>
</Book>
</Books>
<Authors>
<Author>
<Name>John smith</Name>
<Nationality>American</Nationality>
<BirthDate>08051977</BirthDate>
</Author>
<Author>
<Name>Sandra Johns</Name>
<Nationality>American</Nationality>
<BirthDate>03091981</BirthDate>
</Author>
</Authors>
</Library>
First XSLT (pass1.xsl)
This will add the attribute path
to the Author
elements.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:if test="self::Author">
<xsl:attribute name="path">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/',local-name())"/>
<xsl:if test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]">
<xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML Output (temp.xml)
Notice @path
has been added.
<Library>
<Books>
<Book>
<ISBN>123</ISBN>
<Name>Book 1</Name>
<Author-Ref>/Library/Authors/Author[2]</Author-Ref>
</Book>
<Book>
<ISBN>425</ISBN>
<Name>Book 2</Name>
<Author-Ref>/Library/Authors/Author[1]</Author-Ref>
</Book>
</Books>
<Authors>
<Author path="/Library/Authors/Author[1]">
<Name>John smith</Name>
<Nationality>American</Nationality>
<BirthDate>08051977</BirthDate>
</Author>
<Author path="/Library/Authors/Author[2]">
<Name>Sandra Johns</Name>
<Nationality>American</Nationality>
<BirthDate>03091981</BirthDate>
</Author>
</Authors>
</Library>
Second XSLT (pass2.xsl)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*/Books/Book">
<xsl:value-of select="concat('Book Name: ',Name,'
')"/>
<xsl:value-of select="concat('Author Name: ',
/*/Authors/Author[@path=current()/Author-Ref]/Name,'
')"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
Final Output
Book Name: Book 1
Author Name: Sandra Johns
Book Name: Book 2
Author Name: John smith