I am assuming you are using XSLT 1.0, because ... [an educated guess based on your result].
First, the reason why your method cannot work is that the concat()
function works on string-values, not node-sets.
concat(teacher, ':', keyword)
is evaluated as:
concat(string(teacher), ':', string(keyword))
and (in XSLT 1.0) string(node-set)
returns the string-value of the first node in the set.
There are other methods you can use to achieve your goal, for example:
1. Use a key with a predicate:
<xsl:key name="course-by-teacher" match="course" use="teachers/teacher" />
<xsl:template match="/">
<output>
<xsl:apply-templates select="key('course-by-teacher', Nikitin')[keywords/keyword='XML']" />
</output>
</xsl:template>
<xsl:template match="course">
<course>
<xsl:value-of select="title" />
</course>
</xsl:template>
2. Use the intersection of two keys:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets"
extension-element-prefixes="set">
<xsl:output method='xml' version='1.0' encoding='utf-8' indent='yes'/>
<xsl:key name="course-by-teacher" match="course" use="teachers/teacher" />
<xsl:key name="course-by-keyword" match="course" use="keywords/keyword" />
<xsl:template match="/">
<output>
<xsl:apply-templates select="set:intersection(key('course-by-teacher', 'Nikitin'), key('course-by-keyword', 'XML'))" />
</output>
</xsl:template>
<xsl:template match="course">
<course>
<xsl:value-of select="title" />
</course>
</xsl:template>
</xsl:stylesheet>
Note that this method requires the EXSLT set:intersection()
function which is supported by many XSLT 1.0 processors - but not all of them. If necessary, I will post a (more complex) method that can produce the intersection of two node-sets natively in XSLT 1.0.