A: 

A posting by M. David Peterson just taught me how to make this work:

It's not necessary to have an <xsl:variable> for this case. Instead, I can embed the data document directly into the XSL stylesheet (putting it into a namespace for sanity) and then select elements from that. Here's the result:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:map="uri:map">

<xsl:output method="text" encoding="iso-8859-1"/>

<map:colors>
<entry><key>red</key><value>rot</value></entry>
<entry><key>green</key><value>gruen</value></entry>
<entry><key>blue</key><value>blau</value></entry>
</map:colors>

<xsl:template match="/">
<xsl:for-each select="document('')/*/map:colors/entry">
    <xsl:value-of select="key"/>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

This generates the expected output redgreenblue.

The trick is to use document('') to get a handle to the XSLT document itself, then * to get into the toplevel xsl:stylesheet element and from there I can access the color map.

Frerich Raabe
+2  A: 

You're almost right, using document('') will allow you to process node sets inside the current stylesheet:

<xsl:for-each select="document('')/xsl:stylesheet/xsl:variable[@name='stringmap']/map/entry">
    <xsl:value-of select="key"/>
</xsl:for-each>

It's not necessary to define the map node set as a variable in this case:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:data="some.uri" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

  <data:map>
    <entry><key>red</key><value>rot</value></entry>
    <entry><key>green</key><value>gruen</value></entry>
    <entry><key>blue</key><value>blau</value></entry>
  </data:map>

  <xsl:template match="/">
    <xsl:for-each select="document('')/xsl:stylesheet/data:map/entry">
      <xsl:value-of select="key"/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

If you do not use xsl:variable as a wrapper, you must remember that a top level elements must have a non null namespace URI.

In XSLT 2.0 it would've been possible to just iterate over the content in a variable:

<xsl:variable name="map">
  <entry><key>red</key><value>rot</value></entry>
  <entry><key>green</key><value>gruen</value></entry>
  <entry><key>blue</key><value>blau</value></entry>
</xsl:variable>

<xsl:template match="/">
  <xsl:for-each select="$map/entry">
    <xsl:value-of select="key"/>
  </xsl:for-each>
</xsl:template>
Per T
+1 Thanks for pointing out that top level elements must have a non null namespace URI. I found the same XSLT 1.0 solution you give in a different place (mentioned it in my answer) but wondered why a namespace was needed. Also thanks for pointing out how to do this in XSLT 2.0.
Frerich Raabe
@Per T: +1. And from http://www.w3.org/TR/xslt#document : *document("") refers to the root node of the stylesheet; the tree representation of the stylesheet is exactly the same as if the XML document containing the stylesheet was the initial source document.*
Alejandro