*/
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();
int thisframe = vars.getStackFrame();
StackGuard guard = transformer.getStackGuard();
boolean check = (guard.getRecursionLimit() > -1) ? true : false;
boolean pushContextNodeListFlag = false;
try
{
xctxt.pushCurrentNode(DTM.NULL);
xctxt.pushCurrentExpressionNode(DTM.NULL);
xctxt.pushSAXLocatorNull();
transformer.pushElemTemplateElement(null);
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 (transformer.getDebug())
{
transformer.getTraceManager().fireSelectedEvent(sourceNode, this,
"select", new XPath(m_selectExpression),
new org.apache.xpath.objects.XNodeSet(sourceNodes));
}
final SerializationHandler rth = transformer.getSerializationHandler();
// ContentHandler chandler = rth.getContentHandler();
final StylesheetRoot sroot = transformer.getStylesheet();
final TemplateList tl = sroot.getTemplateListComposed();
final boolean quiet = transformer.getQuietConflictWarnings();
// Should be able to get this from the iterator but there must be a bug.
DTM dtm = xctxt.getDTM(sourceNode);
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.
argsFrame = vars.link(nParams);
vars.setStackFrame(thisframe);
for (int i = 0; i < nParams; i++)
{
ElemWithParam ewp = m_paramElems[i];
if (transformer.getDebug())
transformer.getTraceManager().fireTraceEvent(ewp);
XObject obj = ewp.getValue(transformer, sourceNode);
if (transformer.getDebug())
transformer.getTraceManager().fireTraceEndEvent(ewp);
vars.setLocalVariable(i, obj, argsFrame);
}
vars.setStackFrame(argsFrame);
}
xctxt.pushContextNodeList(sourceNodes);
pushContextNodeListFlag = true;
IntStack currentNodes = xctxt.getCurrentNodeStack();
IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();
// pushParams(transformer, xctxt);
int child;
while (DTM.NULL != (child = sourceNodes.nextNode()))
{
currentNodes.setTop(child);
currentExpressionNodes.setTop(child);
if(xctxt.getDTM(child) != dtm)
{
dtm = xctxt.getDTM(child);
}
final int exNodeType = dtm.getExpandedTypeID(child);
final int nodeType = dtm.getNodeType(child);
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;
}
}
else
{
transformer.setCurrentElement(template);
}
transformer.pushPairCurrentMatched(template, child);
if (check)
guard.checkForInfinateLoop();
int currentFrameBottom; // See comment with unlink, below
if(template.m_frameSize > 0)
{
xctxt.pushRTFContext();
currentFrameBottom = vars.getStackFrame(); // See comment with unlink, below
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++;
}
}
}
else
currentFrameBottom = 0;
// Fire a trace event for the template.
if (transformer.getDebug())
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);
try
{
transformer.pushElemTemplateElement(t);
t.execute(transformer);
}
finally
{
transformer.popElemTemplateElement();
}
}
if (transformer.getDebug())
transformer.getTraceManager().fireTraceEndEvent(template);
if(template.m_frameSize > 0)
{
// See Frank Weiss bug around 03/19/2002 (no Bugzilla report yet).
// While unlink will restore to the proper place, the real position
// may have been changed for xsl:with-param, so that variables
// can be accessed.
// of right now.
// More:
// When we entered this function, the current
// frame buffer (cfb) index in the variable stack may
// have been manually set. If we just call
// unlink(), however, it will restore the cfb to the
// previous link index from the link stack, rather than
// the manually set cfb. So,
// the only safe solution is to restore it back
// to the same position it was on entry, since we're
// really not working in a stack context here. (Bug4218)
vars.unlink(currentFrameBottom);
xctxt.popRTFContext();
}
transformer.popCurrentMatched();
} // end while (DTM.NULL != (child = sourceNodes.nextNode()))
}
catch (SAXException se)
{
transformer.getErrorListener().fatalError(new TransformerException(se));
}
finally
{
if (transformer.getDebug())
transformer.getTraceManager().fireSelectedEndEvent(sourceNode, this,
"select", new XPath(m_selectExpression),
new org.apache.xpath.objects.XNodeSet(sourceNodes));
// Unlink to the original stack frame
if(nParams > 0)
vars.unlink(thisframe);
xctxt.popSAXLocator();
if (pushContextNodeListFlag) xctxt.popContextNodeList();
transformer.popElemTemplateElement();
xctxt.popCurrentExpressionNode();
xctxt.popCurrentNode();
sourceNodes.detach();
}
}