const XObjectPtr VariablesStack::findXObject( const XalanQName& name, StylesheetExecutionContext& executionContext, bool fIsParam, bool fSearchGlobalSpace, bool& fNameFound) { typedef VariableStackStackType::size_type size_type; // findEntry() returns an index into the stack. We should // _never_ take the address of anything in the stack, since // the address could change at unexpected times. const size_type theEntryIndex = findEntry(name, fIsParam, fSearchGlobalSpace); if (theEntryIndex == m_stack.size()) { fNameFound = false; return XObjectPtr(); } else { assert(theEntryIndex < m_stack.size()); fNameFound = true; assert(m_stack[theEntryIndex].getType() == StackEntry::eVariable || m_stack[theEntryIndex].getType() == StackEntry::eParam || m_stack[theEntryIndex].getType() == StackEntry::eActiveParam); const XObjectPtr& theValue = m_stack[theEntryIndex].getValue(); if (theValue.null() == false) { return theValue; } else { const ElemVariable* const var = m_stack[theEntryIndex].getVariable(); XObjectPtr theNewValue; if (var != 0) { XalanNode* const doc = executionContext.getRootDocument(); assert(doc != 0); XALAN_USING_STD(find) // See if the ElemVariable instance is already being evaluated... if (find(m_guardStack.begin(), m_guardStack.end(), var) != m_guardStack.end()) { const StylesheetExecutionContext::GetCachedString theGuard(executionContext); executionContext.error( XalanMessageLoader::getMessage( theGuard.get(), XalanMessages::CircularVariableDefWasDetected), doc, var->getLocator()); } m_guardStack.push_back(var); #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION) executionContext.pushContextMarker(); #else // We need to set up a stack frame for the variable's execution... typedef StylesheetExecutionContext::PushAndPopContextMarker PushAndPopContextMarker; const PushAndPopContextMarker theContextMarkerPushPop(executionContext); #endif theNewValue = var->getValue(executionContext, doc); assert(theNewValue.null() == false); #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION) executionContext.popContextMarker(); #endif assert(m_guardStack.empty() == false); m_guardStack.pop_back(); m_stack[theEntryIndex].setValue(theNewValue); m_stack[theEntryIndex].activate(); } return theNewValue; } }
void ElemForEach::transformSelectedChildren( StylesheetExecutionContext& executionContext, const ElemTemplateElement* theTemplate) const { assert(m_selectPattern != 0); assert(m_sortElemsCount == m_sortElems.size()); if (m_sortElemsCount == 0) { selectAndSortChildren( executionContext, theTemplate, 0, executionContext.getCurrentStackFrameIndex()); } else { typedef NodeSorter::NodeSortKeyVectorType NodeSortKeyVectorType; typedef StylesheetExecutionContext::BorrowReturnNodeSorter BorrowReturnNodeSorter; BorrowReturnNodeSorter sorter(executionContext); NodeSortKeyVectorType& keys = sorter->getSortKeys(); assert(keys.empty() == true); CollectionClearGuard<NodeSortKeyVectorType> guard(keys); // Reserve the space now... keys.reserve(m_sortElemsCount); // Get some temporary strings to use for evaluting the AVTs... XPathExecutionContext::GetAndReleaseCachedString theTemp1(executionContext); XalanDOMString& langString = theTemp1.get(); XPathExecutionContext::GetAndReleaseCachedString theTemp2(executionContext); XalanDOMString& scratchString = theTemp2.get(); // March backwards, performing a sort on each xsl:sort child. // Probably not the most efficient method. for(SortElemsVectorType::size_type i = 0; i < m_sortElemsCount; i++) { const ElemSort* const sort = m_sortElems[i]; assert(sort != 0); const AVT* avt = sort->getLangAVT(); if(0 != avt) { avt->evaluate(langString, *this, executionContext); } avt = sort->getDataTypeAVT(); if(0 != avt) { avt->evaluate(scratchString, *this, executionContext); } bool treatAsNumbers = false; if (isEmpty(scratchString) == false) { if (equals(scratchString, Constants::ATTRVAL_DATATYPE_NUMBER) == true) { treatAsNumbers = true; } else if (equals(scratchString, Constants::ATTRVAL_DATATYPE_TEXT) == false) { const XalanQNameByValue theQName(scratchString, this); if (theQName.getNamespace().length() == 0) { executionContext.error( XalanMessageLoader::getMessage(XalanMessages::XslSortDataTypeMustBe), executionContext.getCurrentNode(), sort->getLocator()); } else { executionContext.warn( XalanMessageLoader::getMessage(XalanMessages::XslSortHasUnlnownDataType), executionContext.getCurrentNode(), sort->getLocator()); } } } clear(scratchString); avt = sort->getOrderAVT(); if(0 != avt) { avt->evaluate(scratchString, *this, executionContext); } bool descending = false; if (isEmpty(scratchString) == false) { if (equals(scratchString, Constants::ATTRVAL_ORDER_DESCENDING) == true) { descending = true; } else if (equals(scratchString, Constants::ATTRVAL_ORDER_ASCENDING) == false) { executionContext.error( XalanMessageLoader::getMessage(XalanMessages::XslSortMustBeAscendOrDescend), executionContext.getCurrentNode(), sort->getLocator()); } } clear(scratchString); avt = sort->getCaseOrderAVT(); if(0 != avt) { avt->evaluate(scratchString, *this, executionContext); } XalanCollationServices::eCaseOrder caseOrder = XalanCollationServices::eDefault; if (isEmpty(scratchString) == false) { if (equals(scratchString, Constants::ATTRVAL_CASEORDER_UPPER) == true) { caseOrder = XalanCollationServices::eUpperFirst; } else if (equals(scratchString, Constants::ATTRVAL_CASEORDER_LOWER) == true) { caseOrder = XalanCollationServices::eLowerFirst; } else { executionContext.error( XalanMessageLoader::getMessage(XalanMessages::XslSortCaseOrderMustBe), executionContext.getCurrentNode(), sort->getLocator()); } } clear(scratchString); keys.push_back( NodeSortKey( executionContext, sort->getSelectPattern(), treatAsNumbers, descending, caseOrder, langString, *this)); } selectAndSortChildren( executionContext, theTemplate, sorter.get(), executionContext.getCurrentStackFrameIndex()); } }