Nasty hack.  The issue is that extensions are
building their xpaths on the fly, so they don't really
have a chance to fix up their index lookup for the
variable stack (this problem caught me a bit by
surprise).  The variable stack itself no longer has
any qname information... it's a straight index lookup
to the variable value.  In order to work around this
problem in the short term, I test whether
fixupVariables has been called, and, if it hasn't, I
take the current prefixResolver, *which must be
set to the extension element* (it wasn't in the
Redirect extension), test if it is a
ElemTemplateElement (bad because we're not
supposed to be coupled with the xalan package
in xpath), and look at the previous sibling and
ancestor previous siblings for a ElemVariable.
For each ElemVariable, I can then compare the
qname, and, if a match, get the index from that
element.  Right now it doesn't do anything special
for global variables, and so errors can occur in
this case if you have imports and includes and
the like.  The hack is good enough right now to
get fop codegen to work correctly.  I'll do some
more work on this next week, or someone else
can, and I'll try and figure out a way to do this
without the visibility to xalan.

diff --git a/src/org/apache/xpath/operations/Variable.java b/src/org/apache/xpath/operations/Variable.java
index e74e843..87a5067 100644
--- a/src/org/apache/xpath/operations/Variable.java
+++ b/src/org/apache/xpath/operations/Variable.java
@@ -72,6 +72,9 @@
  */
 public class Variable extends Expression
 {
+  /** Tell if fixupVariables was called.
+   *  @serial   */
+  private boolean m_fixUpWasCalled = false;
 
   /** The qualified name of the variable.
    *  @serial   */
@@ -98,6 +101,7 @@
    */
   public void fixupVariables(java.util.Vector vars, int globalsSize)
   {
+    m_fixUpWasCalled = true;
     int sz = vars.size();
     for (int i = vars.size()-1; i >= 0; i--) 
     {
@@ -152,25 +156,73 @@
 
     // Is the variable fetched always the same?
     // XObject result = xctxt.getVariable(m_qname);
-    
-    XObject result;
-    if(m_isGlobal)
-      result = xctxt.getVarStack().getGlobalVariable(xctxt, m_index);
-    else
-      result = xctxt.getVarStack().getLocalVariable(xctxt, m_index);
-
-    if (null == result)
-    {
-      // This should now never happen...
-      warn(xctxt, XPATHErrorResources.WG_ILLEGAL_VARIABLE_REFERENCE,
-           new Object[]{ m_qname.getLocalPart() });  //"VariableReference given for variable out "+
-//      (new RuntimeException()).printStackTrace();
-//      error(xctxt, XPATHErrorResources.ER_COULDNOT_GET_VAR_NAMED,
-//            new Object[]{ m_qname.getLocalPart() });  //"Could not get variable named "+varName);
-      
-      result = new XNodeSet(xctxt.getDTMManager());
+    if(m_fixUpWasCalled)
+    {    
+      XObject result;
+      if(m_isGlobal)
+        result = xctxt.getVarStack().getGlobalVariable(xctxt, m_index);
+      else
+        result = xctxt.getVarStack().getLocalVariable(xctxt, m_index);
+  
+      if (null == result)
+      {
+        // This should now never happen...
+        warn(xctxt, XPATHErrorResources.WG_ILLEGAL_VARIABLE_REFERENCE,
+             new Object[]{ m_qname.getLocalPart() });  //"VariableReference given for variable out "+
+  //      (new RuntimeException()).printStackTrace();
+  //      error(xctxt, XPATHErrorResources.ER_COULDNOT_GET_VAR_NAMED,
+  //            new Object[]{ m_qname.getLocalPart() });  //"Could not get variable named "+varName);
+        
+        result = new XNodeSet(xctxt.getDTMManager());
+      }
+  
+      return result;
     }
+    else
+    {
+      // Hack city... big time.  This is needed to evaluate xpaths from extensions, 
+      // pending some bright light going off in my head.  Some sort of callback?
+      synchronized(this)
+      {
+        org.apache.xml.utils.PrefixResolver prefixResolver = xctxt.getNamespaceContext();
 
-    return result;
+        // Get the current ElemTemplateElement, which must be pushed in as the 
+        // prefix resolver, and then walk backwards in document order, searching 
+        // for an xsl:param element or xsl:variable element that matches our 
+        // qname.  For this to work really correctly, the stylesheet element 
+        // should be immediatly resolve to the root stylesheet, and the operation 
+        // performed on it's list of global variables.  But that will have to wait 
+        // for another day, or someone else can do it, or I will come up with a 
+        // better solution to this whole damned hack.
+        if(prefixResolver instanceof org.apache.xalan.templates.ElemTemplateElement)
+        {
+          org.apache.xalan.templates.ElemTemplateElement prev = 
+            (org.apache.xalan.templates.ElemTemplateElement)prefixResolver;
+            
+          while(null != prev)
+          {
+            org.apache.xalan.templates.ElemTemplateElement savedprev = prev;
+            while(null != (prev = prev.getPreviousSiblingElem()))
+            {
+              if(prev instanceof org.apache.xalan.templates.ElemVariable)
+              {
+                org.apache.xalan.templates.ElemVariable vvar = 
+                  (org.apache.xalan.templates.ElemVariable)prev;
+                
+                if(vvar.getName().equals(m_qname))
+                {
+                  m_index = vvar.getIndex();
+                  m_isGlobal = vvar.getIsTopLevel();
+                  m_fixUpWasCalled = true;
+                  return execute(xctxt);
+                }
+              }
+            }
+            prev = savedprev.getParentElem();
+          }
+        }
+      }
+      throw new javax.xml.transform.TransformerException("Variable not resolavable: "+m_qname);
+    }
   }
 }