void ElemElement::execute(StylesheetExecutionContext& executionContext) const { StylesheetExecutionContext::GetAndReleaseCachedString elemNameGuard(executionContext); XalanDOMString& elemName = elemNameGuard.get(); m_nameAVT->evaluate(elemName, *this, executionContext); bool isIllegalElement = !XalanQName::isValidQName(elemName); if (isIllegalElement == true) { executionContext.warn( XalanMessageLoader::getMessage(XalanMessages::IllegalElementName_1Param, elemName), executionContext.getCurrentNode(), getLocator()); ElemUse::doExecute(executionContext, false); doExecuteChildren(executionContext, true); } else { StylesheetExecutionContext::GetAndReleaseCachedString elemNameSpaceGuard(executionContext); XalanDOMString& elemNameSpace = elemNameSpaceGuard.get(); if (m_namespaceAVT != 0) { m_namespaceAVT->evaluate(elemNameSpace, *this, executionContext); } XalanDOMString::size_type namespaceLen = length(elemNameSpace); bool foundResultNamespaceForPrefix = false; XalanDOMString::size_type len = length(elemName); const XalanDOMString::size_type indexOfNSSep = indexOf(elemName, XalanUnicode::charColon); const bool havePrefix = indexOfNSSep == len ? false : true; StylesheetExecutionContext::GetAndReleaseCachedString prefixGuard(executionContext); XalanDOMString& prefix = prefixGuard.get(); if (havePrefix == true) { substring(elemName, prefix, 0, indexOfNSSep); const XalanDOMString* const theNamespace = executionContext.getResultNamespaceForPrefix(prefix); if (theNamespace != 0) { foundResultNamespaceForPrefix = true; } else { const XalanDOMString* const theNamespace = getNamespacesHandler().getNamespace(prefix); if(theNamespace == 0 && namespaceLen == 0) { executionContext.warn( XalanMessageLoader::getMessage( XalanMessages::CannotResolvePrefix_1Param, prefix), executionContext.getCurrentNode(), getLocator()); if (m_namespaceAVT != 0) { elemName.erase(0, indexOfNSSep + 1); } else { isIllegalElement = true; executionContext.warn( XalanMessageLoader::getMessage( XalanMessages::IllegalElementName_1Param, elemName), executionContext.getCurrentNode(), getLocator()); } } else if (theNamespace != 0 && namespaceLen == 0 && equals(prefix, DOMServices::s_XMLNamespace) == false) { elemNameSpace = *theNamespace; } } } if (isIllegalElement == false) { executionContext.startElement(c_wstr(elemName)); if(0 == m_namespaceAVT && (havePrefix == false || foundResultNamespaceForPrefix == true)) { if (havePrefix == false) { fixupDefaultNamespace(executionContext); } } else { if(havePrefix == false) { if (namespaceLen > 0) { const XalanDOMString* const theDefaultNamespace = executionContext.getResultNamespaceForPrefix(s_emptyString); if (theDefaultNamespace == 0 || equals(*theDefaultNamespace, elemNameSpace) == false) { executionContext.addResultAttribute( DOMServices::s_XMLNamespace, elemNameSpace); } } else { // OK, the namespace we're generating is the default namespace, // so let's make sure that we really need it. If we don't, // we end up with another xmlns="" on the element we're // generating. Although this isn't really an error, it's // a bit unsightly, so let's suppress it... const XalanDOMString& theParentDefaultNamespace = getParentDefaultNamespace(); if (length(theParentDefaultNamespace) == 0) { if (executionContext.getResultNamespaceForPrefix(s_emptyString) != 0) { executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace); } } else { executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace); } } } else { const XalanDOMString* const theNamespace = executionContext.getResultNamespaceForPrefix(prefix); if (theNamespace == 0 || equals(*theNamespace, elemNameSpace) == false) { insert(prefix, 0, DOMServices::s_XMLNamespaceWithSeparator); executionContext.addResultAttribute(prefix, elemNameSpace); } } } } if (isIllegalElement == true) { ElemUse::doExecute(executionContext, false); doExecuteChildren(executionContext, true); } else { ElemUse::doExecute(executionContext, true); doExecuteChildren(executionContext, false); executionContext.endElement(c_wstr(elemName)); } } }
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()); } }