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/
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.
12 * The Original Code is the Sablotron XSLT Processor.
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.
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
33 #define SablotAsExport
35 #include "domprovider.h"
45 void DOMProvider::constructStringValue(SXP_Node n, DStr &result)
47 switch(getNodeType(n)) {
50 case PROCESSING_INSTRUCTION_NODE:
54 const SXP_char* val = getNodeValue(n);
58 freeValue(n, (char*)val);
64 for (NodeHandle son = getFirstChild(n); !nhNull(son); son = getNextSibling(son))
65 switch(getNodeType(son)) {
69 constructStringValue(son, result);
80 SXP_Node DOMProvider::getFirstChild(SXP_Node n)
82 return getChildNo(n,0);
85 void DOMProvider::freeName(NodeHandle n, char *buff)
87 assert(!"abstract DOMProvider::freeName()");
90 void DOMProvider::freeValue(NodeHandle n, char *buff)
92 assert(!"abstract DOMProvider::freeValue()");
95 eFlag DOMProvider::startCopy(Sit S, NodeHandle n, OutputterObj &outputter)
97 assert(!"abstract DOMProvider::startCopy()");
101 eFlag DOMProvider::endCopy(Sit S, NodeHandle n, OutputterObj &outputter)
103 assert(!"abstract DOMProvider::endCopy()");
107 eFlag DOMProvider::copyNode(Sit S, NodeHandle n, OutputterObj &outputter)
109 assert(!"abstract DOMProvider::copyNode()");
113 eFlag DOMProvider::getMatchingList(Sit S, NodeHandle n,
114 Expression &match, Context &result)
120 E( match.matchesPattern(S, &aux, yes) );
121 if (yes) result.append(n);
124 switch ( type = getNodeType(n) ) {
129 if (type == ELEMENT_NODE) //!!! CHECK
132 num = getNamespaceCount(n);
133 for (i = 0; i < num; i++)
134 getMatchingList(S, getNamespaceNo(n, i), match, result);
136 num = getAttributeCount(n);
137 for (i = 0; i < num; i++)
138 getMatchingList(S, getAttributeNo(n, i), match, result);
140 num = getChildCount(n);
141 for (i = 0; i < num; i++)
142 getMatchingList(S, getChildNo(n, i), match, result);
148 /************************************************************
149 dom provider external
150 ************************************************************/
151 void DOMProviderExternal::getNodeEName(NodeHandle n, EQName &ename)
153 const char *name, *uri;
154 name = getNodeName(n);
155 char *aux = (char *)strchr(name, ':');
159 ename.setPrefix(name);
160 ename.setLocal(aux + 1);
165 ename.setLocal(name);
167 ename.setUri(uri = getNodeNameURI(n));
168 freeName(n, (char*)name);
169 freeName(n, (char*)uri);
172 eFlag DOMProviderExternal::startCopy(Sit S, NodeHandle n,
173 OutputterObj &outputter)
175 switch ( getNodeType(n) ) {
179 getNodeEName(n, ename);
180 E( outputter.eventElementStart(S, ename) );
182 int num = getNamespaceCount(n);
183 for (int i = 0; i < num; i++)
184 startCopy(S, getNamespaceNo(n, i), outputter);
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);
198 const char *val = getNodeValue(n);
199 E( outputter.eventData(S, val) );
200 freeValue(n, (char*)val);
202 case PROCESSING_INSTRUCTION_NODE:
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);
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);
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);
234 eFlag DOMProviderExternal::endCopy(Sit S, NodeHandle n,
235 OutputterObj &outputter)
237 switch ( getNodeType(n) ) {
241 getNodeEName(n, ename);
242 E( outputter.eventElementEnd(S, ename ));
246 case PROCESSING_INSTRUCTION_NODE:
255 eFlag DOMProviderExternal::copyNode(Sit S, NodeHandle n,
256 OutputterObj &outputter)
259 switch ( type = getNodeType(n) ) {
264 E( startCopy(S, n, outputter) );
266 if (type == ELEMENT_NODE)
268 num = getAttributeCount(n);
269 for (i = 0; i < num; i++)
270 E( copyNode(S, getAttributeNo(n, i), outputter) );
273 num = getChildCount(n);
274 for (i = 0; i < num; i++)
275 E( copyNode(S, getChildNo(n, i), outputter) );
277 E( endCopy(S, n, outputter) );
281 case PROCESSING_INSTRUCTION_NODE:
285 startCopy(S, n, outputter);
286 endCopy(S, n, outputter);
293 /************************************************************
294 dom provider standard
295 ************************************************************/
297 SXP_NodeType DOMProviderStandard::getNodeType(SXP_Node n)
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;
311 return (SXP_NodeType)0;
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;
325 const SXP_char* DOMProviderStandard::getNodeName(SXP_Node n)
328 const QName& q = toV(n) -> getName();
329 toV(n) -> getOwner().expandQStr(q, aux);
330 return aux.cloneData();
333 const SXP_char* DOMProviderStandard::getNodeNameURI(SXP_Node n)
335 const QName& q = toV(n) -> getName();
336 Str aux = toV(n) -> getOwner().expand(q.getUri());
337 return aux.cloneData();
340 const SXP_char* DOMProviderStandard::getNodeNameLocal(SXP_Node n)
342 const QName& q = toV(n) -> getName();
343 Str aux = toV(n) -> getOwner().expand(q.getLocal());
344 return aux.cloneData();
347 const SXP_char* DOMProviderStandard::getNodeValue(SXP_Node n)
352 return toA(n) -> cont;
355 return toNS(n) -> getOwner().dict().getKey(toNS(n) -> uri);
358 return toPI(n) -> cont;
360 return toComment(n) -> cont;
362 return toText(n) -> cont;
368 SXP_Node DOMProviderStandard::getNextSibling(SXP_Node n)
370 SXP_Node par = getParent(n);
371 int ndx = toV(n) -> ordinal,
373 if (!par) return NULL;
374 if (baseType(n) == VT_ATTRIBUTE || baseType(n) == VT_NAMESPACE)
376 count = toD(par) -> contents.number();
377 if (ndx >= count - 1)
379 return toD(par) -> contents[ndx + 1];
382 SXP_Node DOMProviderStandard::getPreviousSibling(SXP_Node n)
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)
389 return toD(par) -> contents[ndx - 1];
392 SXP_Node DOMProviderStandard::getNextAttrNS(SXP_Node n)
394 SXP_Node par = getParent(n);
395 int ndx = toV(n) -> ordinal,
397 if (!par) return NULL;
401 count = toE(par) -> atts.number(); break;
403 count = toE(par) -> namespaces.number(); break;
407 if (ndx >= count - 1)
412 return toE(par) -> atts[ndx + 1]; break;
414 return toE(par) -> namespaces[ndx + 1]; break;
416 // do this to keep compiler happy
421 SXP_Node DOMProviderStandard::getPreviousAttrNS(SXP_Node n)
423 SXP_Node par = getParent(n);
424 int ndx = toV(n) -> ordinal;
425 if (!par || !ndx) return NULL;
429 return toE(par) -> atts[ndx - 1]; break;
431 return toE(par) -> namespaces[ndx - 1]; break;
437 int DOMProviderStandard::getChildCount(SXP_Node n)
439 if (baseType(n) != VT_ELEMENT && baseType(n) != VT_ROOT)
442 return toE(n) -> contents.number();
445 int DOMProviderStandard::getAttributeCount(SXP_Node n)
447 if (baseType(n) != VT_ELEMENT)
450 return toE(n) -> atts.number();
453 int DOMProviderStandard::getNamespaceCount(SXP_Node n)
455 if (baseType(n) != VT_ELEMENT)
458 return toE(n) -> namespaces.number();
461 SXP_Node DOMProviderStandard::getChildNo(SXP_Node n, int ndx)
463 if (baseType(n) != VT_ELEMENT && baseType(n) != VT_ROOT)
467 if (ndx < 0 || ndx >= toD(n) -> contents.number())
470 return toD(n) -> contents[ndx];
474 SXP_Node DOMProviderStandard::getAttributeNo(SXP_Node n, int ndx)
476 if (baseType(n) != VT_ELEMENT)
480 if (ndx < 0 || ndx >= toE(n) -> atts.number())
483 return toE(n) -> atts[ndx];
487 SXP_Node DOMProviderStandard::getNamespaceNo(SXP_Node n, int ndx)
489 if (baseType(n) != VT_ELEMENT)
493 if (ndx < 0 || ndx >= toE(n) -> namespaces.number())
496 return toE(n) -> namespaces[ndx];
500 SXP_Node DOMProviderStandard::getParent(SXP_Node n)
502 return toV(n) -> parent;
505 SXP_Document DOMProviderStandard::getOwnerDocument(SXP_Node n)
507 return &(toV(n) -> getOwner().getRoot());
510 int DOMProviderStandard::compareNodes(SXP_Node n1, SXP_Node n2)
512 if (&(toV(n1) -> getOwner()) == &(toV(n2) -> getOwner()) ) //the same owner
514 int s1 = toV(n1) -> stamp;
515 int s2 = toV(n2) -> stamp;
524 return strcmp( (char*)(toV(n1) -> getOwner().getURI()),
525 (char*)(toV(n2) -> getOwner().getURI()) );
529 SXP_Document DOMProviderStandard::retrieveDocument(const SXP_char* uri, const SXP_char* baseUri)
535 SXP_Node DOMProviderStandard::getNodeWithID(SXP_Document doc, const SXP_char* id)
537 // not reading the DTD, we don't know any ID atts
541 /*****************************************/
542 /* universal provider */
543 /*****************************************/
545 DOMProviderUniversal::DOMProviderUniversal()
547 standard = new DOMProviderStandard();
553 DOMProviderUniversal::~DOMProviderUniversal()
556 if (external) cdelete(external);
559 void DOMProviderUniversal::setExtProvider(DOMHandler *domh, void *data)
561 if (external) cdelete(external);
564 external = new DOMProviderExternal(domh, data);
565 external -> setSXPMask(maskBit);
566 external -> setOptions(options);
572 void DOMProviderUniversal::freeName(NodeHandle n, char *data)
574 //assert( (NHC(n) & 1) ); //shouldn't happen for internal nodes
575 if ( ( NHC(n) & 1 ) && (options & SXPF_DISPOSE_NAMES) )
577 NZ(external)->freeName(n, data);
581 void DOMProviderUniversal::freeValue(NodeHandle n, char *data)
583 //assert( (NHC(n) & 1) ); //shouldn't happen for internal nodes
584 if ( ( NHC(n) & 1 ) && (options & SXPF_DISPOSE_VALUES) )
586 NZ(external)->freeValue(n, data);
590 void DOMProviderUniversal::setMaskBit(int mask)
593 if (external) external -> setSXPMask(mask);
596 int DOMProviderUniversal::getMaskBit()
601 int DOMProviderUniversal::compareNodes(SXP_Node n1, SXP_Node n2)
603 if ((NHC(n1) & 1) ^ (NHC(n2) & 1)) //one external other interal
605 return NHC(n1) & 1 ? -1 : 1;
608 return (NHC(n1) & 1) ?
609 NZ(external)->compareNodes(n1, n2) :
610 standard->compareNodes(n1, n2);
613 SXP_Document DOMProviderUniversal::retrieveDocument(const SXP_char* uri, const SXP_char* baseUri)
617 return external -> retrieveDocument(uri, baseUri);
623 eFlag DOMProviderUniversal::startCopy(Sit S, NodeHandle n,
624 OutputterObj &outputter)
626 if ( SXP_EXTERNAL(n) )
627 return external -> startCopy(S, n, outputter);
629 return toPhysical(n) -> startCopy(S, outputter);
632 eFlag DOMProviderUniversal::endCopy(Sit S, NodeHandle n,
633 OutputterObj &outputter)
635 if ( SXP_EXTERNAL(n) )
636 return external -> endCopy(S, n, outputter);
638 return toPhysical(n) -> endCopy(S, outputter);
641 eFlag DOMProviderUniversal::copyNode(Sit S, NodeHandle n,
642 OutputterObj &outputter)
644 if ( SXP_EXTERNAL(n) )
645 return external -> copyNode(S, n, outputter);
647 return toPhysical(n) -> copy(S, outputter);
656 QueryContextClass::QueryContextClass(Sit S)
659 baseTree = new Tree((char*)"urn:_external_",FALSE);
660 queryExpression = NULL;
661 resultExpression = NULL;
662 if (NULL == (proc = theSituation -> getProcessor()))
664 SablotCreateProcessorForSituation(theSituation, (SablotHandle*)&proc);
668 mustKillProc = FALSE;
669 NZ(proc) -> initForSXP(baseTree);
674 QueryContextClass::~QueryContextClass()
676 proc -> cleanupAfterRun(NULL);
677 cdelete(queryExpression);
678 cdelete(resultExpression);
680 cdelete(stringValue);
681 cdelete(numberValue);
686 eFlag QueryContextClass::query(
687 const SXP_char* queryText,
693 //we have to mask the passed-in node handle
694 n = SXP_MASK_LEVEL(n, theSituation->getSXPMaskBit());
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);
707 Context c(NULL); //no current node !!!
708 c.setVirtual(n, contextPosition, contextSize);
709 ecode = queryExpression -> eval(*theSituation, *resultExpression, &c);
711 cdelete(queryExpression);
713 baseTree = baseTreeNew.keep();
714 proc -> cleanupAfterSXP();
718 eFlag QueryContextClass::addVariableBinding(
719 const SXP_char* name,
720 QueryContextClass &source)
722 return addVariableExpr(name, source.getExpression_());
725 eFlag QueryContextClass::addVariableExpr(
726 const SXP_char* name,
730 E( baseTree -> getRoot().setLogical(*theSituation, q, (char*)name, TRUE) );
731 E( proc -> vars -> addBinding(*theSituation, q, value, TRUE) );
735 Expression* QueryContextClass::getNewExpr()
737 return new Expression(baseTree -> getRoot());
740 eFlag QueryContextClass::addNamespaceDeclaration(
741 const SXP_char* prefix,
744 baseTree -> getRoot().namespaces.append(
745 new(&(baseTree -> getArena())) NmSpace(*baseTree,
746 baseTree -> unexpand(prefix),
747 baseTree -> unexpand(uri),
752 Expression* QueryContextClass::getExpression_() const
754 return resultExpression;
757 SXP_ExpressionType QueryContextClass::getType()
759 if (!resultExpression)
761 switch(resultExpression -> type)
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;
771 const Number* QueryContextClass::getNumber()
773 if (!resultExpression)
777 cdelete(numberValue);
778 numberValue = new Number(resultExpression -> tonumber(*theSituation));
783 const Str* QueryContextClass::getString()
785 if (!resultExpression)
789 if (!stringValue) stringValue = new Str;
790 // should be checked for error
791 resultExpression -> tostring(*theSituation, *stringValue);
796 Bool QueryContextClass::getBoolean()
798 if (!resultExpression)
801 return resultExpression -> tobool();
804 const Context* QueryContextClass::getNodeset()
806 if (!resultExpression || resultExpression -> type != EX_NODESET)
809 return &(resultExpression -> tonodesetRef());