added Info.plist
[TestXSLT.git] / libsablot / src / engine / domprovider.cpp
1 /* 
2  * The contents of this file are subject to the Mozilla Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/MPL/
6  * 
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  * 
12  * The Original Code is the Sablotron XSLT Processor.
13  * 
14  * The Initial Developer of the Original Code is Ginger Alliance Ltd.
15  * Portions created by Ginger Alliance are Copyright (C) 2000-2002
16  * Ginger Alliance Ltd. All Rights Reserved.
17  * 
18  * Contributor(s):
19  * 
20  * Alternatively, the contents of this file may be used under the
21  * terms of the GNU General Public License Version 2 or later (the
22  * "GPL"), in which case the provisions of the GPL are applicable 
23  * instead of those above.  If you wish to allow use of your 
24  * version of this file only under the terms of the GPL and not to
25  * allow others to use your version of this file under the MPL,
26  * indicate your decision by deleting the provisions above and
27  * replace them with the notice and other provisions required by
28  * the GPL.  If you do not delete the provisions above, a recipient
29  * may use your version of this file under either the MPL or the
30  * GPL.
31  */
32
33 #define SablotAsExport
34 #include "sablot.h"
35 #include "domprovider.h"
36 #include "verts.h"
37 #include "tree.h"
38 #include "context.h"
39 #include "proc.h"
40 #include "vars.h"
41 #include "guard.h"
42 #include <string.h>
43
44 /* DOMProvider */
45 void DOMProvider::constructStringValue(SXP_Node n, DStr &result)
46 {
47     switch(getNodeType(n)) {
48     case ATTRIBUTE_NODE:
49     case NAMESPACE_NODE:
50     case PROCESSING_INSTRUCTION_NODE:
51     case COMMENT_NODE:
52     case TEXT_NODE:
53       {
54         const SXP_char* val = getNodeValue(n);
55         if (val)
56           {
57             result += val; 
58             freeValue(n, (char*)val);
59           }
60       }; break;
61     case DOCUMENT_NODE:
62     case ELEMENT_NODE:
63       {
64         for (NodeHandle son = getFirstChild(n); !nhNull(son); son = getNextSibling(son))
65           switch(getNodeType(son)) {
66           case ELEMENT_NODE:
67           case TEXT_NODE:
68             {
69               constructStringValue(son, result);
70             }; break;
71           default:
72             {
73               //nothing
74             }; break;
75           }
76       }; break;
77     }
78 }
79
80 SXP_Node DOMProvider::getFirstChild(SXP_Node n)
81 {
82     return getChildNo(n,0);
83 }
84
85 void DOMProvider::freeName(NodeHandle n, char *buff)
86 {
87   assert(!"abstract DOMProvider::freeName()");
88 }
89
90 void DOMProvider::freeValue(NodeHandle n, char *buff)
91 {
92   assert(!"abstract DOMProvider::freeValue()");
93 }
94
95 eFlag DOMProvider::startCopy(Sit S, NodeHandle n, OutputterObj &outputter)
96 {
97   assert(!"abstract DOMProvider::startCopy()");
98   return OK;
99 }
100
101 eFlag DOMProvider::endCopy(Sit S, NodeHandle n, OutputterObj &outputter)
102 {
103   assert(!"abstract DOMProvider::endCopy()");
104   return OK;
105 }
106
107 eFlag DOMProvider::copyNode(Sit S, NodeHandle n, OutputterObj &outputter)
108 {
109   assert(!"abstract DOMProvider::copyNode()");
110   return OK;
111 }
112
113 eFlag DOMProvider::getMatchingList(Sit S, NodeHandle n, 
114                                   Expression &match, Context &result)
115 {
116   //try itself
117   Context aux(NULL);
118   aux.set(n);
119   Bool yes;
120   E( match.matchesPattern(S, &aux, yes) );
121   if (yes) result.append(n);
122   //iterate the tree
123   SXP_NodeType type;
124   switch ( type = getNodeType(n) ) {
125   case DOCUMENT_NODE:
126   case ELEMENT_NODE:
127     {
128       int num, i;
129       if (type == ELEMENT_NODE) //!!! CHECK
130         {
131           //namespaces
132           num = getNamespaceCount(n);
133           for (i = 0; i < num; i++)
134             getMatchingList(S, getNamespaceNo(n, i), match, result);
135           //attributes
136           num = getAttributeCount(n);
137           for (i = 0; i < num; i++)
138             getMatchingList(S, getAttributeNo(n, i), match, result);
139         }
140       num = getChildCount(n);
141       for (i = 0; i < num; i++)
142         getMatchingList(S, getChildNo(n, i), match, result);
143     }; break;
144   }
145   return OK;  
146 }
147
148 /************************************************************
149 dom provider external
150 ************************************************************/
151 void DOMProviderExternal::getNodeEName(NodeHandle n, EQName &ename)
152 {
153   const char *name, *uri;
154   name = getNodeName(n);
155   char *aux = (char *)strchr(name, ':');
156   if (aux)
157     {
158       *aux = '\0';
159       ename.setPrefix(name);
160       ename.setLocal(aux + 1);
161       *aux = ':';
162     }
163   else
164     {
165       ename.setLocal(name);
166     }
167   ename.setUri(uri = getNodeNameURI(n));
168   freeName(n, (char*)name);
169   freeName(n, (char*)uri);
170 }
171
172 eFlag DOMProviderExternal::startCopy(Sit S, NodeHandle n, 
173                                      OutputterObj &outputter)
174 {
175   switch ( getNodeType(n) ) {
176   case ELEMENT_NODE:
177     {
178       EQName ename;
179       getNodeEName(n, ename);
180       E( outputter.eventElementStart(S, ename) );
181       //copy namespaces
182       int num = getNamespaceCount(n);
183       for (int i = 0; i < num; i++)
184         startCopy(S, getNamespaceNo(n, i), outputter);
185     }; break;
186   case ATTRIBUTE_NODE:
187     {
188       EQName ename;
189       getNodeEName(n, ename);
190       const char *val = getNodeValue(n);
191       E( outputter.eventAttributeStart(S, ename) );
192       E( outputter.eventData(S, val) );
193       E( outputter.eventAttributeEnd(S) );
194       freeValue(n, (char*)val);
195     }; break;
196   case TEXT_NODE:
197     {
198       const char *val = getNodeValue(n);
199       E( outputter.eventData(S, val) );
200       freeValue(n, (char*)val);
201     }; break;
202   case PROCESSING_INSTRUCTION_NODE:
203     {
204       const char *name = getNodeNameLocal(n);
205       const char *val = getNodeValue(n);
206       E( outputter.eventPIStart(S, name) );
207       E( outputter.eventData(S, val) );
208       E( outputter.eventPIEnd(S) );
209       freeName(n, (char*)name);
210       freeValue(n, (char*)val);
211     }; break;
212   case COMMENT_NODE:
213     {
214       const char *val = getNodeValue(n);
215       E( outputter.eventCommentStart(S) );
216       E( outputter.eventData(S, val) );
217       E( outputter.eventCommentEnd(S) );
218       freeValue(n, (char*)val);
219     }; break;
220   case DOCUMENT_NODE:
221     {}; break;
222   case NAMESPACE_NODE:
223     {
224       const char *name = getNodeName(n);
225       const char *val = getNodeValue(n);
226       outputter.eventNamespace(S, name, val);
227       freeName(n, (char*)name);
228       freeValue(n, (char*)val);
229     }; break;
230   }
231   return OK;
232 }
233
234 eFlag DOMProviderExternal::endCopy(Sit S, NodeHandle n, 
235                                    OutputterObj &outputter)
236 {
237   switch ( getNodeType(n) ) {
238   case ELEMENT_NODE:
239     {
240       EQName ename;
241       getNodeEName(n, ename);
242       E( outputter.eventElementEnd(S, ename ));
243     }; break;
244   case ATTRIBUTE_NODE:
245   case TEXT_NODE:
246   case PROCESSING_INSTRUCTION_NODE:
247   case COMMENT_NODE:
248   case DOCUMENT_NODE:
249   case NAMESPACE_NODE:
250     break;
251   }
252   return OK;
253 }
254
255 eFlag DOMProviderExternal::copyNode(Sit S, NodeHandle n, 
256                                     OutputterObj &outputter)
257 {
258   SXP_NodeType type;
259   switch ( type = getNodeType(n) ) {
260   case DOCUMENT_NODE:
261   case ELEMENT_NODE:
262     {
263       int num, i;
264       E( startCopy(S, n, outputter) );
265       //attributes
266       if (type == ELEMENT_NODE)
267         {
268           num = getAttributeCount(n);
269           for (i = 0; i < num; i++)
270             E( copyNode(S, getAttributeNo(n, i), outputter) );
271         }
272       //contents
273       num = getChildCount(n);
274       for (i = 0; i < num; i++)
275         E( copyNode(S, getChildNo(n, i), outputter) );
276       //end
277       E( endCopy(S, n, outputter) );
278     }; break;
279   case ATTRIBUTE_NODE:
280   case TEXT_NODE:
281   case PROCESSING_INSTRUCTION_NODE:
282   case COMMENT_NODE:
283   case NAMESPACE_NODE:
284     {
285       startCopy(S, n, outputter);
286       endCopy(S, n, outputter);
287     }; break;
288   }
289   return OK;
290   return OK;
291 }
292
293 /************************************************************
294 dom provider standard
295 ************************************************************/
296
297 SXP_NodeType DOMProviderStandard::getNodeType(SXP_Node n)
298 {
299     switch(baseType(n))
300     {
301     case VT_ELEMENT: return ELEMENT_NODE;
302     case VT_ATTRIBUTE: return ATTRIBUTE_NODE;
303     case VT_NAMESPACE: return NAMESPACE_NODE;
304     case VT_TEXT: return TEXT_NODE;
305     case VT_COMMENT: return COMMENT_NODE;
306     case VT_PI: return PROCESSING_INSTRUCTION_NODE;
307     case VT_ROOT: return DOCUMENT_NODE;
308     default: 
309       {
310         assert(0); 
311         return (SXP_NodeType)0;
312       }
313     }
314 }
315
316 /*
317                 case EXFF_NAME:
318                     toV(v) -> getOwner().expandQStr(q, strg); break;
319                 case EXFF_LOCAL_NAME:
320                     strg = toV(v) -> getOwner().expand(q.getLocal()); break;
321                 case EXFF_NAMESPACE_URI:
322                     strg = toV(v) -> getOwner().expand(q.getUri()); break;
323 */
324
325 const SXP_char* DOMProviderStandard::getNodeName(SXP_Node n)
326 {
327   Str aux;
328   const QName& q = toV(n) -> getName();
329   toV(n) -> getOwner().expandQStr(q, aux);
330   return aux.cloneData();
331 }
332
333 const SXP_char* DOMProviderStandard::getNodeNameURI(SXP_Node n)
334 {
335   const QName& q = toV(n) -> getName();
336   Str aux = toV(n) -> getOwner().expand(q.getUri());
337   return aux.cloneData();
338 }
339
340 const SXP_char* DOMProviderStandard::getNodeNameLocal(SXP_Node n)
341 {
342   const QName& q = toV(n) -> getName();
343   Str aux = toV(n) -> getOwner().expand(q.getLocal());
344   return aux.cloneData();
345 }
346
347 const SXP_char* DOMProviderStandard::getNodeValue(SXP_Node n)
348 {
349     switch(baseType(n))
350     {
351         case VT_ATTRIBUTE:
352                 return toA(n) -> cont;
353                 case VT_NAMESPACE:
354                 {
355                 return toNS(n) -> getOwner().dict().getKey(toNS(n) -> uri);
356                 };
357                 case VT_PI:
358                 return toPI(n) -> cont;
359                 case VT_COMMENT:
360                     return toComment(n) -> cont;
361                 case VT_TEXT:
362                     return toText(n) -> cont;
363                 default:
364                     return NULL;
365     }
366 }
367
368 SXP_Node DOMProviderStandard::getNextSibling(SXP_Node n)
369 {
370     SXP_Node par = getParent(n);
371     int ndx = toV(n) -> ordinal,
372         count = -1;
373     if (!par) return NULL;
374     if (baseType(n) == VT_ATTRIBUTE || baseType(n) == VT_NAMESPACE)
375       return NULL;
376     count = toD(par) -> contents.number();
377     if (ndx >= count - 1)
378         return NULL;
379     return toD(par) -> contents[ndx + 1];
380 }
381
382 SXP_Node DOMProviderStandard::getPreviousSibling(SXP_Node n)
383 {
384     SXP_Node par = getParent(n);
385     int ndx = toV(n) -> ordinal;
386     if (!par || !ndx) return NULL;
387     if (baseType(n) == VT_ATTRIBUTE || baseType(n) == VT_NAMESPACE)
388         return NULL;
389     return toD(par) -> contents[ndx - 1];
390 }
391
392 SXP_Node DOMProviderStandard::getNextAttrNS(SXP_Node n)
393 {
394     SXP_Node par = getParent(n);
395     int ndx = toV(n) -> ordinal,
396         count = -1;
397     if (!par) return NULL;
398     switch(baseType(n))
399     {
400         case VT_ATTRIBUTE:
401                 count = toE(par) -> atts.number(); break;
402         case VT_NAMESPACE:
403                 count = toE(par) -> namespaces.number(); break;
404                 default:
405                     return NULL;
406     }
407     if (ndx >= count - 1)
408         return NULL;
409     switch(baseType(n))
410     {
411         case VT_ATTRIBUTE:
412                 return toE(par) -> atts[ndx + 1]; break;
413         case VT_NAMESPACE:
414           return toE(par) -> namespaces[ndx + 1]; break;
415     default:
416       // do this to keep compiler happy
417       return NULL;
418     }   
419 }
420
421 SXP_Node DOMProviderStandard::getPreviousAttrNS(SXP_Node n)
422 {
423     SXP_Node par = getParent(n);
424     int ndx = toV(n) -> ordinal;
425     if (!par || !ndx) return NULL;
426     switch(baseType(n))
427     {
428         case VT_ATTRIBUTE:
429                 return toE(par) -> atts[ndx - 1]; break;
430         case VT_NAMESPACE:
431                 return toE(par) -> namespaces[ndx - 1]; break;
432                 default:
433                     return NULL;
434     }   
435 }
436
437 int DOMProviderStandard::getChildCount(SXP_Node n)
438 {
439     if (baseType(n) != VT_ELEMENT && baseType(n) != VT_ROOT)
440         return 0;
441         else
442             return toE(n) -> contents.number();
443 }
444
445 int DOMProviderStandard::getAttributeCount(SXP_Node n)
446 {
447     if (baseType(n) != VT_ELEMENT)
448         return 0;
449         else
450             return toE(n) -> atts.number();
451 }
452
453 int DOMProviderStandard::getNamespaceCount(SXP_Node n)
454 {
455     if (baseType(n) != VT_ELEMENT)
456         return 0;
457         else
458             return toE(n) -> namespaces.number();
459 }
460
461 SXP_Node DOMProviderStandard::getChildNo(SXP_Node n, int ndx)
462 {
463     if (baseType(n) != VT_ELEMENT && baseType(n) != VT_ROOT)
464         return NULL;
465         else
466         {
467             if (ndx < 0 || ndx >= toD(n) -> contents.number())
468                 return NULL;
469                 else
470                 return toD(n) -> contents[ndx];
471         }
472 }
473
474 SXP_Node DOMProviderStandard::getAttributeNo(SXP_Node n, int ndx)
475 {
476     if (baseType(n) != VT_ELEMENT)
477         return NULL;
478         else
479         {
480             if (ndx < 0 || ndx >= toE(n) -> atts.number())
481                 return NULL;
482                 else
483                 return toE(n) -> atts[ndx];
484         }
485 }
486
487 SXP_Node DOMProviderStandard::getNamespaceNo(SXP_Node n, int ndx)
488 {
489     if (baseType(n) != VT_ELEMENT)
490         return NULL;
491         else
492         {
493             if (ndx < 0 || ndx >= toE(n) -> namespaces.number())
494                 return NULL;
495                 else
496                 return toE(n) -> namespaces[ndx];
497     }
498 }
499
500 SXP_Node DOMProviderStandard::getParent(SXP_Node n)
501 {
502     return toV(n) -> parent;
503 }
504
505 SXP_Document DOMProviderStandard::getOwnerDocument(SXP_Node n)
506 {
507     return &(toV(n) -> getOwner().getRoot());
508 }
509
510 int DOMProviderStandard::compareNodes(SXP_Node n1, SXP_Node n2)
511 {
512   if (&(toV(n1) -> getOwner()) == &(toV(n2) -> getOwner()) ) //the same owner
513     {
514       int s1 = toV(n1) -> stamp;
515       int s2 = toV(n2) -> stamp;
516       if (s1 < s2)
517         return -1;
518       if (s1 == s2)
519         return 0;
520       return 1;
521     }
522   else
523     {
524       return strcmp( (char*)(toV(n1) -> getOwner().getURI()),
525                      (char*)(toV(n2) -> getOwner().getURI()) );
526     }
527 }
528
529 SXP_Document DOMProviderStandard::retrieveDocument(const SXP_char* uri, const SXP_char* baseUri)
530 {
531     assert(0);
532     return NULL;
533 }
534
535 SXP_Node DOMProviderStandard::getNodeWithID(SXP_Document doc, const SXP_char* id)
536 {
537     // not reading the DTD, we don't know any ID atts
538     return NULL;
539 }
540
541 /*****************************************/
542 /* universal provider */
543 /*****************************************/
544
545 DOMProviderUniversal::DOMProviderUniversal()
546 {
547   standard = new DOMProviderStandard();
548   external = NULL;
549   maskBit = 0;
550   options = 0;
551 }
552
553 DOMProviderUniversal::~DOMProviderUniversal()
554 {
555   cdelete(standard);
556   if (external) cdelete(external);
557 }
558
559 void DOMProviderUniversal::setExtProvider(DOMHandler *domh, void *data)
560 {
561   if (external) cdelete(external);
562   if (domh)
563     {
564       external = new DOMProviderExternal(domh, data);
565       external -> setSXPMask(maskBit);
566       external -> setOptions(options);
567     }
568   else
569     external = NULL;
570 }
571
572 void DOMProviderUniversal::freeName(NodeHandle n, char *data)
573 {
574   //assert( (NHC(n) & 1) ); //shouldn't happen for internal nodes
575   if ( ( NHC(n) & 1 ) && (options & SXPF_DISPOSE_NAMES) )
576     {
577       NZ(external)->freeName(n, data);
578     }
579 }
580
581 void DOMProviderUniversal::freeValue(NodeHandle n, char *data)
582 {
583   //assert( (NHC(n) & 1) ); //shouldn't happen for internal nodes
584   if ( ( NHC(n) & 1 ) && (options & SXPF_DISPOSE_VALUES) )
585     {
586       NZ(external)->freeValue(n, data);
587     }
588 }
589
590 void DOMProviderUniversal::setMaskBit(int mask)
591 {
592   maskBit = mask;
593   if (external) external -> setSXPMask(mask);
594 }
595
596 int DOMProviderUniversal::getMaskBit()
597 {
598   return maskBit;
599 }
600
601 int DOMProviderUniversal::compareNodes(SXP_Node n1, SXP_Node n2)
602
603   if ((NHC(n1) & 1) ^ (NHC(n2) & 1)) //one external other interal
604     {
605       return NHC(n1) & 1 ? -1 : 1;
606     }
607     
608   return (NHC(n1) & 1) ? 
609     NZ(external)->compareNodes(n1, n2) :
610     standard->compareNodes(n1, n2);
611 }
612
613 SXP_Document DOMProviderUniversal::retrieveDocument(const SXP_char* uri, const SXP_char* baseUri)
614 {
615   if (external)
616     {
617       return external -> retrieveDocument(uri, baseUri);
618     }
619   else
620     return NULL;
621 }
622
623 eFlag DOMProviderUniversal::startCopy(Sit S, NodeHandle n, 
624                                       OutputterObj &outputter)
625 {
626   if ( SXP_EXTERNAL(n) )
627     return external -> startCopy(S, n, outputter);
628   else
629     return toPhysical(n) -> startCopy(S, outputter);
630 }
631
632 eFlag DOMProviderUniversal::endCopy(Sit S, NodeHandle n, 
633                                     OutputterObj &outputter)
634 {
635   if ( SXP_EXTERNAL(n) )
636     return external -> endCopy(S, n, outputter);
637   else
638     return toPhysical(n) -> endCopy(S, outputter);
639 }
640
641 eFlag DOMProviderUniversal::copyNode(Sit S, NodeHandle n, 
642                                      OutputterObj &outputter)
643 {
644   if ( SXP_EXTERNAL(n) )
645     return external -> copyNode(S, n, outputter);
646   else
647     return toPhysical(n) -> copy(S, outputter);
648 }
649
650 /*
651  *
652  *    QueryContextClass
653  *
654  */
655     
656 QueryContextClass::QueryContextClass(Sit S)
657     : theSituation(&S)
658 {
659     baseTree = new Tree((char*)"urn:_external_",FALSE);
660     queryExpression = NULL;
661     resultExpression = NULL;
662     if (NULL == (proc = theSituation -> getProcessor()))
663     {
664         SablotCreateProcessorForSituation(theSituation, (SablotHandle*)&proc);
665         mustKillProc = TRUE;
666     }
667     else
668         mustKillProc = FALSE;
669     NZ(proc) -> initForSXP(baseTree);
670     stringValue = NULL;
671     numberValue = NULL;
672 }
673
674 QueryContextClass::~QueryContextClass()
675 {
676     proc -> cleanupAfterRun(NULL);
677     cdelete(queryExpression);
678     cdelete(resultExpression);
679     cdelete(baseTree);
680     cdelete(stringValue);
681     cdelete(numberValue);
682     if (mustKillProc)
683         cdelete(proc);
684 }
685
686 eFlag QueryContextClass::query(
687     const SXP_char* queryText,
688     SXP_Node n,
689     int contextPosition,
690     int contextSize)
691 {
692     eFlag ecode;
693     //we have to mask the passed-in node handle
694     n = SXP_MASK_LEVEL(n, theSituation->getSXPMaskBit());
695
696     cdelete(queryExpression); // unnecessary but just in case
697     cdelete(resultExpression);
698     cdelete(stringValue);
699     cdelete(numberValue);
700     GP( Tree ) baseTreeNew = new Tree((char*)"", FALSE);
701     queryExpression = new Expression(baseTree -> getRoot());
702     resultExpression = new Expression((*baseTreeNew).getRoot());
703     proc -> initForSXP(baseTree);
704     ecode = queryExpression -> parse(*theSituation, queryText);
705     if (!ecode)
706     {
707       Context c(NULL); //no current node !!!
708       c.setVirtual(n, contextPosition, contextSize);
709       ecode = queryExpression -> eval(*theSituation, *resultExpression, &c);
710     }
711     cdelete(queryExpression);
712     cdelete(baseTree);
713     baseTree = baseTreeNew.keep();
714     proc -> cleanupAfterSXP();
715     return ecode;
716 }
717
718 eFlag QueryContextClass::addVariableBinding(
719     const SXP_char* name, 
720     QueryContextClass &source)
721 {
722     return addVariableExpr(name, source.getExpression_());
723 }
724
725 eFlag QueryContextClass::addVariableExpr(
726     const SXP_char* name, 
727     Expression* value)
728 {
729     QName q;
730     E( baseTree -> getRoot().setLogical(*theSituation, q, (char*)name, TRUE) );
731     E( proc -> vars -> addBinding(*theSituation, q, value, TRUE) );
732     return OK;
733 }
734
735 Expression* QueryContextClass::getNewExpr()
736 {
737     return new Expression(baseTree -> getRoot());
738 }
739
740 eFlag QueryContextClass::addNamespaceDeclaration(
741     const SXP_char* prefix, 
742     const SXP_char* uri)
743 {
744     baseTree -> getRoot().namespaces.append(
745         new(&(baseTree -> getArena())) NmSpace(*baseTree, 
746                     baseTree -> unexpand(prefix),
747                     baseTree -> unexpand(uri),
748                     NSKIND_DECLARED));    
749     return OK;
750 }
751
752 Expression* QueryContextClass::getExpression_() const
753 {
754     return resultExpression;
755 }
756
757 SXP_ExpressionType QueryContextClass::getType()
758 {
759     if (!resultExpression)
760         return SXP_NONE;
761     switch(resultExpression -> type)
762     {
763         case EX_NUMBER: return SXP_NUMBER;
764             case EX_STRING: return SXP_STRING;
765             case EX_BOOLEAN: return SXP_BOOLEAN;
766             case EX_NODESET: return SXP_NODESET;
767             default: return SXP_NONE;
768     }
769 }
770
771 const Number* QueryContextClass::getNumber()
772 {
773     if (!resultExpression)
774         return NULL;
775         else
776         {
777             cdelete(numberValue);
778             numberValue = new Number(resultExpression -> tonumber(*theSituation));
779             return numberValue;
780         }
781 }
782
783 const Str* QueryContextClass::getString()
784 {
785     if (!resultExpression)
786         return NULL;
787         else
788         {
789             if (!stringValue) stringValue = new Str;
790             // should be checked for error
791             resultExpression -> tostring(*theSituation, *stringValue);
792             return stringValue;
793         }
794 }
795
796 Bool QueryContextClass::getBoolean()
797 {
798     if (!resultExpression)
799         return FALSE;
800         else
801             return resultExpression -> tobool();
802 }
803
804 const Context* QueryContextClass::getNodeset()
805 {
806     if (!resultExpression || resultExpression -> type != EX_NODESET)
807         return NULL;
808         else
809             return &(resultExpression -> tonodesetRef());
810 }