*/
public void transformSelectedNodes(TransformerImpl transformer)
throws TransformerException
{
final XPathContext xctxt = transformer.getXPathContext();
final int sourceNode = xctxt.getCurrentNode();
DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt,
sourceNode);
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 (transformer.getDebug())
{
// The original code, which is broken for bug#16889,
// which fails to get the original select expression in the select event.
/* transformer.getTraceManager().fireSelectedEvent(
* sourceNode,
* this,
* "select",
* new XPath(m_selectExpression),
* new org.apache.xpath.objects.XNodeSet(sourceNodes));
*/
// The following code fixes bug#16889
// Solution: Store away XPath in setSelect(Xath), and use it here.
// Pass m_xath, which the current node is associated with, onto the TraceManager.
Expression expr = m_xpath.getExpression();
org.apache.xpath.objects.XObject xObject = expr.execute(xctxt);
int current = xctxt.getCurrentNode();
transformer.getTraceManager().fireSelectedEvent(
current,
this,
"select",
m_xpath,
xObject);
}
xctxt.pushCurrentNode(DTM.NULL);
IntStack currentNodes = xctxt.getCurrentNodeStack();
xctxt.pushCurrentExpressionNode(DTM.NULL);
IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();
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 child;
while (DTM.NULL != (child = sourceNodes.nextNode()))
{
currentNodes.setTop(child);
currentExpressionNodes.setTop(child);
if ((child & DTMManager.IDENT_DTM_DEFAULT) != docID)
{
dtm = xctxt.getDTM(child);
docID = child & DTMManager.IDENT_DTM_DEFAULT;
}
//final int exNodeType = dtm.getExpandedTypeID(child);
final int nodeType = dtm.getNodeType(child);
// Fire a trace event for the template.
if (transformer.getDebug())
{
transformer.getTraceManager().fireTraceEvent(this);
}
// And execute the child templates.
// Loop through the children of the template, calling execute on
// each of them.
for (ElemTemplateElement t = this.m_firstChild; t != null;
t = t.m_nextSibling)
{
xctxt.setSAXLocator(t);
transformer.setCurrentElement(t);
t.execute(transformer);
}
if (transformer.getDebug())
{
// We need to make sure an old current element is not
// on the stack. See TransformerImpl#getElementCallstack.
transformer.setCurrentElement(null);
transformer.getTraceManager().fireTraceEndEvent(this);
}
// KLUGE: Implement <?xalan:doc_cache_off?>
// ASSUMPTION: This will be set only when the XPath was indeed
// a call to the Document() function. Calling it in other
// situations is likely to fry Xalan.
//
// %REVIEW% We need a MUCH cleaner solution -- one that will
// handle cleaning up after document() and getDTM() in other
// contexts. The whole SourceTreeManager mechanism should probably
// be moved into DTMManager rather than being explicitly invoked in
// FuncDocument and here.
if(m_doc_cache_off)
{
if(DEBUG)
System.out.println("JJK***** CACHE RELEASE *****\n"+
"\tdtm="+dtm.getDocumentBaseURI());
// NOTE: This will work because this is _NOT_ a shared DTM, and thus has
// only a single Document node. If it could ever be an RTF or other
// shared DTM, this would require substantial rework.
xctxt.getSourceTreeManager().removeDocumentFromCache(dtm.getDocument());
xctxt.release(dtm,false);
}
}
}
finally
{
if (transformer.getDebug())
transformer.getTraceManager().fireSelectedEndEvent(sourceNode, this,
"select", new XPath(m_selectExpression),
new org.apache.xpath.objects.XNodeSet(sourceNodes));
xctxt.popSAXLocator();
xctxt.popContextNodeList();
transformer.popElemTemplateElement();
xctxt.popCurrentExpressionNode();
xctxt.popCurrentNode();
sourceNodes.detach();
}
}