I am trying to learn XSLT 2.0. In the example below, I am trying to list languages and books available in each language. Can you please help me understand how the context works?
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="Library.xsl"?>
<Library>
<Books>
<Book>
<Language code="English">English</Language>
<code>1</code>
<Title>History</Title>
</Book>
<Book>
<Language code="Spanish">Spanish</Language>
<code>2</code>
<Title>Math</Title>
</Book>
</Books>
<Languages>
<Language code="English">English</Language>
<Language code="Spanish">Spanish</Language>
</Languages>
</Library>
// Stylesheet
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table>
<xsl:for-each select="/Library/Languages/Language">
<tr>
<td style="border:1px solid red;">
<xsl:value-of select="@code" /><br /><br />
<xsl:variable name="key" select="@code" />
</td>
</tr>
<xsl:for-each select="/Library/Books/Book">
<xsl:if test="Language[@code=string($key)]">
<tr>
<td style="border:1px solid red;">
<xsl:value-of select="@code" />
</td>
</tr>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
// Desired output:
Language: English
Title: English Book
Language: Spanish
Title: Spanish Book
To get your desired output, you can change your XSLT-1.0 file to the following (XSLT-2.0 does not seem to be necessary). One crucial aspect was moving the <xsl:variable name="key" select="@code" />
out of the td
element up two layers, so that it can be accessed in the xsl:for-each
.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table>
<xsl:for-each select="/Library/Languages/Language">
<xsl:variable name="key" select="@code" />
<tr>
<td style="border:1px solid red;">
<xsl:value-of select="concat('Language: ', @code)" /><br /><br />
</td>
</tr>
<xsl:for-each select="/Library/Books/Book[Language[@code=$key]]">
<tr>
<td style="border:1px solid red;">
<xsl:value-of select="concat('Title: ', $key,' Book')" />
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The output is:
<html>
<body>
<table>
<tr>
<td style="border:1px solid red;">Language: English</td>
</tr>
<tr>
<td style="border:1px solid red;">Title: English Book</td>
</tr>
<tr>
<td style="border:1px solid red;">Language: Spanish</td>
</tr>
<tr>
<td style="border:1px solid red;">Title: Spanish Book</td>
</tr>
</table>
</body>
</html>