~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/extensions/transformiix/source/xslt/txStylesheet.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Mozilla Public License Version
 
6
 * 1.1 (the "License"); you may not use this file except in compliance with
 
7
 * the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/MPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is TransforMiiX XSLT processor.
 
16
 *
 
17
 * The Initial Developer of the Original Code is
 
18
 * Jonas Sicking.
 
19
 * Portions created by the Initial Developer are Copyright (C) 2002
 
20
 * Jonas Sicking. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Jonas Sicking <jonas@sicking.cc>
 
24
 *
 
25
 * Alternatively, the contents of this file may be used under the terms of
 
26
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
27
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
28
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
29
 * of those above. If you wish to allow use of your version of this file only
 
30
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
31
 * use your version of this file under the terms of the MPL, indicate your
 
32
 * decision by deleting the provisions above and replace them with the notice
 
33
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
34
 * the provisions above, a recipient may use your version of this file under
 
35
 * the terms of any one of the MPL, the GPL or the LGPL.
 
36
 *
 
37
 * ***** END LICENSE BLOCK ***** */
 
38
 
 
39
#include "txStylesheet.h"
 
40
#include "Expr.h"
 
41
#include "txXSLTPatterns.h"
 
42
#include "txToplevelItems.h"
 
43
#include "txInstructions.h"
 
44
#include "primitives.h"
 
45
#include "XSLTFunctions.h"
 
46
#include "TxLog.h"
 
47
#include "txKey.h"
 
48
 
 
49
txStylesheet::txStylesheet()
 
50
    : mRootFrame(nsnull),
 
51
      mNamedTemplates(PR_FALSE),
 
52
      mDecimalFormats(PR_TRUE),
 
53
      mAttributeSets(PR_FALSE),
 
54
      mGlobalVariables(PR_TRUE),
 
55
      mKeys(PR_TRUE)
 
56
{
 
57
}
 
58
 
 
59
nsresult
 
60
txStylesheet::init()
 
61
{
 
62
    mRootFrame = new ImportFrame;
 
63
    NS_ENSURE_TRUE(mRootFrame, NS_ERROR_OUT_OF_MEMORY);
 
64
    
 
65
    // Create default templates
 
66
    // element/root template
 
67
    mContainerTemplate = new txPushParams;
 
68
    NS_ENSURE_TRUE(mContainerTemplate, NS_ERROR_OUT_OF_MEMORY);
 
69
 
 
70
    nsAutoPtr<txNodeTest> nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
 
71
    NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY);
 
72
 
 
73
    nsAutoPtr<Expr> nodeExpr(new LocationStep(nt, LocationStep::CHILD_AXIS));
 
74
    NS_ENSURE_TRUE(nodeExpr, NS_ERROR_OUT_OF_MEMORY);
 
75
 
 
76
    txPushNewContext* pushContext = new txPushNewContext(nodeExpr);
 
77
    mContainerTemplate->mNext = pushContext;
 
78
    NS_ENSURE_TRUE(pushContext, NS_ERROR_OUT_OF_MEMORY);
 
79
 
 
80
    txApplyDefaultElementTemplate* applyTemplates =
 
81
        new txApplyDefaultElementTemplate;
 
82
    pushContext->mNext = applyTemplates;
 
83
    NS_ENSURE_TRUE(applyTemplates, NS_ERROR_OUT_OF_MEMORY);
 
84
 
 
85
    txLoopNodeSet* loopNodeSet = new txLoopNodeSet(applyTemplates);
 
86
    applyTemplates->mNext = loopNodeSet;
 
87
    NS_ENSURE_TRUE(loopNodeSet, NS_ERROR_OUT_OF_MEMORY);
 
88
 
 
89
    txPopParams* popParams = new txPopParams;
 
90
    pushContext->mBailTarget = loopNodeSet->mNext = popParams;
 
91
    NS_ENSURE_TRUE(popParams, NS_ERROR_OUT_OF_MEMORY);
 
92
 
 
93
    popParams->mNext = new txReturn();
 
94
    NS_ENSURE_TRUE(popParams->mNext, NS_ERROR_OUT_OF_MEMORY);
 
95
 
 
96
    // attribute/textnode template
 
97
    nt = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
 
98
    NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY);
 
99
 
 
100
    nodeExpr = new LocationStep(nt, LocationStep::SELF_AXIS);
 
101
    NS_ENSURE_TRUE(nodeExpr, NS_ERROR_OUT_OF_MEMORY);
 
102
 
 
103
    mCharactersTemplate = new txValueOf(nodeExpr, PR_FALSE);
 
104
    NS_ENSURE_TRUE(mCharactersTemplate, NS_ERROR_OUT_OF_MEMORY);
 
105
 
 
106
    mCharactersTemplate->mNext = new txReturn();
 
107
    NS_ENSURE_TRUE(mCharactersTemplate->mNext, NS_ERROR_OUT_OF_MEMORY);
 
108
 
 
109
    // pi/comment/namespace template
 
110
    mEmptyTemplate = new txReturn();
 
111
    NS_ENSURE_TRUE(mEmptyTemplate, NS_ERROR_OUT_OF_MEMORY);
 
112
 
 
113
    return NS_OK;
 
114
}
 
115
 
 
116
txStylesheet::~txStylesheet()
 
117
{
 
118
    // Delete all ImportFrames
 
119
    delete mRootFrame;
 
120
    txListIterator frameIter(&mImportFrames);
 
121
    while (frameIter.hasNext()) {
 
122
        delete NS_STATIC_CAST(ImportFrame*, frameIter.next());
 
123
    }
 
124
 
 
125
    txListIterator instrIter(&mTemplateInstructions);
 
126
    while (instrIter.hasNext()) {
 
127
        delete NS_STATIC_CAST(txInstruction*, instrIter.next());
 
128
    }
 
129
    
 
130
    // We can't make the map own its values because then we wouldn't be able
 
131
    // to merge attributesets of the same name
 
132
    txExpandedNameMap::iterator attrSetIter(mAttributeSets);
 
133
    while (attrSetIter.next()) {
 
134
        delete attrSetIter.value();
 
135
    }
 
136
}
 
137
 
 
138
txInstruction*
 
139
txStylesheet::findTemplate(const txXPathNode& aNode,
 
140
                           const txExpandedName& aMode,
 
141
                           txIMatchContext* aContext,
 
142
                           ImportFrame* aImportedBy,
 
143
                           ImportFrame** aImportFrame)
 
144
{
 
145
    NS_ASSERTION(aImportFrame, "missing ImportFrame pointer");
 
146
 
 
147
    *aImportFrame = nsnull;
 
148
    txInstruction* matchTemplate = nsnull;
 
149
    ImportFrame* endFrame = nsnull;
 
150
    txListIterator frameIter(&mImportFrames);
 
151
 
 
152
    if (aImportedBy) {
 
153
        ImportFrame* curr = NS_STATIC_CAST(ImportFrame*, frameIter.next());
 
154
        while (curr != aImportedBy) {
 
155
               curr = NS_STATIC_CAST(ImportFrame*, frameIter.next());
 
156
        }
 
157
        endFrame = aImportedBy->mFirstNotImported;
 
158
    }
 
159
 
 
160
#ifdef PR_LOGGING
 
161
    txPattern* match = 0;
 
162
#endif
 
163
 
 
164
    ImportFrame* frame;
 
165
    while (!matchTemplate &&
 
166
           (frame = NS_STATIC_CAST(ImportFrame*, frameIter.next())) &&
 
167
           frame != endFrame) {
 
168
 
 
169
        // get templatelist for this mode
 
170
        txList* templates =
 
171
            NS_STATIC_CAST(txList*, frame->mMatchableTemplates.get(aMode));
 
172
 
 
173
        if (templates) {
 
174
            txListIterator templateIter(templates);
 
175
 
 
176
            // Find template with highest priority
 
177
            MatchableTemplate* templ;
 
178
            while (!matchTemplate &&
 
179
                   (templ =
 
180
                    NS_STATIC_CAST(MatchableTemplate*, templateIter.next()))) {
 
181
                if (templ->mMatch->matches(aNode, aContext)) {
 
182
                    matchTemplate = templ->mFirstInstruction;
 
183
                    *aImportFrame = frame;
 
184
#ifdef PR_LOGGING
 
185
                    match = templ->mMatch;
 
186
#endif
 
187
                }
 
188
            }
 
189
        }
 
190
    }
 
191
 
 
192
#ifdef PR_LOGGING
 
193
    nsAutoString mode, nodeName;
 
194
    if (aMode.mLocalName) {
 
195
        aMode.mLocalName->ToString(mode);
 
196
    }
 
197
    txXPathNodeUtils::getNodeName(aNode, nodeName);
 
198
    if (matchTemplate) {
 
199
        nsAutoString matchAttr;
 
200
        match->toString(matchAttr);
 
201
        PR_LOG(txLog::xslt, PR_LOG_DEBUG,
 
202
               ("MatchTemplate, Pattern %s, Mode %s, Node %s\n",
 
203
                NS_LossyConvertUCS2toASCII(matchAttr).get(),
 
204
                NS_LossyConvertUCS2toASCII(mode).get(),
 
205
                NS_LossyConvertUCS2toASCII(nodeName).get()));
 
206
    }
 
207
    else {
 
208
        PR_LOG(txLog::xslt, PR_LOG_DEBUG,
 
209
               ("No match, Node %s, Mode %s\n", 
 
210
                NS_LossyConvertUCS2toASCII(nodeName).get(),
 
211
                NS_LossyConvertUCS2toASCII(mode).get()));
 
212
    }
 
213
#endif
 
214
 
 
215
    if (!matchTemplate) {
 
216
        switch (txXPathNodeUtils::getNodeType(aNode)) {
 
217
            case txXPathNodeType::ELEMENT_NODE:
 
218
            case txXPathNodeType::DOCUMENT_NODE:
 
219
            {
 
220
                matchTemplate = mContainerTemplate;
 
221
                break;
 
222
            }
 
223
            case txXPathNodeType::ATTRIBUTE_NODE:
 
224
            case txXPathNodeType::TEXT_NODE:
 
225
            case txXPathNodeType::CDATA_SECTION_NODE:
 
226
            {
 
227
                matchTemplate = mCharactersTemplate;
 
228
                break;
 
229
            }
 
230
            default:
 
231
            {
 
232
                matchTemplate = mEmptyTemplate;
 
233
                break;
 
234
            }
 
235
        }
 
236
    }
 
237
 
 
238
    return matchTemplate;
 
239
}
 
240
 
 
241
txDecimalFormat*
 
242
txStylesheet::getDecimalFormat(const txExpandedName& aName)
 
243
{
 
244
    return NS_STATIC_CAST(txDecimalFormat*, mDecimalFormats.get(aName));
 
245
}
 
246
 
 
247
txInstruction*
 
248
txStylesheet::getAttributeSet(const txExpandedName& aName)
 
249
{
 
250
    return NS_STATIC_CAST(txInstruction*, mAttributeSets.get(aName));
 
251
}
 
252
 
 
253
txInstruction*
 
254
txStylesheet::getNamedTemplate(const txExpandedName& aName)
 
255
{
 
256
    return NS_STATIC_CAST(txInstruction*, mNamedTemplates.get(aName));
 
257
}
 
258
 
 
259
txOutputFormat*
 
260
txStylesheet::getOutputFormat()
 
261
{
 
262
    return &mOutputFormat;
 
263
}
 
264
 
 
265
txStylesheet::GlobalVariable*
 
266
txStylesheet::getGlobalVariable(const txExpandedName& aName)
 
267
{
 
268
    return NS_STATIC_CAST(GlobalVariable*, mGlobalVariables.get(aName));
 
269
}
 
270
 
 
271
const txExpandedNameMap&
 
272
txStylesheet::getKeyMap()
 
273
{
 
274
    return mKeys;
 
275
}
 
276
 
 
277
PRBool
 
278
txStylesheet::isStripSpaceAllowed(const txXPathNode& aNode, txIMatchContext* aContext)
 
279
{
 
280
    PRInt32 frameCount = mStripSpaceTests.Count();
 
281
    if (frameCount == 0) {
 
282
        return PR_FALSE;
 
283
    }
 
284
 
 
285
    txXPathTreeWalker walker(aNode);
 
286
 
 
287
    PRUint16 nodeType = walker.getNodeType();
 
288
    if (nodeType == txXPathNodeType::TEXT_NODE ||
 
289
        nodeType == txXPathNodeType::CDATA_SECTION_NODE) {
 
290
        if (!txXPathNodeUtils::isWhitespace(aNode) || !walker.moveToParent()) {
 
291
            return PR_FALSE;
 
292
        }
 
293
        nodeType = walker.getNodeType();
 
294
    }
 
295
 
 
296
    if (nodeType != txXPathNodeType::ELEMENT_NODE) {
 
297
        return PR_FALSE;
 
298
    }
 
299
 
 
300
    const txXPathNode& node = walker.getCurrentPosition();
 
301
 
 
302
    // check Whitespace stipping handling list against given Node
 
303
    PRInt32 i;
 
304
    for (i = 0; i < frameCount; ++i) {
 
305
        txStripSpaceTest* sst =
 
306
            NS_STATIC_CAST(txStripSpaceTest*, mStripSpaceTests[i]);
 
307
        if (sst->matches(node, aContext)) {
 
308
            return sst->stripsSpace() && !XMLUtils::getXMLSpacePreserve(node);
 
309
        }
 
310
    }
 
311
 
 
312
    return PR_FALSE;
 
313
}
 
314
 
 
315
nsresult
 
316
txStylesheet::doneCompiling()
 
317
{
 
318
    nsresult rv = NS_OK;
 
319
    // Collect all importframes into a single ordered list
 
320
    txListIterator frameIter(&mImportFrames);
 
321
    rv = frameIter.addAfter(mRootFrame);
 
322
    NS_ENSURE_SUCCESS(rv, rv);
 
323
    
 
324
    mRootFrame = nsnull;
 
325
    frameIter.next();
 
326
    rv = addFrames(frameIter);
 
327
    NS_ENSURE_SUCCESS(rv, rv);
 
328
 
 
329
    // Loop through importframes in decreasing-precedence-order and process
 
330
    // all items
 
331
    frameIter.reset();
 
332
    ImportFrame* frame;
 
333
    while ((frame = NS_STATIC_CAST(ImportFrame*, frameIter.next()))) {
 
334
        nsVoidArray frameStripSpaceTests;
 
335
 
 
336
        txListIterator itemIter(&frame->mToplevelItems);
 
337
        itemIter.resetToEnd();
 
338
        txToplevelItem* item;
 
339
        while ((item = NS_STATIC_CAST(txToplevelItem*, itemIter.previous()))) {
 
340
            switch (item->getType()) {
 
341
                case txToplevelItem::attributeSet:
 
342
                {
 
343
                    rv = addAttributeSet(NS_STATIC_CAST(txAttributeSetItem*,
 
344
                                                        item));
 
345
                    NS_ENSURE_SUCCESS(rv, rv);
 
346
                    break;
 
347
                }
 
348
                case txToplevelItem::dummy:
 
349
                case txToplevelItem::import:
 
350
                {
 
351
                    break;
 
352
                }
 
353
                case txToplevelItem::output:
 
354
                {
 
355
                    mOutputFormat.merge(NS_STATIC_CAST(txOutputItem*, item)->mFormat);
 
356
                    break;
 
357
                }
 
358
                case txToplevelItem::stripSpace:
 
359
                {
 
360
                    rv = addStripSpace(NS_STATIC_CAST(txStripSpaceItem*, item),
 
361
                                       frameStripSpaceTests);
 
362
                    NS_ENSURE_SUCCESS(rv, rv);
 
363
                    break;
 
364
                }
 
365
                case txToplevelItem::templ:
 
366
                {
 
367
                    rv = addTemplate(NS_STATIC_CAST(txTemplateItem*, item),
 
368
                                     frame);
 
369
                    NS_ENSURE_SUCCESS(rv, rv);
 
370
 
 
371
                    break;
 
372
                }
 
373
                case txToplevelItem::variable:
 
374
                {
 
375
                    rv = addGlobalVariable(NS_STATIC_CAST(txVariableItem*,
 
376
                                                          item));
 
377
                    NS_ENSURE_SUCCESS(rv, rv);
 
378
 
 
379
                    break;
 
380
                }
 
381
            }
 
382
            delete item;
 
383
            itemIter.remove(); //remove() moves to the previous
 
384
            itemIter.next();
 
385
        }
 
386
        if (!mStripSpaceTests.AppendElements(frameStripSpaceTests)) {
 
387
            return NS_ERROR_OUT_OF_MEMORY;
 
388
        }
 
389
        
 
390
        frameStripSpaceTests.Clear();
 
391
    }
 
392
 
 
393
    if (!mDecimalFormats.get(txExpandedName())) {
 
394
        nsAutoPtr<txDecimalFormat> format(new txDecimalFormat);
 
395
        NS_ENSURE_TRUE(format, NS_ERROR_OUT_OF_MEMORY);
 
396
        
 
397
        rv = mDecimalFormats.add(txExpandedName(), format);
 
398
        NS_ENSURE_SUCCESS(rv, rv);
 
399
        
 
400
        format.forget();
 
401
    }
 
402
 
 
403
    return NS_OK;
 
404
}
 
405
 
 
406
nsresult
 
407
txStylesheet::addTemplate(txTemplateItem* aTemplate,
 
408
                          ImportFrame* aImportFrame)
 
409
{
 
410
    NS_ASSERTION(aTemplate, "missing template");
 
411
 
 
412
    txInstruction* instr = aTemplate->mFirstInstruction;
 
413
    nsresult rv = mTemplateInstructions.add(instr);
 
414
    NS_ENSURE_SUCCESS(rv, rv);
 
415
 
 
416
    // mTemplateInstructions now owns the instructions
 
417
    aTemplate->mFirstInstruction.forget();
 
418
 
 
419
    if (!aTemplate->mName.isNull()) {
 
420
        rv = mNamedTemplates.add(aTemplate->mName, instr);
 
421
        NS_ENSURE_TRUE(NS_SUCCEEDED(rv) || rv == NS_ERROR_XSLT_ALREADY_SET,
 
422
                       rv);
 
423
    }
 
424
 
 
425
    if (!aTemplate->mMatch) {
 
426
        // This is no error, see section 6 Named Templates
 
427
 
 
428
        return NS_OK;
 
429
    }
 
430
 
 
431
    // get the txList for the right mode
 
432
    txList* templates =
 
433
        NS_STATIC_CAST(txList*,
 
434
                       aImportFrame->mMatchableTemplates.get(aTemplate->mMode));
 
435
 
 
436
    if (!templates) {
 
437
        nsAutoPtr<txList> newList(new txList);
 
438
        NS_ENSURE_TRUE(newList, NS_ERROR_OUT_OF_MEMORY);
 
439
 
 
440
        rv = aImportFrame->mMatchableTemplates.add(aTemplate->mMode, newList);
 
441
        NS_ENSURE_SUCCESS(rv, rv);
 
442
        
 
443
        templates = newList.forget();
 
444
    }
 
445
 
 
446
    // Add the simple patterns to the list of matchable templates, according
 
447
    // to default priority
 
448
    txList simpleMatches;
 
449
    rv = aTemplate->mMatch->getSimplePatterns(simpleMatches);
 
450
    if (simpleMatches.get(0) == aTemplate->mMatch) {
 
451
        aTemplate->mMatch.forget();
 
452
    }
 
453
    
 
454
    txListIterator simples(&simpleMatches);
 
455
    while (simples.hasNext()) {
 
456
        // XXX if we fail in this loop, we leak the remaining simple patterns
 
457
        nsAutoPtr<txPattern> simple(NS_STATIC_CAST(txPattern*, simples.next()));
 
458
        double priority = aTemplate->mPrio;
 
459
        if (Double::isNaN(priority)) {
 
460
            priority = simple->getDefaultPriority();
 
461
            NS_ASSERTION(!Double::isNaN(priority),
 
462
                         "simple pattern without default priority");
 
463
        }
 
464
        nsAutoPtr<MatchableTemplate>
 
465
            nt(new MatchableTemplate(instr, simple, priority));
 
466
        NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY);
 
467
 
 
468
        txListIterator templ(templates);
 
469
        while (templ.hasNext()) {
 
470
            MatchableTemplate* mt = NS_STATIC_CAST(MatchableTemplate*,
 
471
                                                   templ.next());
 
472
            if (priority > mt->mPriority) {
 
473
                rv = templ.addBefore(nt);
 
474
                NS_ENSURE_SUCCESS(rv, rv);
 
475
 
 
476
                nt.forget();
 
477
                break;
 
478
            }
 
479
        }
 
480
        if (nt) {
 
481
            rv = templates->add(nt);
 
482
            NS_ENSURE_SUCCESS(rv, rv);
 
483
 
 
484
            nt.forget();
 
485
        }
 
486
    }
 
487
 
 
488
    return NS_OK;
 
489
}
 
490
 
 
491
nsresult
 
492
txStylesheet::addFrames(txListIterator& aInsertIter)
 
493
{
 
494
    ImportFrame* frame = NS_STATIC_CAST(ImportFrame*, aInsertIter.current());
 
495
    nsresult rv = NS_OK;
 
496
    txListIterator iter(&frame->mToplevelItems);
 
497
    txToplevelItem* item;
 
498
    while ((item = NS_STATIC_CAST(txToplevelItem*, iter.next()))) {
 
499
        if (item->getType() == txToplevelItem::import) {
 
500
            txImportItem* import = NS_STATIC_CAST(txImportItem*, item);
 
501
            import->mFrame->mFirstNotImported =
 
502
                NS_STATIC_CAST(ImportFrame*, aInsertIter.next());
 
503
            rv = aInsertIter.addBefore(import->mFrame);
 
504
            NS_ENSURE_SUCCESS(rv, rv);
 
505
 
 
506
            import->mFrame.forget();
 
507
            aInsertIter.previous();
 
508
            rv = addFrames(aInsertIter);
 
509
            NS_ENSURE_SUCCESS(rv, rv);
 
510
            aInsertIter.previous();
 
511
        }
 
512
    }
 
513
    
 
514
    return NS_OK;
 
515
}
 
516
 
 
517
nsresult
 
518
txStylesheet::addStripSpace(txStripSpaceItem* aStripSpaceItem,
 
519
                            nsVoidArray& frameStripSpaceTests)
 
520
{
 
521
    PRInt32 testCount = aStripSpaceItem->mStripSpaceTests.Count();
 
522
    for (; testCount > 0; --testCount) {
 
523
        txStripSpaceTest* sst =
 
524
            NS_STATIC_CAST(txStripSpaceTest*,
 
525
                           aStripSpaceItem->mStripSpaceTests[testCount-1]);
 
526
        double priority = sst->getDefaultPriority();
 
527
        PRInt32 i, frameCount = frameStripSpaceTests.Count();
 
528
        for (i = 0; i < frameCount; ++i) {
 
529
            txStripSpaceTest* fsst =
 
530
                NS_STATIC_CAST(txStripSpaceTest*, frameStripSpaceTests[i]);
 
531
            if (fsst->getDefaultPriority() < priority) {
 
532
                break;
 
533
            }
 
534
        }
 
535
        if (!frameStripSpaceTests.InsertElementAt(sst, i)) {
 
536
            return NS_ERROR_OUT_OF_MEMORY;
 
537
        }
 
538
 
 
539
        aStripSpaceItem->mStripSpaceTests.RemoveElementAt(testCount-1);
 
540
    }
 
541
 
 
542
    return NS_OK;
 
543
}
 
544
 
 
545
nsresult
 
546
txStylesheet::addAttributeSet(txAttributeSetItem* aAttributeSetItem)
 
547
{
 
548
    nsresult rv = NS_OK;
 
549
    txInstruction* oldInstr =
 
550
        NS_STATIC_CAST(txInstruction*,
 
551
                       mAttributeSets.get(aAttributeSetItem->mName));
 
552
    if (!oldInstr) {
 
553
        rv = mAttributeSets.add(aAttributeSetItem->mName,
 
554
                                aAttributeSetItem->mFirstInstruction);
 
555
        NS_ENSURE_SUCCESS(rv, rv);
 
556
        
 
557
        aAttributeSetItem->mFirstInstruction.forget();
 
558
        
 
559
        return NS_OK;
 
560
    }
 
561
    
 
562
    // We need to prepend the new instructions before the existing ones.
 
563
    txInstruction* instr = aAttributeSetItem->mFirstInstruction;
 
564
    txInstruction* lastNonReturn = nsnull;
 
565
    while (instr->mNext) {
 
566
        lastNonReturn = instr;
 
567
        instr = instr->mNext;
 
568
    }
 
569
    
 
570
    if (!lastNonReturn) {
 
571
        // The new attributeset is empty, so lets just ignore it.
 
572
        return NS_OK;
 
573
    }
 
574
 
 
575
    rv = mAttributeSets.set(aAttributeSetItem->mName,
 
576
                            aAttributeSetItem->mFirstInstruction);
 
577
    NS_ENSURE_SUCCESS(rv, rv);
 
578
 
 
579
    aAttributeSetItem->mFirstInstruction.forget();
 
580
 
 
581
    delete lastNonReturn->mNext;      // Delete the txReturn...
 
582
    lastNonReturn->mNext = oldInstr;  // ...and link up the old instructions.
 
583
 
 
584
    return NS_OK;
 
585
}
 
586
 
 
587
nsresult
 
588
txStylesheet::addGlobalVariable(txVariableItem* aVariable)
 
589
{
 
590
    if (mGlobalVariables.get(aVariable->mName)) {
 
591
        return NS_OK;
 
592
    }
 
593
    nsAutoPtr<GlobalVariable> var(
 
594
        new GlobalVariable(aVariable->mValue, aVariable->mFirstInstruction,
 
595
                           aVariable->mIsParam));
 
596
    NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY);
 
597
    
 
598
    nsresult rv = mGlobalVariables.add(aVariable->mName, var);
 
599
    NS_ENSURE_SUCCESS(rv, rv);
 
600
    
 
601
    var.forget();
 
602
    
 
603
    return NS_OK;
 
604
    
 
605
}
 
606
 
 
607
nsresult
 
608
txStylesheet::addKey(const txExpandedName& aName,
 
609
                     nsAutoPtr<txPattern> aMatch, nsAutoPtr<Expr> aUse)
 
610
{
 
611
    nsresult rv = NS_OK;
 
612
 
 
613
    txXSLKey* xslKey = NS_STATIC_CAST(txXSLKey*, mKeys.get(aName));
 
614
    if (!xslKey) {
 
615
        xslKey = new txXSLKey(aName);
 
616
        NS_ENSURE_TRUE(xslKey, NS_ERROR_OUT_OF_MEMORY);
 
617
 
 
618
        rv = mKeys.add(aName, xslKey);
 
619
        if (NS_FAILED(rv)) {
 
620
            delete xslKey;
 
621
            return rv;
 
622
        }
 
623
    }
 
624
    if (!xslKey->addKey(aMatch, aUse)) {
 
625
        return NS_ERROR_OUT_OF_MEMORY;
 
626
    }
 
627
    return NS_OK;
 
628
}
 
629
 
 
630
nsresult
 
631
txStylesheet::addDecimalFormat(const txExpandedName& aName,
 
632
                               nsAutoPtr<txDecimalFormat> aFormat)
 
633
{
 
634
    txDecimalFormat* existing =
 
635
        NS_STATIC_CAST(txDecimalFormat*, mDecimalFormats.get(aName));
 
636
    if (existing) {
 
637
        NS_ENSURE_TRUE(existing->isEqual(aFormat),
 
638
                       NS_ERROR_XSLT_PARSE_FAILURE);
 
639
 
 
640
        return NS_OK;
 
641
    }
 
642
 
 
643
    nsresult rv = mDecimalFormats.add(aName, aFormat);
 
644
    NS_ENSURE_SUCCESS(rv, rv);
 
645
    
 
646
    aFormat.forget();
 
647
 
 
648
    return NS_OK;
 
649
}
 
650
 
 
651
txStylesheet::ImportFrame::ImportFrame()
 
652
    : mMatchableTemplates(MB_TRUE),
 
653
      mFirstNotImported(nsnull)
 
654
{
 
655
}
 
656
 
 
657
txStylesheet::ImportFrame::~ImportFrame()
 
658
{
 
659
    // Delete templates in mMatchableTemplates
 
660
    txExpandedNameMap::iterator mapIter(mMatchableTemplates);
 
661
    while (mapIter.next()) {
 
662
        txListIterator templIter(NS_STATIC_CAST(txList*, mapIter.value()));
 
663
        MatchableTemplate* templ;
 
664
        while ((templ = NS_STATIC_CAST(MatchableTemplate*, templIter.next()))) {
 
665
            delete templ;
 
666
        }
 
667
    }
 
668
    
 
669
    txListIterator tlIter(&mToplevelItems);
 
670
    while (tlIter.hasNext()) {
 
671
        delete NS_STATIC_CAST(txToplevelItem*, tlIter.next());
 
672
    }
 
673
}
 
674
 
 
675
txStylesheet::GlobalVariable::GlobalVariable(nsAutoPtr<Expr> aExpr,
 
676
                                             nsAutoPtr<txInstruction> aFirstInstruction,
 
677
                                             PRBool aIsParam)
 
678
    : mExpr(aExpr), mFirstInstruction(aFirstInstruction), mIsParam(aIsParam)
 
679
{
 
680
}