title: Accessing XSLT param and variable values from lxml extension elements
body: <p>I would like to access <code>xsl:param</code> and <code>xsl:variable</code> values from XSLT extension-elements in lxml, something like:</p>
  <pre class="lang-xml prettyprint-override"><code>&lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;
      xmlns:abc=&quot;bar&quot;
      extension-element-prefixes=&quot;abc&quot;&gt;
      
      &lt;xsl:output method=&quot;text&quot;/&gt;
  
      &lt;xsl:param name=&quot;param1&quot;&gt;default param value&lt;/xsl:param&gt;
  
      &lt;xsl:template match=&quot;/&quot;&gt;
          &lt;!-- var1 is unnecessary - it's purely for demonstration --&gt;
          &lt;xsl:variable name=&quot;var1&quot; select=&quot;$param1&quot;/&gt;
          &lt;abc:foo attr1=&quot;{$var1}&quot;/&gt;
          &lt;xsl:value-of select=&quot;concat( 'XSLT ouput: ', $var1 )&quot;/&gt;
      &lt;/xsl:template&gt;
  
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  <pre class="lang-py prettyprint-override"><code>    #!/usr/local/bin/python3
      # -*- coding: utf-8 -*-
      
      import sys
      
      from lxml import etree
      from copy import deepcopy
      
      class FooExtensionElement( etree.XSLTExtension ):
      
          def execute( self, context, self_node, input_node, output_parent ):
              attr1 = self_node.get( &quot;attr1&quot; )
              print( &quot;attr1: {}&quot;.format( attr1 ))
      
      
      parser = etree.XMLParser( load_dtd=True )
      extensions = { 
          ( 'bar', 'foo' ) : FooExtensionElement()
      }
      transformer = etree.XSLT( etree.parse( sys.stdin, parser ), extensions = extensions )
      xml_doc = etree.XML( '&lt;dummy/&gt;' )
      result = transformer( xml_doc, param1=etree.XSLT.strparam( &quot;passed param value&quot; ))
      print( result )
  
  </code></pre>
  <p>The output of this is:</p>
  <pre><code>attr1: $var1
  XSLT ouput: passed param value
  </code></pre>
  <p>What I would like to do is set some simple (string) values in <code>xsl:variable</code>s (or pass them in to <code>xsl:param</code> as above) and then be able to use their <code>$variable</code> values within my extension-elements.
  In the example above, <code>attr1</code> in the <code>FooExtensionElement</code> would be assigned value &quot;passed param value&quot;.</p>
  <p><code>xsl:variable</code> and <code>xsl:param</code> are operating in an entirely different namespace to <code>abc:foo</code>.  Because of this namespace mismatch, I don't expect the XSLT to pass the <em>value</em> of <code>$var1</code> to <code>abc:foo/@attr1</code>.</p>
  <p><strong>Possible solution 1</strong>:
  The transformer must maintain a map of <code>xsl:variable/@name|xsl:param/@name</code> to their assigned values (for its own substitutions etc.).  If I could access that map (from inside my <code>FooExtensionElement.execute()</code> function) then I could use the value of <code>abc:foo/@attr1</code> (&quot;$var1&quot;/&quot;var1&quot;) as a key to get the variable's value.  I have been unable to find any lxml documentation of such a map.</p>
  <p><strong>Possible solution 2</strong>:
  Use a context-aware (i.e. is aware of current <code>xsl:</code> variable and param values and is able to substitute accordingly) xpath evaluation.  To do this - presumably - we need to start with a node in the <code>xsl</code> namespace.  In the example above, this could be the previous-sibling to <code>abc:foo</code>:</p>
  <pre class="lang-py prettyprint-override"><code>def execute( self, context, self_node, input_node, output_parent ):
      node = self_node.getprevious()
      print( &quot;node tag: {}&quot;.format( node.tag ))
      var = deepcopy( node ).xpath( &quot;concat( '', $var1 )&quot; )
      print( &quot;var: {}&quot;.format( var ))
  </code></pre>
  <p>The output of this is:</p>
  <pre><code>node tag: {http://www.w3.org/1999/XSL/Transform}variable
  </code></pre>
  <p>followed by:</p>
  <pre><code>lxml.etree.XPathEvalError: Undefined variable
  </code></pre>
  <p>Fail: it's complaining that I haven't provided the value (the one that I'm attempting to find) for <code>$var1</code> in the xpath, i.e. it doesn't seem to be aware of current <code>$variables</code>.</p>
  <p>What I need is access to the current state of XSLT &quot;<code>$variables</code>&quot; in the <code>xsl</code> namespace: can anyone tell me if this is possible with lxml?</p>