vars.unlink();
vars.unlink(thisframe);
  public void transformSelectedNodes(TransformerImpl transformer)            throws TransformerException  {    final XPathContext xctxt = transformer.getXPathContext();    final int sourceNode = xctxt.getCurrentNode();    DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);    VariableStack vars = xctxt.getVarStack();    int nParams = getParamElemCount();    try    {      final Vector keys = (m_sortElems == null)                          ? null                          : transformer.processSortKeys(this, sourceNode);      // Sort if we need to.      if (null != keys)        sourceNodes = sortNodes(xctxt, keys, sourceNodes);      if (TransformerImpl.S_DEBUG)        transformer.getTraceManager().fireSelectedEvent(sourceNode, this,                "select", new XPath(m_selectExpression),                new org.apache.xpath.objects.XNodeSet(sourceNodes));      final ResultTreeHandler rth = transformer.getResultTreeHandler();      ContentHandler chandler = rth.getContentHandler();      final StylesheetRoot sroot = transformer.getStylesheet();      final TemplateList tl = sroot.getTemplateListComposed();      final boolean quiet = transformer.getQuietConflictWarnings();            xctxt.pushCurrentNode(DTM.NULL);      int[] currentNodes = xctxt.getCurrentNodeStack();      int currentNodePos = xctxt.getCurrentNodeFirstFree() - 1;            xctxt.pushCurrentExpressionNode(DTM.NULL);      int[] currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();      int currentExpressionNodePos = xctxt.getCurrentExpressionNodesFirstFree() - 1;      xctxt.pushSAXLocatorNull();      xctxt.pushContextNodeList(sourceNodes);      transformer.pushElemTemplateElement(null);      // pushParams(transformer, xctxt);      // Should be able to get this from the iterator but there must be a bug.      DTM dtm = xctxt.getDTM(sourceNode);      int docID = sourceNode & DTMManager.IDENT_DTM_DEFAULT;            int argsFrame = -1;      if(nParams > 0)      {        // This code will create a section on the stack that is all the         // evaluated arguments.  These will be copied into the real params         // section of each called template.        int thisframe = vars.getStackFrame();        argsFrame = vars.link(nParams);        vars.setStackFrame(thisframe);                for (int i = 0; i < nParams; i++)         {          ElemWithParam ewp = m_paramElems[i];          XObject obj = ewp.getValue(transformer, sourceNode);                    vars.setLocalVariable(i, obj, argsFrame);        }        vars.setStackFrame(argsFrame);      }                  int child;      while (DTM.NULL != (child = sourceNodes.nextNode()))      {        currentNodes[currentNodePos] = child;        currentExpressionNodes[currentExpressionNodePos] = child;        if((child & DTMManager.IDENT_DTM_DEFAULT) != docID)        {          dtm = xctxt.getDTM(child);          docID = sourceNode & DTMManager.IDENT_DTM_DEFAULT;        }                final int exNodeType = dtm.getExpandedTypeID(child);        final int nodeType = (exNodeType >> ExpandedNameTable.ROTAMOUNT_TYPE);        final QName mode = transformer.getMode();        ElemTemplate template = tl.getTemplateFast(xctxt, child, exNodeType, mode,                                       -1, quiet, dtm);        // If that didn't locate a node, fall back to a default template rule.        // See http://www.w3.org/TR/xslt#built-in-rule.        if (null == template)        {          switch (nodeType)          {          case DTM.DOCUMENT_FRAGMENT_NODE :          case DTM.ELEMENT_NODE :            template = sroot.getDefaultRule();            // %OPT% direct faster?            break;          case DTM.ATTRIBUTE_NODE :          case DTM.CDATA_SECTION_NODE :          case DTM.TEXT_NODE :            // if(rth.m_elemIsPending || rth.m_docPending)            //  rth.flushPending(true);            transformer.pushPairCurrentMatched(sroot.getDefaultTextRule(), child);            transformer.setCurrentElement(sroot.getDefaultTextRule());            // dtm.dispatchCharactersEvents(child, chandler, false);            dtm.dispatchCharactersEvents(child, rth, false);            transformer.popCurrentMatched();            continue;          case DTM.DOCUMENT_NODE :            template = sroot.getDefaultRootRule();            break;          default :            // No default rules for processing instructions and the like.            continue;          }        }                transformer.pushPairCurrentMatched(template, child);        if(template.m_frameSize > 0)        {          vars.link(template.m_frameSize);          // You can't do the check for nParams here, otherwise the           // xsl:params might not be nulled.          if(/* nParams > 0 && */ template.m_inArgsSize > 0)          {            int paramIndex = 0;            for (ElemTemplateElement elem = template.getFirstChildElem();                  null != elem; elem = elem.getNextSiblingElem())             {              if(Constants.ELEMNAME_PARAMVARIABLE == elem.getXSLToken())              {                ElemParam ep = (ElemParam)elem;                                int i;                for (i = 0; i < nParams; i++)                 {                  ElemWithParam ewp = m_paramElems[i];                  if(ewp.m_qnameID == ep.m_qnameID)                  {                    XObject obj = vars.getLocalVariable(i, argsFrame);                    vars.setLocalVariable(paramIndex, obj);                    break;                  }                }                if(i == nParams)                  vars.setLocalVariable(paramIndex, null);              }              else                break;              paramIndex++;            }                      }        }        // if (check)        //  guard.push(this, child);        // Fire a trace event for the template.        if (TransformerImpl.S_DEBUG)          transformer.getTraceManager().fireTraceEvent(template);        // And execute the child templates.        // Loop through the children of the template, calling execute on         // each of them.        for (ElemTemplateElement t = template.m_firstChild;              t != null; t = t.m_nextSibling)        {          xctxt.setSAXLocator(t);          transformer.setCurrentElement(t);          t.execute(transformer);        }                if(template.m_frameSize > 0)          vars.unlink();                  transformer.popCurrentMatched();              } // end while (DTM.NULL != (child = sourceNodes.nextNode()))    }    catch (SAXException se)    {      transformer.getErrorListener().fatalError(new TransformerException(se));    }    finally    {      if (TransformerImpl.S_DEBUG)        transformer.getTraceManager().fireSelectedEndEvent(sourceNode, this,                "select", new XPath(m_selectExpression),                new org.apache.xpath.objects.XNodeSet(sourceNodes));      if(nParams > 0)        vars.unlink();      xctxt.popSAXLocator();      xctxt.popContextNodeList();      transformer.popElemTemplateElement();      xctxt.popCurrentExpressionNode();      xctxt.popCurrentNode();      sourceNodes.detach();    }  }