Back to index

lightning-sunbird  0.9+nobinonly
txInstructions.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is TransforMiiX XSLT processor code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Jonas Sicking.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Jonas Sicking <jonas@sicking.cc>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "txInstructions.h"
00040 #include "txError.h"
00041 #include "Expr.h"
00042 #include "ExprResult.h"
00043 #include "txStylesheet.h"
00044 #include "txNodeSetContext.h"
00045 #include "txTextHandler.h"
00046 #include "nsIConsoleService.h"
00047 #include "nsServiceManagerUtils.h"
00048 #include "txStringUtils.h"
00049 #include "txAtoms.h"
00050 #include "txRtfHandler.h"
00051 #include "txNodeSorter.h"
00052 #include "txXSLTNumber.h"
00053 #include "txExecutionState.h"
00054 
00055 nsresult
00056 txApplyDefaultElementTemplate::execute(txExecutionState& aEs)
00057 {
00058     txExecutionState::TemplateRule* rule = aEs.getCurrentTemplateRule();
00059     txExpandedName mode(rule->mModeNsId, rule->mModeLocalName);
00060     txStylesheet::ImportFrame* frame = 0;
00061     txInstruction* templ =
00062         aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
00063                                       mode, &aEs, nsnull, &frame);
00064 
00065     nsresult rv = aEs.pushTemplateRule(frame, mode, aEs.mTemplateParams);
00066     NS_ENSURE_SUCCESS(rv, rv);
00067 
00068     return aEs.runTemplate(templ);
00069 }
00070 
00071 nsresult
00072 txApplyImportsEnd::execute(txExecutionState& aEs)
00073 {
00074     aEs.popTemplateRule();
00075     aEs.popParamMap();
00076     
00077     return NS_OK;
00078 }
00079 
00080 nsresult
00081 txApplyImportsStart::execute(txExecutionState& aEs)
00082 {
00083     txExecutionState::TemplateRule* rule = aEs.getCurrentTemplateRule();
00084     // The frame is set to null when there is no current template rule, or
00085     // when the current template rule is a default template. However this
00086     // instruction isn't used in default templates.
00087     if (!rule->mFrame) {
00088         // XXX ErrorReport: apply-imports instantiated without a current rule
00089         return NS_ERROR_XSLT_EXECUTION_FAILURE;
00090     }
00091 
00092     nsresult rv = aEs.pushParamMap(rule->mParams);
00093     NS_ENSURE_SUCCESS(rv, rv);
00094 
00095     txStylesheet::ImportFrame* frame = 0;
00096     txExpandedName mode(rule->mModeNsId, rule->mModeLocalName);
00097     txInstruction* templ =
00098         aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
00099                                       mode, &aEs, rule->mFrame, &frame);
00100 
00101     rv = aEs.pushTemplateRule(frame, mode, rule->mParams);
00102     NS_ENSURE_SUCCESS(rv, rv);
00103 
00104     return aEs.runTemplate(templ);
00105 }
00106 
00107 txApplyTemplates::txApplyTemplates(const txExpandedName& aMode)
00108     : mMode(aMode)
00109 {
00110 }
00111 
00112 nsresult
00113 txApplyTemplates::execute(txExecutionState& aEs)
00114 {
00115     txStylesheet::ImportFrame* frame = 0;
00116     txInstruction* templ =
00117         aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
00118                                       mMode, &aEs, nsnull, &frame);
00119 
00120     nsresult rv = aEs.pushTemplateRule(frame, mMode, aEs.mTemplateParams);
00121     NS_ENSURE_SUCCESS(rv, rv);
00122 
00123     return aEs.runTemplate(templ);
00124 }
00125 
00126 txAttribute::txAttribute(nsAutoPtr<Expr> aName, nsAutoPtr<Expr> aNamespace,
00127                          txNamespaceMap* aMappings)
00128     : mName(aName),
00129       mNamespace(aNamespace),
00130       mMappings(aMappings)
00131 {
00132 }
00133 
00134 nsresult
00135 txAttribute::execute(txExecutionState& aEs)
00136 {
00137     nsRefPtr<txAExprResult> exprRes;
00138     nsresult rv = mName->evaluate(aEs.getEvalContext(),
00139                                   getter_AddRefs(exprRes));
00140     NS_ENSURE_SUCCESS(rv, rv);
00141 
00142     nsAutoString name;
00143     exprRes->stringValue(name);
00144 
00145     const PRUnichar* colon;
00146     if (!XMLUtils::isValidQName(name, &colon) ||
00147         TX_StringEqualsAtom(name, txXMLAtoms::xmlns)) {
00148         // truncate name to indicate failure
00149         name.Truncate();
00150     }
00151 
00152     nsCOMPtr<nsIAtom> prefix;
00153     if (colon) {
00154         prefix = do_GetAtom(Substring(name.get(), colon));
00155     }
00156 
00157     PRInt32 nsId = kNameSpaceID_None;
00158     if (!name.IsEmpty()) {
00159         if (mNamespace) {
00160             rv = mNamespace->evaluate(aEs.getEvalContext(),
00161                                       getter_AddRefs(exprRes));
00162             NS_ENSURE_SUCCESS(rv, rv);
00163 
00164             nsAutoString nspace;
00165             exprRes->stringValue(nspace);
00166 
00167             if (!nspace.IsEmpty()) {
00168                 nsId = txNamespaceManager::getNamespaceID(nspace);
00169                 NS_ENSURE_FALSE(nsId == kNameSpaceID_Unknown,
00170                                 NS_ERROR_FAILURE);
00171             }
00172         }
00173         else if (prefix) {
00174             nsId = mMappings->lookupNamespace(prefix);
00175             if (nsId == kNameSpaceID_Unknown) {
00176                 // tunkate name to indicate failure
00177                 name.Truncate();
00178             }
00179         }
00180     }
00181 
00182     if (prefix == txXMLAtoms::xmlns) {
00183         // Cut xmlns: (6 characters)
00184         name.Cut(0, 6);
00185     }
00186 
00187     nsAutoPtr<txTextHandler> handler(
00188         NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()));
00189     if (!name.IsEmpty()) {
00190         // add attribute if everything was ok
00191         aEs.mResultHandler->attribute(name, nsId, handler->mValue);
00192     }
00193 
00194     return NS_OK;
00195 }
00196 
00197 txCallTemplate::txCallTemplate(const txExpandedName& aName)
00198     : mName(aName)
00199 {
00200 }
00201 
00202 nsresult
00203 txCallTemplate::execute(txExecutionState& aEs)
00204 {
00205     txInstruction* instr = aEs.mStylesheet->getNamedTemplate(mName);
00206     NS_ENSURE_TRUE(instr, NS_ERROR_XSLT_EXECUTION_FAILURE);
00207 
00208     nsresult rv = aEs.runTemplate(instr);
00209     NS_ENSURE_SUCCESS(rv, rv);
00210     
00211     return NS_OK;
00212 }
00213 
00214 txCheckParam::txCheckParam(const txExpandedName& aName)
00215     : mName(aName), mBailTarget(nsnull)
00216 {
00217 }
00218 
00219 nsresult
00220 txCheckParam::execute(txExecutionState& aEs)
00221 {
00222     nsresult rv = NS_OK;
00223     if (aEs.mTemplateParams) {
00224         nsRefPtr<txAExprResult> exprRes;
00225         aEs.mTemplateParams->getVariable(mName, getter_AddRefs(exprRes));
00226         if (exprRes) {
00227             rv = aEs.bindVariable(mName, exprRes);
00228             NS_ENSURE_SUCCESS(rv, rv);
00229 
00230             aEs.gotoInstruction(mBailTarget);
00231         }
00232     }
00233     
00234     return NS_OK;
00235 }
00236 
00237 txConditionalGoto::txConditionalGoto(nsAutoPtr<Expr> aCondition,
00238                                      txInstruction* aTarget)
00239     : mCondition(aCondition),
00240       mTarget(aTarget)
00241 {
00242 }
00243 
00244 nsresult
00245 txConditionalGoto::execute(txExecutionState& aEs)
00246 {
00247     nsRefPtr<txAExprResult> exprRes;
00248     nsresult rv = mCondition->evaluate(aEs.getEvalContext(),
00249                                        getter_AddRefs(exprRes));
00250     NS_ENSURE_SUCCESS(rv, rv);
00251 
00252     if (!exprRes->booleanValue()) {
00253         aEs.gotoInstruction(mTarget);
00254     }
00255 
00256     return NS_OK;
00257 }
00258 
00259 nsresult
00260 txComment::execute(txExecutionState& aEs)
00261 {
00262     nsAutoPtr<txTextHandler> handler(
00263         NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()));
00264     PRUint32 length = handler->mValue.Length();
00265     PRInt32 pos = 0;
00266     while ((pos = handler->mValue.FindChar('-', (PRUint32)pos)) != kNotFound) {
00267         ++pos;
00268         if ((PRUint32)pos == length || handler->mValue.CharAt(pos) == '-') {
00269             handler->mValue.Insert(PRUnichar(' '), pos++);
00270             ++length;
00271         }
00272     }
00273 
00274     aEs.mResultHandler->comment(handler->mValue);
00275 
00276     return NS_OK;
00277 }
00278 
00279 nsresult
00280 txCopyBase::copyNode(const txXPathNode& aNode, txExecutionState& aEs)
00281 {
00282     switch (txXPathNodeUtils::getNodeType(aNode)) {
00283         case txXPathNodeType::ATTRIBUTE_NODE:
00284         {
00285             nsAutoString nodeName, nodeValue;
00286             txXPathNodeUtils::getNodeName(aNode, nodeName);
00287             txXPathNodeUtils::appendNodeValue(aNode, nodeValue);
00288             aEs.mResultHandler->attribute(nodeName,
00289                                           txXPathNodeUtils::getNamespaceID(aNode),
00290                                           nodeValue);
00291             break;
00292         }
00293         case txXPathNodeType::COMMENT_NODE:
00294         {
00295             nsAutoString nodeValue;
00296             txXPathNodeUtils::appendNodeValue(aNode, nodeValue);
00297             aEs.mResultHandler->comment(nodeValue);
00298             break;
00299         }
00300         case txXPathNodeType::DOCUMENT_NODE:
00301         case txXPathNodeType::DOCUMENT_FRAGMENT_NODE:
00302         {
00303             // Copy children
00304             txXPathTreeWalker walker(aNode);
00305             PRBool hasChild = walker.moveToFirstChild();
00306             while (hasChild) {
00307                 copyNode(walker.getCurrentPosition(), aEs);
00308                 hasChild = walker.moveToNextSibling();
00309             }
00310             break;
00311         }
00312         case txXPathNodeType::ELEMENT_NODE:
00313         {
00314             nsAutoString name;
00315             txXPathNodeUtils::getNodeName(aNode, name);
00316             PRInt32 nsID = txXPathNodeUtils::getNamespaceID(aNode);
00317             aEs.mResultHandler->startElement(name, nsID);
00318 
00319             // Copy attributes
00320             txXPathTreeWalker walker(aNode);
00321             if (walker.moveToFirstAttribute()) {
00322                 do {
00323                     nsAutoString nodeName, nodeValue;
00324                     walker.getNodeName(nodeName);
00325                     walker.appendNodeValue(nodeValue);
00326                     aEs.mResultHandler->attribute(nodeName,
00327                                                   walker.getNamespaceID(),
00328                                                   nodeValue);
00329                 } while (walker.moveToNextAttribute());
00330                 walker.moveToParent();
00331             }
00332 
00333             // Copy children
00334             PRBool hasChild = walker.moveToFirstChild();
00335             while (hasChild) {
00336                 copyNode(walker.getCurrentPosition(), aEs);
00337                 hasChild = walker.moveToNextSibling();
00338             }
00339 
00340             aEs.mResultHandler->endElement(name, nsID);
00341             break;
00342         }
00343         case txXPathNodeType::PROCESSING_INSTRUCTION_NODE:
00344         {
00345             nsAutoString target, data;
00346             txXPathNodeUtils::getNodeName(aNode, target);
00347             txXPathNodeUtils::appendNodeValue(aNode, data);
00348             aEs.mResultHandler->processingInstruction(target, data);
00349             break;
00350         }
00351         case txXPathNodeType::TEXT_NODE:
00352         case txXPathNodeType::CDATA_SECTION_NODE:
00353         {
00354             nsAutoString nodeValue;
00355             txXPathNodeUtils::appendNodeValue(aNode, nodeValue);
00356             aEs.mResultHandler->characters(nodeValue, PR_FALSE);
00357             break;
00358         }
00359     }
00360     
00361     return NS_OK;
00362 }
00363 
00364 txCopy::txCopy()
00365     : mBailTarget(nsnull)
00366 {
00367 }
00368 
00369 nsresult
00370 txCopy::execute(txExecutionState& aEs)
00371 {
00372     nsresult rv = NS_OK;
00373     const txXPathNode& node = aEs.getEvalContext()->getContextNode();
00374 
00375     switch (txXPathNodeUtils::getNodeType(node)) {
00376         case txXPathNodeType::DOCUMENT_NODE:
00377         {
00378             const nsAFlatString& empty = EmptyString();
00379 
00380             // "close" current element to ensure that no attributes are added
00381             aEs.mResultHandler->characters(empty, PR_FALSE);
00382 
00383             rv = aEs.pushString(empty);
00384             NS_ENSURE_SUCCESS(rv, rv);
00385 
00386             rv = aEs.pushInt(kNameSpaceID_None);
00387             NS_ENSURE_SUCCESS(rv, rv);
00388 
00389             break;
00390         }
00391         case txXPathNodeType::ELEMENT_NODE:
00392         {
00393             nsAutoString nodeName;
00394             txXPathNodeUtils::getNodeName(node, nodeName);
00395             PRInt32 nsID = txXPathNodeUtils::getNamespaceID(node);
00396 
00397             aEs.mResultHandler->startElement(nodeName, nsID);
00398             // XXX copy namespace nodes once we have them
00399 
00400             rv = aEs.pushString(nodeName);
00401             NS_ENSURE_SUCCESS(rv, rv);
00402 
00403             rv = aEs.pushInt(nsID);
00404             NS_ENSURE_SUCCESS(rv, rv);
00405 
00406             break;
00407         }
00408         default:
00409         {
00410             rv = copyNode(node, aEs);
00411             NS_ENSURE_SUCCESS(rv, rv);
00412 
00413             aEs.gotoInstruction(mBailTarget);
00414         }
00415     }
00416 
00417     return NS_OK;
00418 }
00419 
00420 txCopyOf::txCopyOf(nsAutoPtr<Expr> aSelect)
00421     : mSelect(aSelect)
00422 {
00423 }
00424 
00425 nsresult
00426 txCopyOf::execute(txExecutionState& aEs)
00427 {
00428     nsRefPtr<txAExprResult> exprRes;
00429     nsresult rv = mSelect->evaluate(aEs.getEvalContext(),
00430                                     getter_AddRefs(exprRes));
00431     NS_ENSURE_SUCCESS(rv, rv);
00432 
00433     switch (exprRes->getResultType()) {
00434         case txAExprResult::NODESET:
00435         {
00436             txNodeSet* nodes = NS_STATIC_CAST(txNodeSet*,
00437                                               NS_STATIC_CAST(txAExprResult*,
00438                                                              exprRes));
00439             PRInt32 i;
00440             for (i = 0; i < nodes->size(); ++i) {
00441                 rv = copyNode(nodes->get(i), aEs);
00442                 NS_ENSURE_SUCCESS(rv, rv);
00443             }
00444             break;
00445         }
00446         case txAExprResult::RESULT_TREE_FRAGMENT:
00447         {
00448             txResultTreeFragment* rtf =
00449                 NS_STATIC_CAST(txResultTreeFragment*,
00450                                NS_STATIC_CAST(txAExprResult*, exprRes));
00451             rv = rtf->flushToHandler(&aEs.mResultHandler);
00452             NS_ENSURE_SUCCESS(rv, rv);
00453 
00454             break;
00455         }
00456         default:
00457         {
00458             nsAutoString value;
00459             exprRes->stringValue(value);
00460             if (!value.IsEmpty()) {
00461                 aEs.mResultHandler->characters(value, PR_FALSE);
00462             }
00463             break;
00464         }
00465     }
00466     
00467     return NS_OK;
00468 }
00469 
00470 nsresult
00471 txEndElement::execute(txExecutionState& aEs)
00472 {
00473     PRInt32 namespaceID = aEs.popInt();
00474     nsAutoString nodeName;
00475     aEs.popString(nodeName);
00476     
00477     
00478     // For xsl:elements with a bad name we push an empty name
00479     if (!nodeName.IsEmpty()) {
00480         aEs.mResultHandler->endElement(nodeName, namespaceID);
00481     }
00482 
00483     return NS_OK;
00484 }
00485 
00486 nsresult
00487 txErrorInstruction::execute(txExecutionState& aEs)
00488 {
00489     // XXX ErrorReport: unknown instruction executed
00490     return NS_ERROR_XSLT_EXECUTION_FAILURE;
00491 }
00492 
00493 txGoTo::txGoTo(txInstruction* aTarget)
00494     : mTarget(aTarget)
00495 {
00496 }
00497 
00498 nsresult
00499 txGoTo::execute(txExecutionState& aEs)
00500 {
00501     aEs.gotoInstruction(mTarget);
00502 
00503     return NS_OK;
00504 }
00505 
00506 txInsertAttrSet::txInsertAttrSet(const txExpandedName& aName)
00507     : mName(aName)
00508 {
00509 }
00510 
00511 nsresult
00512 txInsertAttrSet::execute(txExecutionState& aEs)
00513 {
00514     txInstruction* instr = aEs.mStylesheet->getAttributeSet(mName);
00515     NS_ENSURE_TRUE(instr, NS_ERROR_XSLT_EXECUTION_FAILURE);
00516 
00517     nsresult rv = aEs.runTemplate(instr);
00518     NS_ENSURE_SUCCESS(rv, rv);
00519     
00520     return NS_OK;
00521 }
00522 
00523 txLoopNodeSet::txLoopNodeSet(txInstruction* aTarget)
00524     : mTarget(aTarget)
00525 {
00526 }
00527 
00528 nsresult
00529 txLoopNodeSet::execute(txExecutionState& aEs)
00530 {
00531     aEs.popTemplateRule();
00532     txNodeSetContext* context =
00533         NS_STATIC_CAST(txNodeSetContext*, aEs.getEvalContext());
00534     if (!context->hasNext()) {
00535         delete aEs.popEvalContext();
00536 
00537         return NS_OK;
00538     }
00539 
00540     context->next();
00541     aEs.gotoInstruction(mTarget);
00542     
00543     return NS_OK;
00544 }
00545 
00546 txLREAttribute::txLREAttribute(PRInt32 aNamespaceID, nsIAtom* aLocalName,
00547                                nsIAtom* aPrefix, nsAutoPtr<Expr> aValue)
00548     : mNamespaceID(aNamespaceID),
00549       mLocalName(aLocalName),
00550       mPrefix(aPrefix),
00551       mValue(aValue)
00552 {
00553 }
00554 
00555 nsresult
00556 txLREAttribute::execute(txExecutionState& aEs)
00557 {
00558     // We should atomize the resulthandler
00559     nsAutoString nodeName;
00560     if (mPrefix) {
00561         mPrefix->ToString(nodeName);
00562         nsAutoString localName;
00563         nodeName.Append(PRUnichar(':'));
00564         mLocalName->ToString(localName);
00565         nodeName.Append(localName);
00566     }
00567     else {
00568         mLocalName->ToString(nodeName);
00569     }
00570 
00571     nsRefPtr<txAExprResult> exprRes;
00572     nsresult rv = mValue->evaluate(aEs.getEvalContext(),
00573                                    getter_AddRefs(exprRes));
00574     NS_ENSURE_SUCCESS(rv, rv);
00575 
00576     nsAString* value = exprRes->stringValuePointer();
00577     if (value) {
00578         aEs.mResultHandler->attribute(nodeName, mNamespaceID, *value);
00579     }
00580     else {
00581         nsAutoString valueStr;
00582         exprRes->stringValue(valueStr);
00583         aEs.mResultHandler->attribute(nodeName, mNamespaceID, valueStr);
00584     }
00585 
00586     return NS_OK;
00587 }
00588 
00589 txMessage::txMessage(PRBool aTerminate)
00590     : mTerminate(aTerminate)
00591 {
00592 }
00593 
00594 nsresult
00595 txMessage::execute(txExecutionState& aEs)
00596 {
00597     nsAutoPtr<txTextHandler> handler(
00598         NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()));
00599 
00600     nsCOMPtr<nsIConsoleService> consoleSvc = 
00601       do_GetService("@mozilla.org/consoleservice;1");
00602     if (consoleSvc) {
00603         nsAutoString logString(NS_LITERAL_STRING("xsl:message - "));
00604         logString.Append(handler->mValue);
00605         consoleSvc->LogStringMessage(logString.get());
00606     }
00607 
00608     return mTerminate ? NS_ERROR_XSLT_ABORTED : NS_OK;
00609 }
00610 
00611 txNumber::txNumber(txXSLTNumber::LevelType aLevel, nsAutoPtr<txPattern> aCount,
00612                    nsAutoPtr<txPattern> aFrom, nsAutoPtr<Expr> aValue,
00613                    nsAutoPtr<Expr> aFormat, nsAutoPtr<Expr> aGroupingSeparator,
00614                    nsAutoPtr<Expr> aGroupingSize)
00615     : mLevel(aLevel), mCount(aCount), mFrom(aFrom), mValue(aValue),
00616       mFormat(aFormat), mGroupingSeparator(aGroupingSeparator),
00617       mGroupingSize(aGroupingSize)
00618 {
00619 }
00620 
00621 nsresult
00622 txNumber::execute(txExecutionState& aEs)
00623 {
00624     nsAutoString res;
00625     nsresult rv =
00626         txXSLTNumber::createNumber(mValue, mCount, mFrom, mLevel, mGroupingSize,
00627                                    mGroupingSeparator, mFormat,
00628                                    aEs.getEvalContext(), res);
00629     NS_ENSURE_SUCCESS(rv, rv);
00630     
00631     aEs.mResultHandler->characters(res, PR_FALSE);
00632 
00633     return NS_OK;
00634 }
00635 
00636 nsresult
00637 txPopParams::execute(txExecutionState& aEs)
00638 {
00639     delete aEs.popParamMap();
00640 
00641     return NS_OK;
00642 }
00643 
00644 txProcessingInstruction::txProcessingInstruction(nsAutoPtr<Expr> aName)
00645     : mName(aName)
00646 {
00647 }
00648 
00649 nsresult
00650 txProcessingInstruction::execute(txExecutionState& aEs)
00651 {
00652     nsAutoPtr<txTextHandler> handler(
00653         NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()));
00654     XMLUtils::normalizePIValue(handler->mValue);
00655 
00656     nsRefPtr<txAExprResult> exprRes;
00657     nsresult rv = mName->evaluate(aEs.getEvalContext(),
00658                                   getter_AddRefs(exprRes));
00659     NS_ENSURE_SUCCESS(rv, rv);
00660 
00661     nsAutoString name;
00662     exprRes->stringValue(name);
00663 
00664     // Check name validity (must be valid NCName and a PITarget)
00665     // XXX Need to check for NCName and PITarget
00666     const PRUnichar* colon;
00667     if (!XMLUtils::isValidQName(name, &colon)) {
00668         // XXX ErrorReport: bad PI-target
00669         return NS_ERROR_FAILURE;
00670     }
00671 
00672     aEs.mResultHandler->processingInstruction(name, handler->mValue);
00673 
00674     return NS_OK;
00675 }
00676 
00677 txPushNewContext::txPushNewContext(nsAutoPtr<Expr> aSelect)
00678     : mSelect(aSelect), mBailTarget(nsnull)
00679 {
00680 }
00681 
00682 txPushNewContext::~txPushNewContext()
00683 {
00684     PRInt32 i;
00685     for (i = 0; i < mSortKeys.Count(); ++i)
00686     {
00687         delete NS_STATIC_CAST(SortKey*, mSortKeys[i]);
00688     }
00689 }
00690 
00691 nsresult
00692 txPushNewContext::execute(txExecutionState& aEs)
00693 {
00694     nsRefPtr<txAExprResult> exprRes;
00695     nsresult rv = mSelect->evaluate(aEs.getEvalContext(),
00696                                     getter_AddRefs(exprRes));
00697     NS_ENSURE_SUCCESS(rv, rv);
00698 
00699     if (exprRes->getResultType() != txAExprResult::NODESET) {
00700         // XXX ErrorReport: nodeset expected
00701         return NS_ERROR_XSLT_NODESET_EXPECTED;
00702     }
00703     
00704     txNodeSet* nodes = NS_STATIC_CAST(txNodeSet*,
00705                                       NS_STATIC_CAST(txAExprResult*,
00706                                                      exprRes));
00707     
00708     if (nodes->isEmpty()) {
00709         aEs.gotoInstruction(mBailTarget);
00710         
00711         return NS_OK;
00712     }
00713 
00714     txNodeSorter sorter;
00715     PRInt32 i, count = mSortKeys.Count();
00716     for (i = 0; i < count; ++i) {
00717         SortKey* sort = NS_STATIC_CAST(SortKey*, mSortKeys[i]);
00718         rv = sorter.addSortElement(sort->mSelectExpr, sort->mLangExpr,
00719                                    sort->mDataTypeExpr, sort->mOrderExpr,
00720                                    sort->mCaseOrderExpr,
00721                                    aEs.getEvalContext());
00722         NS_ENSURE_SUCCESS(rv, rv);
00723     }
00724     nsRefPtr<txNodeSet> sortedNodes;
00725     rv = sorter.sortNodeSet(nodes, &aEs, getter_AddRefs(sortedNodes));
00726     NS_ENSURE_SUCCESS(rv, rv);
00727     
00728     txNodeSetContext* context = new txNodeSetContext(sortedNodes, &aEs);
00729     NS_ENSURE_TRUE(context, NS_ERROR_OUT_OF_MEMORY);
00730 
00731     context->next();
00732 
00733     rv = aEs.pushEvalContext(context);
00734     if (NS_FAILED(rv)) {
00735         delete context;
00736         return rv;
00737     }
00738     
00739     return NS_OK;
00740 }
00741 
00742 nsresult
00743 txPushNewContext::addSort(nsAutoPtr<Expr> aSelectExpr,
00744                           nsAutoPtr<Expr> aLangExpr,
00745                           nsAutoPtr<Expr> aDataTypeExpr,
00746                           nsAutoPtr<Expr> aOrderExpr,
00747                           nsAutoPtr<Expr> aCaseOrderExpr)
00748 {
00749     SortKey* sort = new SortKey(aSelectExpr, aLangExpr, aDataTypeExpr,
00750                                 aOrderExpr, aCaseOrderExpr);
00751     NS_ENSURE_TRUE(sort, NS_ERROR_OUT_OF_MEMORY);
00752 
00753     if (!mSortKeys.AppendElement(sort)) {
00754         delete sort;
00755         return NS_ERROR_OUT_OF_MEMORY;
00756     }
00757    
00758     return NS_OK;
00759 }
00760 
00761 txPushNewContext::SortKey::SortKey(nsAutoPtr<Expr> aSelectExpr,
00762                                    nsAutoPtr<Expr> aLangExpr,
00763                                    nsAutoPtr<Expr> aDataTypeExpr,
00764                                    nsAutoPtr<Expr> aOrderExpr,
00765                                    nsAutoPtr<Expr> aCaseOrderExpr)
00766     : mSelectExpr(aSelectExpr), mLangExpr(aLangExpr),
00767       mDataTypeExpr(aDataTypeExpr), mOrderExpr(aOrderExpr),
00768       mCaseOrderExpr(aCaseOrderExpr)
00769 {
00770 }
00771 
00772 nsresult
00773 txPushNullTemplateRule::execute(txExecutionState& aEs)
00774 {
00775     return aEs.pushTemplateRule(nsnull, txExpandedName(), nsnull);
00776 }
00777 
00778 nsresult
00779 txPushParams::execute(txExecutionState& aEs)
00780 {
00781     return aEs.pushParamMap(nsnull);
00782 }
00783 
00784 nsresult
00785 txPushRTFHandler::execute(txExecutionState& aEs)
00786 {
00787     txAXMLEventHandler* handler = new txRtfHandler;
00788     NS_ENSURE_TRUE(handler, NS_ERROR_OUT_OF_MEMORY);
00789     
00790     nsresult rv = aEs.pushResultHandler(handler);
00791     if (NS_FAILED(rv)) {
00792         delete handler;
00793         return rv;
00794     }
00795 
00796     return NS_OK;
00797 }
00798 
00799 txPushStringHandler::txPushStringHandler(PRBool aOnlyText)
00800     : mOnlyText(aOnlyText)
00801 {
00802 }
00803 
00804 nsresult
00805 txPushStringHandler::execute(txExecutionState& aEs)
00806 {
00807     txAXMLEventHandler* handler = new txTextHandler(mOnlyText);
00808     NS_ENSURE_TRUE(handler, NS_ERROR_OUT_OF_MEMORY);
00809     
00810     nsresult rv = aEs.pushResultHandler(handler);
00811     if (NS_FAILED(rv)) {
00812         delete handler;
00813         return rv;
00814     }
00815 
00816     return NS_OK;
00817 }
00818 
00819 txRemoveVariable::txRemoveVariable(const txExpandedName& aName)
00820     : mName(aName)
00821 {
00822 }
00823 
00824 nsresult
00825 txRemoveVariable::execute(txExecutionState& aEs)
00826 {
00827     aEs.removeVariable(mName);
00828     
00829     return NS_OK;
00830 }
00831 
00832 nsresult
00833 txReturn::execute(txExecutionState& aEs)
00834 {
00835     NS_ASSERTION(!mNext, "instructions exist after txReturn");
00836     aEs.returnFromTemplate();
00837 
00838     return NS_OK;
00839 }
00840 
00841 txSetParam::txSetParam(const txExpandedName& aName, nsAutoPtr<Expr> aValue)
00842     : mName(aName), mValue(aValue)
00843 {
00844 }
00845 
00846 nsresult
00847 txSetParam::execute(txExecutionState& aEs)
00848 {
00849     nsresult rv = NS_OK;
00850     if (!aEs.mTemplateParams) {
00851         aEs.mTemplateParams = new txVariableMap;
00852         NS_ENSURE_TRUE(aEs.mTemplateParams, NS_ERROR_OUT_OF_MEMORY);
00853     }
00854 
00855     nsRefPtr<txAExprResult> exprRes;
00856     if (mValue) {
00857         rv = mValue->evaluate(aEs.getEvalContext(),
00858                               getter_AddRefs(exprRes));
00859         NS_ENSURE_SUCCESS(rv, rv);
00860     }
00861     else {
00862         nsAutoPtr<txRtfHandler> rtfHandler(
00863             NS_STATIC_CAST(txRtfHandler*, aEs.popResultHandler()));
00864         rv = rtfHandler->getAsRTF(getter_AddRefs(exprRes));
00865         NS_ENSURE_SUCCESS(rv, rv);
00866     }
00867     
00868     rv = aEs.mTemplateParams->bindVariable(mName, exprRes);
00869     NS_ENSURE_SUCCESS(rv, rv);
00870     
00871     return NS_OK;
00872 }
00873 
00874 txSetVariable::txSetVariable(const txExpandedName& aName,
00875                              nsAutoPtr<Expr> aValue)
00876     : mName(aName), mValue(aValue)
00877 {
00878 }
00879 
00880 nsresult
00881 txSetVariable::execute(txExecutionState& aEs)
00882 {
00883     nsresult rv = NS_OK;
00884     nsRefPtr<txAExprResult> exprRes;
00885     if (mValue) {
00886         rv = mValue->evaluate(aEs.getEvalContext(), getter_AddRefs(exprRes));
00887         NS_ENSURE_SUCCESS(rv, rv);
00888     }
00889     else {
00890         nsAutoPtr<txRtfHandler> rtfHandler(
00891             NS_STATIC_CAST(txRtfHandler*, aEs.popResultHandler()));
00892         rv = rtfHandler->getAsRTF(getter_AddRefs(exprRes));
00893         NS_ENSURE_SUCCESS(rv, rv);
00894     }
00895     
00896     return aEs.bindVariable(mName, exprRes);
00897 }
00898 
00899 txStartElement::txStartElement(nsAutoPtr<Expr> aName,
00900                                nsAutoPtr<Expr> aNamespace,
00901                                txNamespaceMap* aMappings)
00902     : mName(aName),
00903       mNamespace(aNamespace),
00904       mMappings(aMappings)
00905 {
00906 }
00907 
00908 nsresult
00909 txStartElement::execute(txExecutionState& aEs)
00910 {
00911     nsRefPtr<txAExprResult> exprRes;
00912     nsresult rv = mName->evaluate(aEs.getEvalContext(),
00913                                   getter_AddRefs(exprRes));
00914     NS_ENSURE_SUCCESS(rv, rv);
00915 
00916     nsAutoString name;
00917     exprRes->stringValue(name);
00918 
00919     const PRUnichar* colon;
00920     if (!XMLUtils::isValidQName(name, &colon)) {
00921         // tunkate name to indicate failure
00922         name.Truncate();
00923     }
00924 
00925     PRInt32 nsId = kNameSpaceID_None;
00926     if (!name.IsEmpty()) {
00927         if (mNamespace) {
00928             rv = mNamespace->evaluate(aEs.getEvalContext(),
00929                                       getter_AddRefs(exprRes));
00930             NS_ENSURE_SUCCESS(rv, rv);
00931 
00932             nsAutoString nspace;
00933             exprRes->stringValue(nspace);
00934 
00935             if (!nspace.IsEmpty()) {
00936                 nsId = txNamespaceManager::getNamespaceID(nspace);
00937                 NS_ENSURE_FALSE(nsId == kNameSpaceID_Unknown,
00938                                 NS_ERROR_FAILURE);
00939             }
00940         }
00941         else {
00942             nsCOMPtr<nsIAtom> prefix;
00943             if (colon) {
00944                 prefix = do_GetAtom(Substring(name.get(), colon));
00945             }
00946             nsId = mMappings->lookupNamespace(prefix);
00947             if (nsId == kNameSpaceID_Unknown) {
00948                 // truncate name to indicate failure
00949                 name.Truncate();
00950             }
00951         }
00952     }
00953 
00954     if (!name.IsEmpty()) {
00955         // add element if everything was ok
00956         aEs.mResultHandler->startElement(name, nsId);
00957     }
00958     else {
00959         // we call characters with an empty string to "close" any element to
00960         // make sure that no attributes are added
00961         aEs.mResultHandler->characters(EmptyString(), PR_FALSE);
00962     }
00963 
00964     rv = aEs.pushString(name);
00965     NS_ENSURE_SUCCESS(rv, rv);
00966 
00967     rv = aEs.pushInt(nsId);
00968     NS_ENSURE_SUCCESS(rv, rv);
00969 
00970     return NS_OK;
00971 }
00972 
00973 
00974 txStartLREElement::txStartLREElement(PRInt32 aNamespaceID,
00975                                      nsIAtom* aLocalName,
00976                                      nsIAtom* aPrefix)
00977     : mNamespaceID(aNamespaceID),
00978       mLocalName(aLocalName),
00979       mPrefix(aPrefix)
00980 {
00981 }
00982 
00983 nsresult
00984 txStartLREElement::execute(txExecutionState& aEs)
00985 {
00986     // We should atomize the resulthandler
00987     nsAutoString nodeName;
00988     if (mPrefix) {
00989         mPrefix->ToString(nodeName);
00990         nsAutoString localName;
00991         nodeName.Append(PRUnichar(':'));
00992         mLocalName->ToString(localName);
00993         nodeName.Append(localName);
00994     }
00995     else {
00996         mLocalName->ToString(nodeName);
00997     }
00998 
00999     aEs.mResultHandler->startElement(nodeName, mNamespaceID);
01000 
01001     nsresult rv = aEs.pushString(nodeName);
01002     NS_ENSURE_SUCCESS(rv, rv);
01003 
01004     rv = aEs.pushInt(mNamespaceID);
01005     NS_ENSURE_SUCCESS(rv, rv);
01006 
01007     return NS_OK;
01008 }
01009 
01010 txText::txText(const nsAString& aStr, PRBool aDOE)
01011     : mStr(aStr),
01012       mDOE(aDOE)
01013 {
01014 }
01015 
01016 nsresult
01017 txText::execute(txExecutionState& aEs)
01018 {
01019     aEs.mResultHandler->characters(mStr, mDOE);
01020     return NS_OK;
01021 }
01022 
01023 txValueOf::txValueOf(nsAutoPtr<Expr> aExpr, PRBool aDOE)
01024     : mExpr(aExpr),
01025       mDOE(aDOE)
01026 {
01027 }
01028 
01029 nsresult
01030 txValueOf::execute(txExecutionState& aEs)
01031 {
01032     nsRefPtr<txAExprResult> exprRes;
01033     nsresult rv = mExpr->evaluate(aEs.getEvalContext(),
01034                                   getter_AddRefs(exprRes));
01035     NS_ENSURE_SUCCESS(rv, rv);
01036 
01037     nsAString* value = exprRes->stringValuePointer();
01038     if (value) {
01039         if (!value->IsEmpty()) {
01040             aEs.mResultHandler->characters(*value, mDOE);
01041         }
01042     }
01043     else {
01044         nsAutoString valueStr;
01045         exprRes->stringValue(valueStr);
01046         if (!valueStr.IsEmpty()) {
01047             aEs.mResultHandler->characters(valueStr, mDOE);
01048         }
01049     }
01050 
01051     return NS_OK;
01052 }