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 /* sdom.cpp */
34
35 #define SablotAsExport
36 #include "sdom.h"
37
38 #ifdef ENABLE_DOM
39
40 #include "base.h"
41 #include "verts.h"
42 #include "tree.h"
43 #include "context.h"
44 #include "guard.h"
45 #include "platform.h"
46
47 #define getTmpList(v) (toV(v) -> getOwner().tmpList)
48
49 char* SDOM_ExceptionMsg[] =
50 {
51 // SDOM_OK
52 (char *) "OK",
53
54 // SDOM_INDEX_SIZE_ERR 1
55 (char *) "list index out of bounds",
56
57 // SDOM_DOMSTRING_SIZE_ERR 2
58 (char *) "invalid size of string",
59
60 // SDOM_HIERARCHY_REQUEST_ERR 3
61 (char *) "hierarchy request error",
62
63 // SDOM_WRONG_DOCUMENT_ERR 4
64 (char *) "node used in a document that did not create it",
65
66 // SDOM_INVALID_CHARACTER_ERR 5
67 (char *) "invalid character in string",
68
69 // SDOM_NO_DATA_ALLOWED_ERR 6
70 (char *) "data not allowed",
71
72 // SDOM_NO_MODIFICATION_ALLOWED_ERR 7
73 (char *) "modification not allowed",
74
75 // SDOM_NOT_FOUND_ERR 8
76 (char *) "reference to a non-existent node",
77
78 // SDOM_NOT_FOUND_ERR 9
79 (char *) "functionality not supported",
80
81 // SDOM_INUSE_ATTRIBUTE_ERR 10
82 (char *) "attribute is inuse",
83
84 // SDOM_NOT_FOUND_ERR 10
85 (char *) "attribute is inuse",
86
87 // SDOM_INVALID_STATE_ERR 11
88 (char *) "invalid state",
89
90 // SDOM_SYNTAX_ERR 12
91 (char *) "syntax error",
92
93 // SDOM_INVALID_MODIFICATION_ERR 13
94 (char *) "invalid modification",
95
96 // SDOM_NAMESPACE_ERR 14
97 (char *) "namespace error",
98
99 // SDOM_INVALID_ACCESS_ERR 15
100 (char *) "invalid access",
101
102 // INVALID_NODE_TYPE
103 (char *) "invalid node type",
104
105 // SDOM_QUERY_PARSE_ERR
106 (char *) "query parsing error",
107
108 // SDOM_QUERY_EXECUTION_ERR
109 (char *) "query execution error",
110
111 // SDOM_NOT_OK
112 (char *) "general exception"
113 };
114
115 #define SDOM_Err(SITUA, CODE) { SIT( SITUA ).setSDOMExceptionCode( CODE );\
116 SIT( SITUA ).message(\
117 MT_ERROR, E2_SDOM, CODE, SDOM_ExceptionMsg[CODE]); return CODE; }
118
119 #define SE(statement) {SDOM_Exception code__ = statement; \
120 if (code__) return code__;}
121
122 #define SIT(PTR) (*(Situation*)PTR)
123
124 #define isXMLNS_(qn, resolver) \
125 (qn.getPrefix() == resolver -> getOwner().stdPhrase(PHRASE_XMLNS) || \
126 (qn.getPrefix() == UNDEF_PHRASE && \
127 qn.getLocal() == resolver -> getOwner().stdPhrase(PHRASE_XMLNS)))
128
129 //
130 // globals
131 //
132
133 SDOM_NodeCallback* theDisposeCallback = NULL;
134 #define ownerDoc(NODE) ( &(toV(NODE)->getOwner().getRoot()) )
135
SDOM_newString(const Str & strg)136 char* SDOM_newString(const Str& strg)
137 {
138 int len = strg.length();
139 char *p = new char[len + 1];
140 strcpy(p, (char*)(const char*)strg);
141 p[len] = 0;
142 return p;
143 }
144
145 //_JP_ v
146 // helper functions for namespace handling
___SDOM_swallowParentNSrec(SablotSituation s,SDOM_Node n,Tree * t,NSList * parentNs)147 SDOM_Exception ___SDOM_swallowParentNSrec(SablotSituation s, SDOM_Node n, Tree* t, NSList* parentNs)
148 {
149 // inherits from parentNs to begin of n->namespaces with respect to scoping
150 // do it recursively for all child elements
151 if ( isElement(toV(n)) ) {
152 NSList* currentNs = &(toE(n) -> namespaces);
153 NmSpace* nm;
154 const int imax = parentNs->number() - 1;
155 for (int i = imax; i >= 0; i--) {
156 nm = toNS((*parentNs)[i]);
157 if (currentNs -> findNdx(nm -> prefix) == -1) {
158 nm = new(&(NZ(t) -> getArena())) NmSpace(*t, nm -> prefix, nm -> uri,
159 NSKIND_PARENT);
160 currentNs -> append(toV(nm));
161 nm -> parent = toV(n);
162 };
163 };
164 //zero in args => all appended namespaces will have kind == NSKIND_PARENT
165 //parentNs->giveCurrent(SIT(s), *currentNs, t, 0);
166 SDOM_Node checkedNode;
167 SE( SDOM_getFirstChild(s, n, &checkedNode) );
168 while (checkedNode) {
169 SE( ___SDOM_swallowParentNSrec(s, checkedNode, t, currentNs) );
170 SE( SDOM_getNextSibling(s, checkedNode, &checkedNode) );
171 };
172 };
173 return SDOM_OK;
174 }
175
__SDOM_swallowParentNS(SablotSituation s,SDOM_Node n)176 SDOM_Exception __SDOM_swallowParentNS(SablotSituation s, SDOM_Node n)
177 {
178 // inherits from parent's NSList to begin of n->namespaces with respect to scoping
179 // do it recursively for all child elements
180 if ( n && isElement(toV(n)) && toE(n) -> parent ) {
181 NSList* parentNs = &(toE(toE(n) -> parent) -> namespaces);
182 Tree* t = toTree(ownerDoc(toE(n)));
183 SE( ___SDOM_swallowParentNSrec(s, n, t, parentNs) );
184 };
185 return SDOM_OK;
186 }
187
__SDOM_dropParentNS(SablotSituation s,SDOM_Node n)188 SDOM_Exception __SDOM_dropParentNS(SablotSituation s, SDOM_Node n)
189 {
190 // removes inherited namespaces from n->namespaces
191 // and from all child elements recursively
192 if ( n && isElement(toV(n)) ) {
193 NSList *checkedNs = &(toE(n) -> namespaces);
194 NmSpace *nm;
195 const int imax = checkedNs->number() - 1;
196 for (int i = imax; i >= 0; i--) {
197 nm = toNS((*checkedNs)[i]);
198 if ( nm -> usageCount == 0 && nm -> kind == NSKIND_PARENT ) {
199 checkedNs->rm(i);
200 nm -> parent = NULL;
201 //getTmpList(toE(n)).append(nm);
202 delete nm;
203 };
204 };
205 SDOM_Node checkedNode;
206 SE( SDOM_getFirstChild(s, n, &checkedNode) );
207 while (checkedNode) {
208 SE( __SDOM_dropParentNS(s, checkedNode) );
209 SE( SDOM_getNextSibling(s, checkedNode, &checkedNode) );
210 };
211 };
212 return SDOM_OK;
213 }
214
__SDOM_refreshNS(SablotSituation s,SDOM_Node n,NmSpace * nmspace)215 SDOM_Exception __SDOM_refreshNS(SablotSituation s, SDOM_Node n, NmSpace* nmspace)
216 {
217 // appends or changes nmspace in all child elements recursively
218 // with respect to scoping
219 SDOM_Node checkedNode;
220 Tree *t;
221 NmSpace *nm;
222 SE( SDOM_getFirstChild(s, n, &checkedNode) );
223 while (checkedNode) {
224 if ( isElement(checkedNode) ) {
225 nm = toE(checkedNode) -> namespaces.find(nmspace -> prefix);
226 if ( nm ) {
227 if ( nm -> usageCount == 0 && nm -> kind == NSKIND_PARENT ) {
228 nm -> uri = nmspace -> uri;
229 SE( __SDOM_refreshNS(s, checkedNode, nmspace) );
230 };
231 } else {
232 //t = toTree(ownerDoc(toE(n)));
233 t = &(toE(n) -> getOwner());
234 nm = new(&(t -> getArena())) NmSpace(*t, nmspace -> prefix,
235 nmspace -> uri,
236 NSKIND_PARENT);
237 toE(checkedNode) -> namespaces.append(nm);
238 nm -> setParent(toE(checkedNode));
239 SE( __SDOM_refreshNS(s, checkedNode, nmspace) );
240 };
241 };
242 SE( SDOM_getNextSibling(s, checkedNode, &checkedNode) );
243 };
244 return SDOM_OK;
245 }
246
__SDOM_canChangeUriNS(SablotSituation s,SDOM_Node n,NmSpace * nmspace,const SDOM_char * uri)247 SDOM_Exception __SDOM_canChangeUriNS(SablotSituation s, SDOM_Node n, NmSpace* nmspace, const SDOM_char *uri)
248 {
249 // order of tests has meaning
250 if ( !n || nmspace->usageCount == 0 )
251 // namespace without parent is changeable
252 // not used namespace is changeable
253 return SDOM_OK;
254
255 Str olduri = toV(nmspace)->getOwner().expand(nmspace->uri);
256 if ( !strcmp((char*)olduri,(char*)uri) )
257 return SDOM_OK;// no change will be done
258
259 return SDOM_NAMESPACE_ERR;
260 }
261
262
__SDOM_touchNS(SablotSituation s,SDOM_Node n,Phrase prefix,Phrase uri,NsKind kind,unsigned int maxUsageCount)263 SDOM_Exception __SDOM_touchNS(SablotSituation s, SDOM_Node n, Phrase prefix, Phrase uri, NsKind kind, unsigned int maxUsageCount)
264 {
265 //appends or changes n.namespaces to push prefix:uri into scope
266 //potentially refreshes childrens' namespaces
267 //suppose if kind == NSKIND_DECLARED then nm will NOT be immediatelly used
268 //suppose if kind == NSKIND_PARENT then nm will be immediatelly used
269 NmSpace *nm = toE(n)->namespaces.find(prefix);
270 if (nm) {
271 //nm->prefix == prefix
272 if (nm->uri == uri) {
273 if (kind == NSKIND_PARENT) nm -> usageCount++;
274 else nm -> kind = kind;
275 } else {
276 if ( kind == NSKIND_PARENT ) {
277 if (nm -> kind == NSKIND_PARENT && nm -> usageCount <= maxUsageCount) {
278 nm -> uri = uri;
279 return __SDOM_refreshNS(s, n, nm);
280 } else {
281 return SDOM_NAMESPACE_ERR;//_JP_ not in spec - namespace collision
282 };
283 } else {
284 if (nm -> usageCount <= maxUsageCount) {
285 nm -> kind = kind;
286 nm -> uri = uri;
287 return __SDOM_refreshNS(s, n, nm);
288 } else {
289 return SDOM_NAMESPACE_ERR;//_JP_ not in spec - namespace collision
290 };
291 };
292 };
293 } else {
294 //nm with prefix not exists
295 //!!chybka
296 //Tree *auxt = NZ(toTree(ownerDoc(toE(n))));
297 Tree *auxt = &(toE(n) -> getOwner());
298 nm = new(&(auxt -> getArena()))
299 NmSpace(toE(n) -> getOwner(),prefix, uri, kind);
300 if (kind == NSKIND_PARENT) nm -> usageCount = 1;
301 toE(n) -> namespaces.append(nm);
302 toV(nm) -> setParent(toE(n));
303 };
304 return SDOM_OK;
305 }
306
307
__SDOM_touchNSByChar(SablotSituation s,SDOM_Node n,SDOM_char * prefix,SDOM_char * uri,NsKind kind,int maxUsageCount)308 SDOM_Exception __SDOM_touchNSByChar(SablotSituation s, SDOM_Node n, SDOM_char* prefix, SDOM_char* uri, NsKind kind, int maxUsageCount)
309 {
310 //appends or changes n.namespaces to push prefix:uri into scope
311 //potentially refreshes childrens' namespaces
312 Phrase ph_prefix = prefix && strcmp((char*)prefix,"xmlns") ? toE(ownerDoc(toE(n)))->dict().insert((const char*)prefix) : UNDEF_PHRASE;
313 Phrase ph_uri = uri ? toE(ownerDoc(toE(n)))->dict().insert((const char*)uri) : UNDEF_PHRASE;
314 return __SDOM_touchNS(s, n, ph_prefix, ph_uri, kind, maxUsageCount);
315 }
316
317
318 //_JP_ ^
319
320
SDOM_createElement(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * tagName)321 SDOM_Exception SDOM_createElement(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *tagName)
322 {
323 QName q;
324 //try to find the document element
325 Element *e = NULL;
326 for (int i = 0; i < toRoot(d) -> contents.number(); i++)
327 {
328 if (isElement(toRoot(d) -> contents[i]))
329 {
330 e = toE(toRoot(d) -> contents[i]);
331 break;
332 }
333 }
334 if (!e) e = toRoot(d);
335
336 e -> setLogical(SIT(s), q, tagName, TRUE);
337 *pn = new(&(toTree(d) -> getArena())) Element(*toTree(d), q);
338 //_TH_ v
339 getTmpList(d).append(*pn);
340 //_TH_ ^
341 return SDOM_OK;
342 }
343
344 //_JP_ v
SDOM_createElementNS(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * uri,const SDOM_char * qName)345 SDOM_Exception SDOM_createElementNS(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *uri, const SDOM_char *qName)
346 {
347 if ( !isValidQName((char*)qName) )
348 return SDOM_INVALID_CHARACTER_ERR;
349
350 Str prefix = Str();
351 const char *colon = strchr((char*)qName,':');
352 QName q;
353
354 if ( colon ) { //qName has prefix
355
356 if ( !uri )
357 return SDOM_NAMESPACE_ERR;
358
359 prefix.nset((char*)qName, intPtrDiff(colon, qName));
360
361 if ( !strcmp((const char*)prefix,"xml") && strcmp(theXMLNamespace,uri) )
362 //redefinition of xml-namespace
363 return SDOM_NAMESPACE_ERR;
364
365 q.setPrefix(toE(d)->dict().insert((const char*)prefix));
366 q.setLocal(toE(d)->dict().insert((const char*)((ptrdiff_t)colon + 1)));
367 q.setUri(toE(d)->dict().insert((const char*)uri));
368
369 } else {
370
371 q.setPrefix(UNDEF_PHRASE);
372 q.setLocal(toE(d)->dict().insert((const char*)qName));
373
374 if ( uri && strcmp((char*)uri,"") ) {
375 q.setUri(toE(d)->dict().insert((const char*)uri));
376 } else {
377 q.setUri(UNDEF_PHRASE);
378 };
379 };
380
381 *pn = new(&(toTree(d) -> getArena())) Element(*toTree(d), q);
382 // no parent, no childs, no attributes => only 1 namespace:
383 NmSpace* newNS = new(&(toTree(d) -> getArena())) NmSpace(*toTree(d),
384 q.getPrefix(),
385 q.getUri(),
386 NSKIND_DECLARED);
387 newNS -> usageCount = 1;
388 toE(*pn) -> namespaces.append(newNS);
389 toV(newNS) -> setParent(toE(*pn));
390 //_TH_ v
391 getTmpList(d).append(*pn);
392 //_TH_ ^
393 return SDOM_OK;
394 }
395 //_JP_ ^
396
_SDOM_createAttributeWithParent(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * name,SDOM_Node parent)397 SDOM_Exception _SDOM_createAttributeWithParent(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *name, SDOM_Node parent)
398 {
399 QName q;
400 //_JP_ v
401 // uses parent's NSList, if exists
402 if ( parent )
403 toE(parent) -> setLogical(SIT(s), q, name, FALSE);
404 else
405 toRoot(d) -> setLogical(SIT(s), q, name, FALSE);
406 //_JP_ ^
407 if ( !isXMLNS_(q, toRoot(d)) ) {
408 *pn = new(&(toTree(d) -> getArena()))
409 Attribute(*toTree(d), q, (char*)"", XSLA_NONE);
410 if (parent)
411 toE(parent)->namespaces.incPrefixUsage(q.getPrefix());
412 } else
413 *pn = new(&(toTree(d) -> getArena()))
414 NmSpace(*toTree(d),
415 q.getPrefix() == UNDEF_PHRASE ? UNDEF_PHRASE : q.getLocal(),
416 UNDEF_PHRASE,
417 NSKIND_DECLARED);
418 //_TH_ v
419 getTmpList(d).append(*pn);
420 //_TH_ ^
421 return SDOM_OK;
422 }
423
SDOM_createAttribute(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * name)424 SDOM_Exception SDOM_createAttribute(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *name)
425 {
426 return _SDOM_createAttributeWithParent(s, d, pn, name, NULL);
427 }
428
429 //_JP_ v
SDOM_createAttributeNS(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * uri,const SDOM_char * qName)430 SDOM_Exception SDOM_createAttributeNS(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *uri, const SDOM_char *qName)
431 {
432 if ( !isValidQName((char*)qName) )
433 return SDOM_INVALID_CHARACTER_ERR;
434
435 Str prefix = Str();
436 const char *colon = strchr((char*)qName,':');
437 QName q;
438
439 if ( colon ) { //qName has prefix
440
441 if ( !uri )
442 return SDOM_NAMESPACE_ERR;
443
444 prefix.nset((char*)qName, intPtrDiff(colon, qName));
445
446 if ( !strcmp((const char*)prefix,"xml") && strcmp(theXMLNamespace,uri) )
447 //redefinition of xml namespace
448 return SDOM_NAMESPACE_ERR;
449
450 if ( !strcmp((const char*)prefix,"xmlns") && strcmp(theXMLNSNamespace,uri) )
451 //redefinition of xmlns namespace
452 return SDOM_NAMESPACE_ERR;
453
454 q.setPrefix(toE(d)->dict().insert((const char*)prefix));
455 q.setLocal(toE(d)->dict().insert((const char*)((ptrdiff_t)colon + 1)));
456 q.setUri(toE(d)->dict().insert((const char*)uri));
457
458 } else {
459
460 q.setPrefix(UNDEF_PHRASE);
461 q.setLocal(toE(d)->dict().insert((const char*)qName));
462 if ( uri && strcmp((char*)uri,"") ) {
463 q.setUri(toE(d)->dict().insert((const char*)uri));
464 } else {
465 q.setUri(UNDEF_PHRASE);
466 };
467 };
468
469 if ( !isXMLNS_(q, toRoot(d)) )
470 *pn = new(&(toTree(d) -> getArena()))
471 Attribute(*toTree(d), q, (char*)"", XSLA_NONE);
472 else
473 *pn = new(&(toTree(d) -> getArena()))
474 NmSpace(*toTree(d),
475 q.getLocal(),
476 UNDEF_PHRASE,
477 NSKIND_DECLARED);
478
479 //_TH_ v
480 getTmpList(d).append(*pn);
481 //_TH_ ^
482 return SDOM_OK;
483 }
484 //_JP_ ^
485
SDOM_createTextNode(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * data)486 SDOM_Exception SDOM_createTextNode(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *data)
487 {
488 *pn = new(&(toTree(d) -> getArena())) Text(*toTree(d), (char*) data);
489 //_TH_ v
490 getTmpList(d).append(*pn);
491 //_TH_ ^
492 return SDOM_OK;
493 }
494
SDOM_createCDATASection(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * data)495 SDOM_Exception SDOM_createCDATASection(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *data)
496 {
497 SE( SDOM_createTextNode(s, d, pn, data) );
498 toText(toV(*pn)) -> beCDATA();
499 return SDOM_OK;
500 }
501
SDOM_createComment(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * data)502 SDOM_Exception SDOM_createComment(
503 SablotSituation s,
504 SDOM_Document d,
505 SDOM_Node *pn,
506 const SDOM_char *data)
507 {
508 *pn = new(&(toTree(d) -> getArena())) Comment(*toTree(d), (char*) data);
509 //_TH_ v
510 getTmpList(d).append(*pn);
511 //_TH_ ^
512 return SDOM_OK;
513 }
514
SDOM_createProcessingInstruction(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * target,const SDOM_char * data)515 SDOM_Exception SDOM_createProcessingInstruction(
516 SablotSituation s,
517 SDOM_Document d,
518 SDOM_Node *pn,
519 const SDOM_char *target,
520 const SDOM_char *data)
521 {
522 *pn = new(&(toTree(d) -> getArena())) ProcInstr(
523 *toTree(d),
524 toTree(d) -> unexpand((char*) target),
525 (char*) data);
526 //_TH_ v
527 getTmpList(d).append(*pn);
528 //_TH_ ^
529 return SDOM_OK;
530 }
531
SDOM_disposeNode(SablotSituation s,SDOM_Node n)532 SDOM_Exception SDOM_disposeNode(SablotSituation s, SDOM_Node n)
533 {
534 Vertex *v = toV(n);
535 switch(v -> vt & VT_BASE)
536 {
537 case VT_ELEMENT:
538 ccdelete(v, toE(v)); break;
539 case VT_ATTRIBUTE:
540 ccdelete(v, toA(v)); break;
541 case VT_NAMESPACE:
542 ccdelete(v, toNS(v)); break;
543 case VT_PI:
544 ccdelete(v, toPI(v)); break;
545 case VT_TEXT: // and CDATA
546 ccdelete(v, toText(v)); break;
547 case VT_XSL:
548 ccdelete(v, toX(v)); break;
549 case VT_COMMENT:
550 ccdelete(v, toComment(v)); break;
551 default:
552 sabassert(!"disposeSDOM_Node");
553 }
554 return SDOM_OK;
555 }
556
SDOM_getNodeType(SablotSituation s,SDOM_Node n,SDOM_NodeType * pType)557 SDOM_Exception SDOM_getNodeType(SablotSituation s, SDOM_Node n, SDOM_NodeType *pType)
558 {
559 Vertex *v = toV(n);
560 switch(basetype(v))
561 {
562 case VT_ROOT:
563 *pType = SDOM_DOCUMENT_NODE; break;
564 case VT_ELEMENT:
565 *pType = SDOM_ELEMENT_NODE; break;
566 case VT_ATTRIBUTE:
567 *pType = SDOM_ATTRIBUTE_NODE; break;
568 case VT_TEXT:
569 {
570 if (toText(v) -> isCDATA())
571 *pType = SDOM_CDATA_SECTION_NODE;
572 else
573 *pType = SDOM_TEXT_NODE;
574 }; break;
575 case VT_COMMENT:
576 *pType = SDOM_COMMENT_NODE; break;
577 case VT_PI:
578 *pType = SDOM_PROCESSING_INSTRUCTION_NODE; break;
579 case VT_NAMESPACE:
580 *pType = SDOM_ATTRIBUTE_NODE; break;
581 default:
582 *pType = SDOM_OTHER_NODE;
583 }
584 return SDOM_OK;
585 }
586
SDOM_getNodeName(SablotSituation s,SDOM_Node n,SDOM_char ** pName)587 SDOM_Exception SDOM_getNodeName(SablotSituation s, SDOM_Node n, SDOM_char **pName)
588 {
589 Str fullName;
590 Vertex *v = toV(n);
591 switch(v -> vt & VT_BASE)
592 {
593 case VT_ELEMENT:
594 {
595 v -> getOwner().expandQStr(toE(v) -> getName(), fullName);
596 *pName = SDOM_newString(fullName);
597 };
598 break;
599 case VT_ATTRIBUTE:
600 {
601 v -> getOwner().expandQStr(toA(v) -> getName(), fullName);
602 *pName = SDOM_newString(fullName);
603 };
604 break;
605 case VT_NAMESPACE:
606 {
607 v -> getOwner().expandQStr(toNS(v) -> getName(), fullName);
608 DStr fullName2 = "xmlns";
609 if ( strcmp(fullName,"") ) {
610 fullName2 += ":";
611 fullName2 += fullName;
612 }
613 *pName = SDOM_newString(fullName2);
614 };
615 break;
616 case VT_TEXT: // and CDATA
617 {
618 if (toText(v) -> isCDATA())
619 *pName = SDOM_newString("#cdata-section");
620 else
621 *pName = SDOM_newString("#text");
622 }; break;
623 case VT_COMMENT:
624 *pName = SDOM_newString("#comment"); break;
625 case VT_ROOT:
626 *pName = SDOM_newString("#document"); break;
627 case VT_PI:
628 *pName = SDOM_newString(toPI(v) -> getOwner().expand(toPI(v) -> getName().getLocal())); break;
629
630 default:
631 *pName = NULL;
632 }
633 return SDOM_OK;
634 }
635
SDOM_getNodeNSUri(SablotSituation s,SDOM_Node n,SDOM_char ** pName)636 SDOM_Exception SDOM_getNodeNSUri(SablotSituation s, SDOM_Node n, SDOM_char **pName)
637 {
638 Str value;
639 Vertex *v = toV(n);
640 switch(v -> vt & VT_BASE)
641 {
642 case VT_ELEMENT:
643 {
644 value = v -> getOwner().expand(toE(v) -> getName().getUri());
645 *pName = SDOM_newString(value);
646 };
647 break;
648 case VT_ATTRIBUTE:
649 {
650 value = v -> getOwner().expand(toA(v) -> getName().getUri());
651 *pName = SDOM_newString(value);
652 };
653 break;
654 case VT_NAMESPACE:
655 {
656 *pName = SDOM_newString(theXMLNSNamespace);
657 };
658 break;
659 default:
660 *pName = NULL;
661 }
662 return SDOM_OK;
663 }
664
SDOM_getNodePrefix(SablotSituation s,SDOM_Node n,SDOM_char ** pName)665 SDOM_Exception SDOM_getNodePrefix(SablotSituation s, SDOM_Node n, SDOM_char **pName)
666 {
667 Str value;
668 Vertex *v = toV(n);
669 switch(v -> vt & VT_BASE)
670 {
671 case VT_ELEMENT:
672 {
673 value = v -> getOwner().expand(toE(v) -> getName().getPrefix());
674 *pName = SDOM_newString(value);
675 };
676 break;
677 case VT_ATTRIBUTE:
678 {
679 value = v -> getOwner().expand(toA(v) -> getName().getPrefix());
680 *pName = SDOM_newString(value);
681 };
682 break;
683 case VT_NAMESPACE:
684 {
685 v -> getOwner().expandQStr(toNS(v) -> getName(), value);
686 if ( !strcmp(value,"") ) {
687 *pName = SDOM_newString("");
688 } else {
689 *pName = SDOM_newString("xmlns");
690 };
691 };
692 break;
693 default:
694 *pName = NULL;
695 }
696 return SDOM_OK;
697 }
698
SDOM_getNodeLocalName(SablotSituation s,SDOM_Node n,SDOM_char ** pName)699 SDOM_Exception SDOM_getNodeLocalName(SablotSituation s, SDOM_Node n, SDOM_char **pName)
700 {
701 Str value;
702 Vertex *v = toV(n);
703 switch(v -> vt & VT_BASE)
704 {
705 case VT_ELEMENT:
706 {
707 value = v -> getOwner().expand(toE(v) -> getName().getLocal());
708 *pName = SDOM_newString(value);
709 };
710 break;
711 case VT_ATTRIBUTE:
712 {
713 value = v -> getOwner().expand(toA(v) -> getName().getLocal());
714 *pName = SDOM_newString(value);
715 };
716 break;
717 case VT_NAMESPACE:
718 {
719 v -> getOwner().expandQStr(toNS(v) -> getName(), value);
720 if ( !strcmp(value,"") ) {
721 *pName = SDOM_newString("xmlns");
722 } else {
723 value = v -> getOwner().expand(toNS(v) -> getName().getLocal());
724 *pName = SDOM_newString(value);
725 };
726
727
728 };
729 break;
730 default:
731 *pName = NULL;
732 }
733 return SDOM_OK;
734 }
735
SDOM_setNodeName(SablotSituation s,SDOM_Node n,const SDOM_char * name)736 SDOM_Exception SDOM_setNodeName(SablotSituation s, SDOM_Node n, const SDOM_char *name)
737 {
738 Vertex *v = toV(n);
739 QName q;
740 if (isRoot(v))
741 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
742 switch (v -> vt & VT_BASE)
743 {
744 case VT_ELEMENT:
745 toE(v) -> setLogical(SIT(s), q, name, TRUE);
746 break;
747 default:
748 {
749 if (v -> parent)
750 toE(v -> parent) -> setLogical(SIT(s), q, name, FALSE);
751 else
752 v -> getOwner().getRoot().setLogical(SIT(s), q, name, FALSE);
753 }
754 }
755
756 switch(v -> vt & VT_BASE)
757 {
758 case VT_ELEMENT:
759 if ( q.getPrefix() != UNDEF_PHRASE && !toE(v) -> namespaces.find(q.getPrefix()) )
760 SDOM_Err(s, SDOM_NAMESPACE_ERR);
761 toE(v) -> namespaces.decPrefixUsage(toE(v) -> name.getPrefix());
762 toE(v) -> name = q;
763 toE(v) -> namespaces.incPrefixUsage(q.getPrefix());
764 break;
765 case VT_ATTRIBUTE:
766 if ( toA(v) -> parent ) {
767 Phrase curPrefix = toA(v) -> name.getPrefix();
768 Phrase newPrefix = q.getPrefix();
769 if ( (newPrefix != UNDEF_PHRASE
770 && !toE(toA(v) -> parent) -> namespaces.find(newPrefix))
771 ||
772 (newPrefix == toA(v)-> getOwner().stdPhrase(PHRASE_XMLNS)
773 || !strcmp(name,"xmlns")) ){
774 //attempt to change attribute to namespace
775 SDOM_Err(s, SDOM_NAMESPACE_ERR);
776 };
777 if ( curPrefix != UNDEF_PHRASE)
778 toE(toA(v) -> parent) -> namespaces.decPrefixUsage(curPrefix);
779 toA(v) -> name = q;
780 if ( newPrefix != UNDEF_PHRASE)
781 toE(toA(v) -> parent) -> namespaces.incPrefixUsage(newPrefix);
782 } else
783 toA(v) -> name = q;
784 break;
785 case VT_NAMESPACE:
786 {
787 if ( strcmp(name,"xmlns") ) {
788 if ( !(q.getPrefix() == toNS(v)-> getOwner().stdPhrase(PHRASE_XMLNS)) ) {
789 //attempt to change namespace to attribute
790 SDOM_Err(s, SDOM_NAMESPACE_ERR);
791 };
792 } else {
793 //default namespace
794 q.setLocal(UNDEF_PHRASE);
795 };
796 q.setPrefix(UNDEF_PHRASE);
797 if ( !(toNS(v) -> name == q) ) {
798 if ( toNS(v) -> usageCount != 0 ) {
799 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
800 } else {
801 toNS(v) -> prefix = q.getLocal();
802 toNS(v) -> name = q;
803 };
804 };
805 }; break;
806 case VT_PI:
807 toPI(v) -> name = q;
808 break;
809 default:
810 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
811 }
812 return SDOM_OK;
813 }
814
SDOM_getNodeValue(SablotSituation s,SDOM_Node n,SDOM_char ** pValue)815 SDOM_Exception SDOM_getNodeValue(SablotSituation s, SDOM_Node n, SDOM_char **pValue)
816 {
817 Vertex *v = toV(n);
818 switch(v -> vt & VT_BASE)
819 {
820 case VT_ATTRIBUTE:
821 *pValue = SDOM_newString(toA(v) -> cont);
822 break;
823 case VT_NAMESPACE:
824 *pValue = SDOM_newString(v -> getOwner().expand(toNS(v) -> uri));
825 break;
826 case VT_TEXT: // and CDATA section
827 *pValue = SDOM_newString(toText(v) -> cont);
828 break;
829 case VT_COMMENT:
830 *pValue = SDOM_newString(toComment(v) -> cont);
831 break;
832 case VT_PI:
833 *pValue = SDOM_newString(toPI(v) -> cont);
834 break;
835 default:
836 // element and document (root) have void value
837 *pValue = NULL;
838 }
839 return SDOM_OK;
840 }
841
SDOM_setNodeValue(SablotSituation s,SDOM_Node n,const SDOM_char * value)842 SDOM_Exception SDOM_setNodeValue(SablotSituation s, SDOM_Node n, const SDOM_char *value)
843 {
844 Vertex *v = toV(n);
845 switch(v -> vt & VT_BASE)
846 {
847 case VT_ATTRIBUTE:
848 toA(v) -> cont = value;
849 break;
850 case VT_NAMESPACE:
851 SE( __SDOM_canChangeUriNS(s, toNS(v) -> parent, toNS(v), value) );
852 toNS(v) -> uri = v -> getOwner().unexpand(value);
853 break;
854 case VT_TEXT: // and CDATA section
855 toText(v) -> cont = value;
856 break;
857 case VT_COMMENT:
858 toComment(v) -> cont = value;
859 break;
860 case VT_PI:
861 toPI(v) -> cont = value;
862 break;
863 default:
864 // element and document (root) have void value
865 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
866 }
867 return SDOM_OK;
868 }
869
SDOM_getParentNode(SablotSituation s,SDOM_Node n,SDOM_Node * pParent)870 SDOM_Exception SDOM_getParentNode(SablotSituation s, SDOM_Node n, SDOM_Node *pParent)
871 {
872 Vertex *v = toV(n);
873 if (isRoot(v) || isAttr(v) || isNS(v))
874 *pParent = NULL;
875 else
876 *pParent = v -> parent;
877 return SDOM_OK;
878 }
879
SDOM_getFirstChild(SablotSituation s,SDOM_Node n,SDOM_Node * pFirstChild)880 SDOM_Exception SDOM_getFirstChild(SablotSituation s, SDOM_Node n, SDOM_Node *pFirstChild)
881 {
882 Vertex *v = toV(n);
883 if (!isElement(v) && !isRoot(v))
884 *pFirstChild = NULL;
885 else
886 {
887 int childCount = toE(v) -> contents.number();
888 if (childCount)
889 *pFirstChild = (SDOM_Node)(toE(v) -> contents[0]);
890 else
891 *pFirstChild = NULL;
892 }
893 return SDOM_OK;
894 }
895
SDOM_getLastChild(SablotSituation s,SDOM_Node n,SDOM_Node * pLastChild)896 SDOM_Exception SDOM_getLastChild(SablotSituation s, SDOM_Node n, SDOM_Node *pLastChild)
897 {
898 Vertex *v = toV(n);
899 if (!isElement(v) && !isRoot(v))
900 *pLastChild = NULL;
901 else
902 {
903 int childCount = toE(v) -> contents.number();
904 if (childCount)
905 *pLastChild = (SDOM_Node)(toE(v) -> contents.last());
906 else
907 *pLastChild = NULL;
908 }
909 return SDOM_OK;
910 }
911
SDOM_getPreviousSibling(SablotSituation s,SDOM_Node n,SDOM_Node * pPreviousSibling)912 SDOM_Exception SDOM_getPreviousSibling(SablotSituation s, SDOM_Node n, SDOM_Node *pPreviousSibling)
913 {
914 switch(toV(n) -> vt & VT_BASE)
915 {
916 case VT_ATTRIBUTE:
917 case VT_NAMESPACE:
918 case VT_ROOT:
919 *pPreviousSibling = NULL;
920 break;
921 default:
922 *pPreviousSibling = toV(n) -> getPreviousSibling();
923 }
924 return SDOM_OK;
925 }
926
SDOM_getNextSibling(SablotSituation s,SDOM_Node n,SDOM_Node * pNextSibling)927 SDOM_Exception SDOM_getNextSibling(SablotSituation s, SDOM_Node n, SDOM_Node *pNextSibling)
928 {
929 switch(toV(n) -> vt & VT_BASE)
930 {
931 case VT_ATTRIBUTE:
932 case VT_NAMESPACE:
933 case VT_ROOT:
934 *pNextSibling = NULL;
935 break;
936 default:
937 *pNextSibling = toV(n) -> getNextSibling();
938 }
939 return SDOM_OK;
940 }
941
SDOM_getChildNodeIndex(SablotSituation s,SDOM_Node n,int index,SDOM_Node * pChildNode)942 SDOM_Exception SDOM_getChildNodeIndex(SablotSituation s, SDOM_Node n, int index, SDOM_Node *pChildNode)
943 {
944 Vertex *v = toV(n);
945 if ( (!isElement(v) && !isRoot(v))
946 || index < 0
947 || index >= toE(v) -> contents.number() )
948 *pChildNode = NULL;
949 else
950 *pChildNode = (SDOM_Node)(toE(n) -> contents[index]);
951 return SDOM_OK;
952 }
953
SDOM_getChildNodeCount(SablotSituation s,SDOM_Node n,int * count)954 SDOM_Exception SDOM_getChildNodeCount(SablotSituation s, SDOM_Node n, int *count)
955 {
956 Vertex *v = toV(n);
957 if ( !isElement(v) && !isRoot(v) )
958 *count = 0;
959 else
960 *count = toE(v) -> contents.number();
961 return SDOM_OK;
962 }
963
SDOM_getOwnerDocument(SablotSituation s,SDOM_Node n,SDOM_Document * pOwnerDocument)964 SDOM_Exception SDOM_getOwnerDocument(SablotSituation s, SDOM_Node n, SDOM_Document *pOwnerDocument)
965 {
966 if (isRoot(toV(n)))
967 *pOwnerDocument = NULL;
968 else
969 *pOwnerDocument = ownerDoc(n);
970 return SDOM_OK;
971 }
972
hasElementChild(RootNode * r)973 Bool hasElementChild(RootNode *r)
974 {
975 for (int i = 0; i < r -> contents.number(); i++)
976 if (isElement(r -> contents[i]))
977 return TRUE;
978 return FALSE;
979 }
980
981 // is first ancestor of second?
isAncestor(Vertex * first,Vertex * second)982 Bool isAncestor(Vertex *first, Vertex *second)
983 {
984 for (Vertex *p = second; p; p = p -> parent)
985 if (p == first) return TRUE;
986 return FALSE;
987 }
988
SDOM_insertBefore(SablotSituation s,SDOM_Node n,SDOM_Node newChild,SDOM_Node refChild)989 SDOM_Exception SDOM_insertBefore(SablotSituation s, SDOM_Node n, SDOM_Node newChild, SDOM_Node refChild)
990 {
991 Vertex *v = toV(n);
992
993 // check if v is an element (or root)
994 if (!isElement(v))
995 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
996
997 // check the type of newChild
998 if (!newChild)
999 SDOM_Err(s, SDOM_NOT_FOUND_ERR)
1000 else
1001 switch(basetype(newChild))
1002 {
1003 case VT_ATTRIBUTE:
1004 case VT_NAMESPACE:
1005 case VT_ROOT:
1006 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1007 }
1008 // check if newChild is from the same doc
1009 if ((isRoot(v) && ownerDoc(newChild) != v) ||
1010 (!isRoot(v) && ownerDoc(v) != ownerDoc(newChild)))
1011 SDOM_Err(s, SDOM_WRONG_DOCUMENT_ERR);
1012
1013 // check type of the reference child
1014 if (refChild)
1015 switch(toV(refChild) -> vt & VT_BASE)
1016 {
1017 case VT_ATTRIBUTE:
1018 case VT_NAMESPACE:
1019 case VT_ROOT:
1020 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1021 }
1022
1023 // check if newChild is not an ancestor of n
1024 if (isAncestor(toV(newChild), toV(n)))
1025 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1026
1027 // check if not attempting to have more doc elements
1028 if (isRoot(v) && isElement(newChild) && hasElementChild(toRoot(v)))
1029 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1030
1031 // see if newChild needs to be removed from tree
1032 Vertex *parent;
1033 if (NULL != (parent = toV(newChild) -> parent))
1034 SE( SDOM_removeChild(s, parent, newChild) );
1035 //_JP_ v
1036 // // v ???
1037 // int ndx = toE(v) -> contents.getIndex(toV(newChild));
1038 // if (ndx != -1)
1039 // toE(v) -> contents.rm(ndx);
1040 // // ^ ???
1041 // //_TH_ v
1042 // getTmpList(n).rmP(newChild);
1043 // //_TH_ ^
1044 int ndx = toE(v) -> contents.getIndex(toV(newChild));
1045 if (ndx != -1)
1046 toE(v) -> contents.rm(ndx);
1047 else
1048 getTmpList(n).rmP(newChild);
1049 //_JP_ ^
1050 if (refChild)
1051 {
1052 ndx = toE(v) -> contents.getIndex(toV(refChild));
1053 if (ndx == -1)
1054 SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1055 toE(v) -> contents.insertBefore(toV(newChild), ndx);
1056 }
1057 else
1058 toE(v) -> contents.append(toV(newChild));
1059 // toE(v) -> contents.appendAndSetOrdinal(toV(newChild));
1060 toV(newChild) -> setParent(v);
1061 //_JP_ v
1062 //old_parent's not used namespaces was cleaned by SDOM_removeChild
1063 SE( __SDOM_swallowParentNS(s, newChild) );
1064 //_JP_ ^
1065 return SDOM_OK;
1066 }
1067
SDOM_removeChild(SablotSituation s,SDOM_Node n,SDOM_Node oldChild)1068 SDOM_Exception SDOM_removeChild(SablotSituation s, SDOM_Node n, SDOM_Node oldChild)
1069 {
1070 Vertex *v = toV(n);
1071 if (!isElement(v))
1072 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1073 switch(toV(oldChild) -> vt & VT_BASE)
1074 {
1075 case VT_ATTRIBUTE:
1076 case VT_NAMESPACE:
1077 case VT_ROOT:
1078 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1079 }
1080 if (toV(oldChild) -> parent != toV(n))
1081 SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1082 //_JP_ v
1083 //SE( __SDOM_dropParentNS(s, oldChild) );
1084 //_JP_ ^
1085 toE(v) -> removeChild(toV(oldChild));
1086 //_TH_ v
1087 getTmpList(n).append(oldChild);
1088 //_TH_ ^
1089 return SDOM_OK;
1090 }
1091
SDOM_replaceChild(SablotSituation s,SDOM_Node n,SDOM_Node newChild,SDOM_Node oldChild)1092 SDOM_Exception SDOM_replaceChild(SablotSituation s, SDOM_Node n, SDOM_Node newChild, SDOM_Node oldChild)
1093 {
1094 SDOM_Node tmp;
1095 SE( SDOM_getParentNode(s, newChild, &tmp) );
1096 if (tmp) SE( SDOM_removeChild(s, tmp, newChild) );
1097
1098 SE( SDOM_getNextSibling(s, oldChild, &tmp) );
1099 SE( SDOM_removeChild(s, n, oldChild) );
1100 SE( SDOM_insertBefore(s, n, newChild, tmp) );
1101
1102 //_JP_ old version not satisfying DOM spec:
1103 //SE( SDOM_insertBefore(s, n, newChild, oldChild) );
1104 //SE( SDOM_removeChild(s, n, oldChild) );
1105
1106 return SDOM_OK;
1107 }
1108
SDOM_appendChild(SablotSituation s,SDOM_Node n,SDOM_Node newChild)1109 SDOM_Exception SDOM_appendChild(SablotSituation s, SDOM_Node n, SDOM_Node newChild)
1110 {
1111 return SDOM_insertBefore(s, n, newChild, NULL);
1112 }
1113
1114 SDOM_Exception cloneVertex(SablotSituation, Tree *, Vertex *, int, Vertex **);
1115
cloneVertexList(SablotSituation s,Tree * t,VertexList * vlForeign,int deep,Element * tParent)1116 SDOM_Exception cloneVertexList(SablotSituation s, Tree *t, VertexList *vlForeign, int deep, Element *tParent)
1117 {
1118 Vertex *newVertex;
1119 for (int i = 0; i < vlForeign -> number(); i++)
1120 {
1121 SE( cloneVertex(s, t, (*vlForeign)[i], deep, &newVertex) );
1122 // the following also handles atts and namespaces correctly
1123 tParent -> newChild(SIT(s), newVertex);
1124 }
1125 return SDOM_OK;
1126 }
1127
cloneVertex(SablotSituation s,Tree * t,Vertex * foreign,int deep,Vertex ** clone)1128 SDOM_Exception cloneVertex(SablotSituation s, Tree *t, Vertex *foreign, int deep, Vertex **clone)
1129 {
1130 Tree *tForeign = &(foreign -> getOwner());
1131 QName q;
1132 EQName expanded;
1133
1134 if (basetype(foreign) == VT_ROOT)
1135 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1136
1137 // get the correctly unexpanded name
1138 if (basetype(foreign) == VT_ELEMENT ||
1139 basetype(foreign) == VT_ATTRIBUTE ||
1140 basetype(foreign) == VT_PI ||
1141 basetype(foreign) == VT_NAMESPACE)
1142 {
1143 switch(basetype(foreign))
1144 {
1145 case VT_ELEMENT:
1146 tForeign -> expandQ(toE(foreign) -> getName(), expanded);
1147 break;
1148 case VT_ATTRIBUTE:
1149 tForeign -> expandQ(toA(foreign) -> getName(), expanded);
1150 break;
1151 case VT_NAMESPACE:
1152 tForeign -> expandQ(toNS(foreign) -> getName(), expanded);
1153 break;
1154 case VT_PI:
1155 tForeign -> expandQ(toPI(foreign) -> getName(), expanded);
1156 break;
1157 };
1158 q.setLocal(t -> unexpand(expanded.getLocal()));
1159 q.setPrefix(t -> unexpand(expanded.getPrefix()));
1160 q.setUri(t -> unexpand(expanded.getUri()));
1161 }
1162
1163 // create the actual copy
1164 switch(basetype(foreign))
1165 {
1166 case VT_ELEMENT:
1167 *clone = new(&(t -> getArena()))
1168 Element(*t, q);
1169 break;
1170 case VT_ATTRIBUTE:
1171 *clone = new(&(t -> getArena()))
1172 Attribute(*t, q, toA(foreign) -> cont, XSLA_NONE);
1173 break;
1174 case VT_NAMESPACE:
1175 *clone = new(&(t -> getArena())) NmSpace(*t,
1176 t -> unexpand(tForeign -> expand(toNS(foreign) -> prefix)),
1177 t -> unexpand(tForeign -> expand(toNS(foreign) -> uri)),
1178 toNS(foreign) -> kind);
1179 // _JP_ v
1180 toNS(*clone) -> usageCount = toNS(foreign) -> usageCount;
1181 // _JP_ ^
1182 break;
1183 case VT_PI:
1184 *clone = new(&(t -> getArena())) ProcInstr(*t, q.getLocal(), toPI(foreign) -> cont);
1185 break;
1186 case VT_COMMENT:
1187 *clone = new(&(t -> getArena())) Comment(*t, toComment(foreign) -> cont);
1188 break;
1189 case VT_TEXT:
1190 {
1191 *clone = new(&(t -> getArena())) Text(*t, toText(foreign) -> cont);
1192 if (toText(foreign) -> isCDATA())
1193 toText(*clone) -> beCDATA();
1194 }; break;
1195 }
1196
1197 if (isElement(foreign))
1198 {
1199 // must clone atts and namespaces in any case
1200 sabassert(isElement(*clone));
1201 cloneVertexList(s, t, &(toE(foreign) -> atts), deep, toE(*clone));
1202 cloneVertexList(s, t, &(toE(foreign) -> namespaces), deep, toE(*clone));
1203
1204 // if deep then recurse
1205 if (deep)
1206 cloneVertexList(s, t, &(toE(foreign) -> contents), deep, toE(*clone));
1207 }
1208 return SDOM_OK;
1209 }
1210
SDOM_cloneForeignNode(SablotSituation s,SDOM_Document d,SDOM_Node n,int deep,SDOM_Node * clone)1211 SDOM_Exception SDOM_cloneForeignNode(SablotSituation s, SDOM_Document d, SDOM_Node n, int deep, SDOM_Node *clone)
1212 {
1213 SDOM_Exception se = cloneVertex(s, toTree(d), toV(n), deep, (Vertex**) clone);
1214 //_JP_ v
1215 se = (se != SDOM_OK) ? se : __SDOM_dropParentNS(s, *clone);
1216 //_JP_ ^
1217 //_TH_ v
1218 getTmpList(d).append(*clone);
1219 //_TH_ ^
1220 return se;
1221 }
1222
SDOM_cloneNode(SablotSituation s,SDOM_Node n,int deep,SDOM_Node * clone)1223 SDOM_Exception SDOM_cloneNode(SablotSituation s, SDOM_Node n, int deep, SDOM_Node *clone)
1224 {
1225 return SDOM_cloneForeignNode(s, ownerDoc(n), n, deep, clone);
1226 }
1227
SDOM_getAttribute(SablotSituation s,SDOM_Node n,const SDOM_char * name,SDOM_char ** pValue)1228 SDOM_Exception SDOM_getAttribute(SablotSituation s, SDOM_Node n, const SDOM_char *name, SDOM_char **pValue)
1229 {
1230 QName q;
1231 if (!isElement(toV(n)))
1232 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1233 Element *e = toE(toV(n));
1234
1235 e -> setLogical(SIT(s), q, name, FALSE);
1236 Vertex *v = NULL;
1237 Bool isXMLNS = isXMLNS_(q, e);
1238 if (!isXMLNS)
1239 v = e -> atts.find(q);
1240 else
1241 v = e -> namespaces.find(
1242 q.getLocal() != UNDEF_PHRASE ? q.getLocal() : UNDEF_PHRASE);
1243 if (!v)
1244 *pValue = SDOM_newString("");
1245 else
1246 {
1247 if (!isXMLNS)
1248 *pValue = SDOM_newString(toA(v) -> cont);
1249 else
1250 *pValue = SDOM_newString(e -> getOwner().expand(toNS(v) -> uri));
1251 }
1252 return SDOM_OK;
1253 }
1254
SDOM_getAttributeNS(SablotSituation s,SDOM_Node n,SDOM_char * uri,SDOM_char * local,SDOM_char ** pValue)1255 SDOM_Exception SDOM_getAttributeNS(SablotSituation s, SDOM_Node n, SDOM_char *uri, SDOM_char *local, SDOM_char **pValue)
1256 {
1257 QName q;
1258 if (!isElement(toV(n)))
1259 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1260 Element *e = toE(toV(n));
1261
1262 Vertex *v = NULL;
1263 Bool isXMLNS = ( !strcmp((char*)uri,theXMLNSNamespace) );
1264 if ( !isXMLNS ) {
1265 const int attcount = e -> atts.number();
1266 for (int i = 0; i < attcount; i++) {
1267 q = toA(e->atts[i]) -> name;
1268 if (!strcmp((char*)local, (char*)(e -> getOwner().expand(q.getLocal())))
1269 && !strcmp((char*)uri, (char*)(e -> getOwner().expand(q.getUri())))) {
1270 v = e -> atts[i];
1271 break;
1272 };
1273 };
1274 } else {
1275 const int nscount = e -> namespaces.number();
1276 for (int i = 0; i < nscount; i++) {
1277 q = toNS(e->namespaces[i]) -> name;
1278 if (!strcmp((char*)local, (char*)(e -> getOwner().expand(toNS(e->namespaces[i])->prefix)))) {
1279 v = e -> namespaces[i];
1280 break;
1281 };
1282 };
1283 }
1284 if (!v)
1285 *pValue = SDOM_newString("");
1286 else
1287 {
1288 if (!isXMLNS)
1289 *pValue = SDOM_newString(toA(v) -> cont);
1290 else
1291 *pValue = SDOM_newString(e -> getOwner().expand(toNS(v) -> uri));
1292 }
1293 return SDOM_OK;
1294 }
1295
SDOM_getAttributeNode(SablotSituation s,SDOM_Node n,const SDOM_char * name,SDOM_Node * attr)1296 SDOM_Exception SDOM_getAttributeNode(SablotSituation s, SDOM_Node n, const SDOM_char *name, SDOM_Node *attr)
1297 {
1298 QName q;
1299 if ( !isElement(toV(n)) )
1300 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1301 Element *e = toE(toV(n));
1302
1303 e -> setLogical(SIT(s), q, name, FALSE);
1304 Vertex *v = NULL;
1305 Bool isXMLNS = isXMLNS_(q, e);
1306 if (!isXMLNS)
1307 v = e -> atts.find(q);
1308 else
1309 {
1310 v = e -> namespaces.find(
1311 q.getLocal() != e -> getOwner().stdPhrase(PHRASE_XMLNS)?
1312 q.getLocal() : UNDEF_PHRASE);
1313 }
1314 if (!v)
1315 *attr = 0;
1316 else
1317 {
1318 *attr = (SDOM_Node)v;
1319 }
1320 return SDOM_OK;
1321 }
1322
SDOM_getAttributeNodeNS(SablotSituation s,SDOM_Node n,SDOM_char * uri,SDOM_char * local,SDOM_Node * attr)1323 SDOM_Exception SDOM_getAttributeNodeNS(SablotSituation s, SDOM_Node n, SDOM_char *uri, SDOM_char *local, SDOM_Node *attr)
1324 {
1325 QName q;
1326 if (!isElement(toV(n)))
1327 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1328 Element *e = toE(toV(n));
1329
1330 Vertex *v = NULL;
1331 if ( strcmp((char*)uri,theXMLNSNamespace) ) {
1332 //true attribute
1333 const int attcount = e -> atts.number();
1334 for (int i = 0; i < attcount; i++) {
1335 q = toA(e->atts[i]) -> name;
1336 if (!strcmp((char*)local, (char*)(e -> getOwner().expand(q.getLocal())))
1337 && !strcmp((char*)uri, (char*)(e -> getOwner().expand(q.getUri())))) {
1338 v = e -> atts[i];
1339 break;
1340 };
1341 };
1342 } else {
1343 //namespace
1344 const int nscount = e -> namespaces.number();
1345 char* pre;
1346 if ( !strcmp(local,"xmlns") )
1347 pre = "";
1348 else
1349 pre = (char*)local;
1350
1351 for (int i = 0; i < nscount; i++) {
1352 q = toNS(e->namespaces[i]) -> name;
1353 if (!strcmp(pre, (char*)(e -> getOwner().expand(toNS(e->namespaces[i])->prefix)))) {
1354 v = e -> namespaces[i];
1355 break;
1356 };
1357 };
1358 };
1359 *attr = v;
1360 return SDOM_OK;
1361 }
1362
SDOM_getAttributeNodeIndex(SablotSituation s,SDOM_Node n,const int index,SDOM_Node * attr)1363 SDOM_Exception SDOM_getAttributeNodeIndex(SablotSituation s, SDOM_Node n, const int index, SDOM_Node *attr)
1364 {
1365 if (!isElement(toV(n)))
1366 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1367 Element *e = toE(toV(n));
1368 int nscount = e -> namespaces.number();
1369
1370 if (index < 0 || index >= nscount + e -> atts.number() )
1371 *attr = NULL;
1372 else
1373 if (index < nscount)
1374 *attr = (SDOM_Node)(e -> namespaces[index]);
1375 else
1376 *attr = (SDOM_Node)(e -> atts[index-nscount]);
1377 return SDOM_OK;
1378 }
1379
SDOM_getAttributeNodeCount(SablotSituation s,SDOM_Node n,int * count)1380 SDOM_Exception SDOM_getAttributeNodeCount(SablotSituation s, SDOM_Node n, int *count)
1381 {
1382 if (!isElement(toV(n)))
1383 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1384 Element *e = toE(toV(n));
1385 *count = e -> namespaces.number() + e -> atts.number();
1386 return SDOM_OK;
1387 }
1388
1389
SDOM_setAttribute(SablotSituation s,SDOM_Node n,const SDOM_char * attName,const SDOM_char * attValue)1390 SDOM_Exception SDOM_setAttribute(SablotSituation s, SDOM_Node n, const SDOM_char *attName, const SDOM_char *attValue)
1391 {
1392 QName q;
1393 if (!isElement(toV(n)))
1394 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1395 Element *e = toE(toV(n));
1396
1397 e -> setLogical(SIT(s), q, attName, FALSE);
1398 Vertex *v;
1399 if ( !isXMLNS_(q, e) ) {
1400 v = e -> atts.find(q);
1401 if (!v) {
1402 SE( _SDOM_createAttributeWithParent(s, ownerDoc(e), (SDOM_Node*) &v, attName, e));
1403 //_TH_ v
1404 getTmpList(n).rmP(v);
1405 //_TH_ ^
1406 e -> atts.append(toA(v));
1407 toV(v) -> setParent(e);
1408 };
1409 SE( SDOM_setNodeValue(s, v, attValue) );
1410 } else { //attribute is namespace declaration
1411 v = e -> namespaces.find(q.getLocal() != e -> getOwner().stdPhrase(PHRASE_XMLNS) ? q.getLocal() : UNDEF_PHRASE);
1412 if (!v) {
1413 SE( _SDOM_createAttributeWithParent(s, ownerDoc(e), (SDOM_Node*) &v, attName, e));
1414 //_TH_ v
1415 getTmpList(n).rmP(v);
1416 //_TH_ ^
1417 e -> namespaces.append(toNS(v));
1418 toV(v) -> setParent(e);
1419 };
1420 SE( SDOM_setNodeValue(s, v, attValue) );
1421 //_JP_ v
1422 toNS(v) -> kind = NSKIND_DECLARED;
1423 SE( __SDOM_refreshNS(s, n, toNS(v)) );
1424 //_JP_ ^
1425 };
1426
1427 return SDOM_OK;
1428 }
1429
1430 //_JP_ v
SDOM_setAttributeNS(SablotSituation s,SDOM_Node n,const SDOM_char * uri,const SDOM_char * qName,const SDOM_char * value)1431 SDOM_Exception SDOM_setAttributeNS(SablotSituation s, SDOM_Node n, const SDOM_char *uri, const SDOM_char *qName, const SDOM_char *value)
1432 {
1433 if (!isElement(toV(n)))
1434 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1435
1436 if ( !isValidQName((char*)qName) )
1437 SDOM_Err(s, SDOM_INVALID_CHARACTER_ERR);
1438
1439 QName q;
1440 Element *e = toE(toV(n));
1441 Str prefix = Str();
1442 char *colon = strchr((char*)qName,':');
1443
1444 if ( colon ) { //qName has prefix
1445
1446 if ( !uri )
1447 SDOM_Err(s, SDOM_NAMESPACE_ERR);
1448
1449 prefix.nset((char*)qName, intPtrDiff(colon, qName));
1450
1451 if ( !strcmp((const char*)prefix,"xml") && strcmp(theXMLNamespace,uri) )
1452 //redefinition of xml-namespace
1453 SDOM_Err(s, SDOM_NAMESPACE_ERR);
1454
1455 if ( !strcmp((const char*)prefix,"xmlns") && strcmp(theXMLNSNamespace,uri) )
1456 //redefinition of xmlns-namespace
1457 SDOM_Err(s, SDOM_NAMESPACE_ERR);
1458
1459 q.setPrefix(ownerDoc(toE(n))->dict().insert((const char*)prefix));
1460 q.setLocal(ownerDoc(toE(n))->dict().insert((const char*)((ptrdiff_t)colon + 1)));
1461 q.setUri(ownerDoc(toE(n))->dict().insert((const char*)uri));
1462
1463 } else {
1464
1465 q.setPrefix(UNDEF_PHRASE);
1466 q.setLocal(ownerDoc(toE(n))->dict().insert((const char*)qName));
1467
1468 if ( uri && strcmp((char*)uri,"") ) {
1469 q.setUri(ownerDoc(toE(n))->dict().insert((const char*)uri));
1470 } else {
1471 q.setUri(UNDEF_PHRASE);
1472 };
1473 };
1474
1475 SDOM_Node replaced;
1476 SE( SDOM_getAttributeNodeNS(s, n,
1477 (SDOM_char*)(e -> getOwner().expand(q.getUri())),
1478 (SDOM_char*)(e -> getOwner().expand(q.getLocal())),
1479 &replaced) );
1480
1481 if ( strcmp((char*)uri, theXMLNSNamespace) ) {
1482 //true attribute
1483 if ( replaced ) {
1484 //attr with the same uri:local found
1485 if ( q.getPrefix() == toA(replaced)->name.getPrefix() ) {
1486 //the same prefix
1487 } else {
1488 //prefix != replaced.prefix
1489 if ( q.getPrefix() != UNDEF_PHRASE ) {
1490 SE( __SDOM_touchNS(s, n,
1491 q.getPrefix(),
1492 q.getUri(),
1493 NSKIND_PARENT, 0) );
1494 e -> namespaces.decPrefixUsage(toA(replaced)->name.getPrefix());
1495 };
1496 toA(replaced)->name.setPrefix(q.getPrefix());
1497 };
1498 } else {
1499 //attr with the same uri:local NOT found
1500 if ( q.getPrefix() != UNDEF_PHRASE )
1501 SE( __SDOM_touchNS(s, n,
1502 q.getPrefix(),
1503 q.getUri(),
1504 NSKIND_PARENT, 0) );
1505 Tree *tOwner = toTree(ownerDoc(e));
1506 replaced = new(&(tOwner -> getArena()))
1507 Attribute(*tOwner, q, (char*)"", XSLA_NONE);
1508 e -> atts.append(toA(replaced));
1509 toV(replaced) -> setParent(e);
1510 };
1511 SE( SDOM_setNodeValue(s, replaced, value) );
1512
1513 } else {
1514 // att is namespace
1515 SE( __SDOM_touchNSByChar(s, n,
1516 (SDOM_char*)(e -> getOwner().expand(q.getLocal())),
1517 (SDOM_char*)value,
1518 NSKIND_DECLARED, 0) );
1519 };
1520 return SDOM_OK;
1521 }
1522
1523
SDOM_setAttributeNode(SablotSituation s,SDOM_Node n,SDOM_Node attnode,SDOM_Node * replaced)1524 SDOM_Exception SDOM_setAttributeNode(SablotSituation s, SDOM_Node n, SDOM_Node attnode, SDOM_Node *replaced)
1525 {
1526 if ( !( isElement(toV(n)) && (isAttr(toV(attnode))
1527 || isNS(toV(attnode))) ) )
1528 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1529 if ( ownerDoc(n) != ownerDoc(attnode) )
1530 SDOM_Err(s, SDOM_WRONG_DOCUMENT_ERR);
1531 if ( toV(attnode) -> parent )
1532 SDOM_Err(s, SDOM_INUSE_ATTRIBUTE_ERR);
1533 Element *e = toE(toV(n));
1534 //NmSpace *nm;
1535 if ( isAttr(toV(attnode)) ) {
1536 Str attname;
1537 e -> getOwner().expandQStr(toA(attnode) -> getName(), attname);
1538 SE( SDOM_getAttributeNode(s, n, (SDOM_char*)attname, replaced) );
1539 if ( *replaced ) {
1540 //attr with the same prefix:local found
1541 if ( toA(attnode)->name.getUri() == toA(*replaced)->name.getUri() ) {
1542 //the same uri
1543 // int ndx = e -> atts.findNdx(toA(*replaced)->name);
1544 // toV(*replaced) -> parent = NULL;
1545 // //_TH_ v
1546 // getTmpList(n).append(*replaced);
1547 // //_TH_ ^
1548 // e -> atts[ndx] = toV(attnode);
1549 //_JP_ v
1550 int ndx = toV(*replaced) -> ordinal;
1551 toV(*replaced) -> parent = NULL;
1552 //_TH_ v
1553 getTmpList(n).append(*replaced);
1554 getTmpList(n).rmP(attnode);
1555 //_TH_ ^
1556 e -> atts[ndx] = toV(attnode);
1557 toV(attnode) -> ordinal = ndx;
1558 //_JP_ ^
1559 } else {
1560 //attnode.uri != replaced.uri
1561 if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1562 SE( __SDOM_touchNS(s, n,
1563 toA(attnode)->name.getPrefix(),
1564 toA(attnode)->name.getUri(),
1565 NSKIND_PARENT, 1) );
1566 // int ndx = e -> atts.findNdx(toA(*replaced)->name);
1567 // toV(*replaced) -> parent = NULL;
1568 // //_TH_ v
1569 // getTmpList(n).append(*replaced);
1570 // //_TH_ ^
1571 // e -> atts[ndx] = toV(attnode);
1572 //_JP_ v
1573 int ndx = toV(*replaced) -> ordinal;
1574 toV(*replaced) -> parent = NULL;
1575 //_TH_ v
1576 getTmpList(n).append(*replaced);
1577 getTmpList(n).rmP(attnode);
1578 //_TH_ ^
1579 e -> atts[ndx] = toV(attnode);
1580 toV(attnode) -> ordinal = ndx;
1581 //_JP_ ^
1582 };
1583 } else {
1584 //attr with the same prefix:local NOT found
1585 if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1586 SE( __SDOM_touchNS(s, n,
1587 toA(attnode)->name.getPrefix(),
1588 toA(attnode)->name.getUri(),
1589 NSKIND_PARENT, 0) );
1590 //_TH_ v
1591 getTmpList(n).rmP(attnode);
1592 //_TH_ ^
1593 e -> atts.append(toA(attnode));
1594 };
1595 toV(attnode) -> setParent(e);
1596
1597 } else {
1598 // attnode is namespace
1599 int ndx = e -> namespaces.findNdx(toNS(attnode)->prefix);
1600 if (ndx != -1) {
1601 //namespace with the attnode.prefix exists
1602 NmSpace *nm = toNS(e -> namespaces[ndx]);
1603 if ( nm -> uri == toNS(attnode) -> uri ) {
1604 //namespace with attnode.prefix has attnode.uri
1605 //_TH_ v
1606 getTmpList(n).rmP(attnode);
1607 //_TH_ ^
1608 toV(nm) -> parent = NULL;
1609 //_TH_ v
1610 getTmpList(n).append(nm);
1611 //_TH_ ^
1612 e -> namespaces[ndx] = toV(attnode);
1613 toV(attnode) -> setParent(e);
1614 toV(attnode) -> ordinal = ndx;
1615 toNS(attnode)->kind = nm->kind;
1616 toNS(attnode)->usageCount = nm->usageCount;
1617 *replaced = (SDOM_Node)nm;
1618 } else {
1619 //namespace with attnode.prefix has NOT attnode.uri
1620 if ( nm -> usageCount != 0 || nm -> kind == NSKIND_DECLARED ) {
1621 // namespace used
1622 SDOM_Err(s, SDOM_NAMESPACE_ERR);
1623 } else {
1624 // namespace NOT used
1625 //_TH_ v
1626 getTmpList(n).rmP(attnode);
1627 //_TH_ ^
1628 toV(nm) -> parent = NULL;
1629 //_TH_ v
1630 getTmpList(n).append(nm);
1631 //_TH_ ^
1632 e -> namespaces[ndx] = toV(attnode);
1633 toV(attnode) -> setParent(e);
1634 toV(attnode) -> ordinal = ndx;
1635 toNS(attnode)->kind = NSKIND_DECLARED;
1636 toNS(attnode)->usageCount = 0;
1637 *replaced = (SDOM_Node)nm;
1638 };
1639 };
1640 } else {
1641 //namespace with attnode.prefix NOT exists
1642 *replaced = NULL;
1643 toNS(attnode)->kind = NSKIND_DECLARED;
1644 toNS(attnode)->usageCount = 0;
1645 //_TH_ v
1646 getTmpList(n).rmP(attnode);
1647 //_TH_ ^
1648 e -> namespaces.append(toNS(attnode));
1649 toV(attnode) -> setParent(e);
1650 SE( __SDOM_refreshNS(s, n, toNS(attnode)) );
1651 };
1652 };
1653 return SDOM_OK;
1654 }
1655
SDOM_setAttributeNodeNS(SablotSituation s,SDOM_Node n,SDOM_Node attnode,SDOM_Node * replaced)1656 SDOM_Exception SDOM_setAttributeNodeNS(SablotSituation s, SDOM_Node n, SDOM_Node attnode, SDOM_Node *replaced)
1657 {
1658 if ( !( isElement(toV(n)) && (isAttr(toV(attnode))
1659 || isNS(toV(attnode))) ) )
1660 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1661 if ( ownerDoc(n) != ownerDoc(attnode) )
1662 SDOM_Err(s, SDOM_WRONG_DOCUMENT_ERR);
1663 if ( toV(attnode) -> parent )
1664 SDOM_Err(s, SDOM_INUSE_ATTRIBUTE_ERR);
1665 Element *e = toE(toV(n));
1666 //NmSpace *nm;
1667 if ( isAttr(toV(attnode)) ) {
1668 Str attname;
1669 e -> getOwner().expandQStr(toA(attnode) -> getName(), attname);
1670 SE( SDOM_getAttributeNodeNS(s, n,
1671 (SDOM_char*)(e -> getOwner().expand(toA(attnode)->name.getUri())),
1672 (SDOM_char*)(e -> getOwner().expand(toA(attnode)->name.getLocal())),
1673 replaced) );
1674 if ( *replaced ) {
1675 //attr with the same uri:local found
1676 if ( toA(attnode)->name.getPrefix() == toA(*replaced)->name.getPrefix() ) {
1677 //the same prefix
1678 // int ndx = e -> atts.findNdx(toA(*replaced)->name);
1679 // toV(*replaced) -> parent = NULL;
1680 // //_TH_ v
1681 // getTmpList(n).append(*replaced);
1682 // //_TH_ ^
1683 // e -> atts[ndx] = toV(attnode);
1684 //_JP_ v
1685 int ndx = toV(*replaced) -> ordinal;
1686 toV(*replaced) -> parent = NULL;
1687 //_TH_ v
1688 getTmpList(n).append(*replaced);
1689 getTmpList(n).rmP(attnode);
1690 //_TH_ ^
1691 e -> atts[ndx] = toV(attnode);
1692 toV(attnode) -> ordinal = ndx;
1693 //_JP_ ^
1694
1695 //+++++++++++++++++
1696 } else {
1697 //attnode.prefix != replaced.prefix
1698 if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1699 SE( __SDOM_touchNS(s, n,
1700 toA(attnode)->name.getPrefix(),
1701 toA(attnode)->name.getUri(),
1702 NSKIND_PARENT, 1) );
1703 if ( toA(*replaced)->name.getPrefix() != UNDEF_PHRASE )
1704 e -> namespaces.decPrefixUsage(toA(*replaced)->name.getPrefix());
1705 // int ndx = e -> atts.findNdx(toA(*replaced)->name);
1706 // toV(*replaced) -> parent = NULL;
1707 // //_TH_ v
1708 // getTmpList(n).append(*replaced);
1709 // //_TH_ ^
1710 // e -> atts[ndx] = toV(attnode);
1711 //_JP_ v
1712 int ndx = toV(*replaced) -> ordinal;
1713 toV(*replaced) -> parent = NULL;
1714 //_TH_ v
1715 getTmpList(n).rmP(attnode);
1716 getTmpList(n).append(*replaced);
1717 //_TH_ ^
1718 e -> atts[ndx] = toV(attnode);
1719 toV(attnode) -> ordinal = ndx;
1720 //_JP_ ^
1721 };
1722 } else {
1723 //attr with the same uri:local NOT found
1724 if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1725 SE( __SDOM_touchNS(s, n,
1726 toA(attnode)->name.getPrefix(),
1727 toA(attnode)->name.getUri(),
1728 NSKIND_PARENT, 0) );
1729 //_TH_ v
1730 getTmpList(n).rmP(attnode);
1731 //_TH_ ^
1732 e -> atts.append(toA(attnode));
1733 };
1734 toV(attnode) -> setParent(e);
1735
1736 } else {
1737 // attnode is namespace
1738 int ndx = e -> namespaces.findNdx(toNS(attnode)->prefix);
1739 if (ndx != -1) {
1740 //namespace with the attnode.prefix exists
1741 NmSpace *nm = toNS(e -> namespaces[ndx]);
1742 if ( nm -> uri == toNS(attnode) -> uri ) {
1743 //namespace with attnode.prefix has attnode.uri
1744 //_TH_ v
1745 getTmpList(n).rmP(attnode);
1746 //_TH_ ^
1747 toV(nm) -> parent = NULL;
1748 //_TH_ v
1749 getTmpList(n).append(nm);
1750 //_TH_ ^
1751 e -> namespaces[ndx] = toV(attnode);
1752 toV(attnode) -> setParent(e);
1753 toV(attnode) -> ordinal = ndx;
1754 toNS(attnode)->kind = nm->kind;
1755 toNS(attnode)->usageCount = nm->usageCount;
1756 *replaced = (SDOM_Node)nm;
1757 } else {
1758 //namespace with attnode.prefix has NOT attnode.uri
1759 if ( nm -> usageCount != 0 || nm -> kind == NSKIND_DECLARED ) {
1760 // namespace used
1761 return SDOM_NAMESPACE_ERR;
1762 } else {
1763 // namespace NOT used
1764 //_TH_ v
1765 getTmpList(n).rmP(attnode);
1766 //_TH_ ^
1767 toV(nm) -> parent = NULL;
1768 //_TH_ v
1769 getTmpList(n).append(nm);
1770 //_TH_ ^
1771 e -> namespaces[ndx] = toV(attnode);
1772 toV(attnode) -> setParent(e);
1773 toV(attnode) -> ordinal = ndx;
1774 toNS(attnode)->kind = NSKIND_DECLARED;
1775 toNS(attnode)->usageCount = 0;
1776 *replaced = (SDOM_Node)nm;
1777 };
1778 };
1779 } else {
1780 //namespace with attnode.prefix NOT exists
1781 *replaced = NULL;
1782 toNS(attnode)->kind = NSKIND_DECLARED;
1783 toNS(attnode)->usageCount = 0;
1784 //_TH_ v
1785 getTmpList(n).rmP(attnode);
1786 //_TH_ ^
1787 e -> namespaces.append(toNS(attnode));
1788 toV(attnode) -> setParent(e);
1789 SE( __SDOM_refreshNS(s, n, toNS(attnode)) );
1790 };
1791 };
1792 return SDOM_OK;
1793 }
1794
1795
SDOM_removeAttributeNode(SablotSituation s,SDOM_Node n,SDOM_Node attnode,SDOM_Node * removed)1796 SDOM_Exception SDOM_removeAttributeNode(SablotSituation s, SDOM_Node n, SDOM_Node attnode, SDOM_Node *removed)
1797 {
1798 if (!isElement(toV(n)))
1799 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1800 Element *e = toE(toV(n));
1801
1802 if (isAttr(attnode))
1803 {
1804 int attNdx = e -> atts.findNdx(toA(attnode)->name);
1805 if (attNdx != -1)
1806 {
1807 //_TH_ v
1808 Vertex *tmp = e -> atts[attNdx];
1809 //_TH_ ^
1810 tmp -> parent = NULL;
1811 e -> atts.rm(attNdx);
1812 //_TH_ v
1813 getTmpList(n).append(tmp);
1814 //_TH_ ^
1815 if (toA(tmp) -> name.getPrefix() != UNDEF_PHRASE)
1816 e -> namespaces.decPrefixUsage(toA(tmp) -> name.getPrefix());
1817 *removed = tmp;
1818 } else {
1819 SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1820 };
1821 }
1822 else
1823 {
1824 int attNdx = e -> namespaces.findNdx(toNS(attnode)->prefix);
1825 if (attNdx != -1)
1826 {
1827 if (toNS(e -> namespaces[attNdx]) -> usageCount != 0)
1828 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
1829 //_TH_ v
1830 Vertex *tmp = e -> namespaces[attNdx];
1831 //_TH_ ^
1832 tmp -> parent = NULL;
1833 e -> namespaces.rm(attNdx);
1834 //_TH_ v
1835 getTmpList(n).append(tmp);
1836 //_TH_ ^
1837 *removed = tmp;
1838 } else {
1839 SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1840 };
1841 }
1842 return SDOM_OK;
1843 }
1844 //_JP_ ^
1845
1846
SDOM_removeAttribute(SablotSituation s,SDOM_Node n,const SDOM_char * name)1847 SDOM_Exception SDOM_removeAttribute(SablotSituation s, SDOM_Node n, const SDOM_char *name)
1848 {
1849 QName q;
1850 if (!isElement(toV(n)))
1851 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1852 Element *e = toE(toV(n));
1853
1854 e -> setLogical(SIT(s), q, name, FALSE);
1855 if (!isXMLNS_(q, e))
1856 {
1857 int attNdx = e -> atts.findNdx(q);
1858 if (attNdx != -1)
1859 {
1860 //_TH_ v
1861 Vertex *tmp = e -> atts[attNdx];
1862 //_TH_ ^
1863 e -> atts[attNdx] -> parent = NULL;
1864 e -> atts.rm(attNdx);
1865 //_TH_ v
1866 getTmpList(n).append(tmp);
1867 //_TH_ ^
1868 //_JP_ v
1869 if (toA(tmp) -> name.getPrefix() != UNDEF_PHRASE)
1870 e -> namespaces.decPrefixUsage(toA(tmp) -> name.getPrefix());
1871 //_JP_ ^
1872 }
1873 }
1874 else
1875 {
1876 int attNdx = e -> namespaces.findNdx(
1877 q.getLocal() != e -> getOwner().stdPhrase(PHRASE_XMLNS) ?
1878 q.getLocal() : UNDEF_PHRASE);
1879 if (attNdx != -1)
1880 {
1881 //_JP_ v
1882 if (toNS(e -> namespaces[attNdx]) -> usageCount != 0)
1883 return SDOM_NO_MODIFICATION_ALLOWED_ERR;
1884 //_JP_ ^
1885 e -> namespaces[attNdx] -> parent = NULL;
1886 e -> namespaces.rm(attNdx);
1887 }
1888 }
1889 return SDOM_OK;
1890 }
1891
1892
SDOM_getAttributeElement(SablotSituation s,SDOM_Node attr,SDOM_Node * owner)1893 SDOM_Exception SDOM_getAttributeElement(SablotSituation s, SDOM_Node attr, SDOM_Node *owner)
1894 {
1895 Vertex *v = toV(attr);
1896 if ( isAttr(v) | isNS(v) )
1897 {
1898 *owner = v -> parent;
1899 return SDOM_OK;
1900 }
1901 else
1902 return SDOM_HIERARCHY_REQUEST_ERR;
1903 }
1904
SDOM_getAttributeList(SablotSituation s,SDOM_Node n,SDOM_NodeList * pAttrList)1905 SDOM_Exception SDOM_getAttributeList(SablotSituation s, SDOM_Node n, SDOM_NodeList *pAttrList)
1906 {
1907 *pAttrList = new CList;
1908 if (isElement(toV(n)))
1909 {
1910 int i;
1911 NSList& namespaces = toE(toV(n)) -> namespaces;
1912 for (i = 0; i < namespaces.number(); i++)
1913 ((CList*)(*pAttrList)) -> append(namespaces[i]);
1914 AttList& atts = toE(toV(n)) -> atts;
1915 for (i = 0; i < atts.number(); i++)
1916 ((CList*)(*pAttrList)) -> append(atts[i]);
1917 }
1918 return SDOM_OK;
1919 }
1920
1921 //
1922 //
1923 //
1924
SDOM_docToString(SablotSituation s,SDOM_Document d,SDOM_char ** pSerialized)1925 SDOM_Exception SDOM_docToString(SablotSituation s, SDOM_Document d, SDOM_char **pSerialized)
1926 {
1927 // using explicit temp because of BeOS
1928 char *serializedTemp = NULL;
1929 toTree(d) -> serialize(SIT(s), serializedTemp);
1930 *pSerialized = serializedTemp;
1931 return SDOM_OK;
1932 }
1933
1934 //_PH_
SDOM_nodeToString(SablotSituation s,SDOM_Document d,SDOM_Node n,SDOM_char ** pSerialized)1935 SDOM_Exception SDOM_nodeToString(SablotSituation s, SDOM_Document d,
1936 SDOM_Node n,
1937 SDOM_char **pSerialized)
1938 {
1939 char *serializedTemp = NULL;
1940 toTree(d) -> serializeNode(SIT(s), toE(n), serializedTemp);
1941 *pSerialized = serializedTemp;
1942 return SDOM_OK;
1943 }
1944
1945 //
1946 //
1947 //
1948
SDOM_getNodeListLength(SablotSituation s,SDOM_NodeList l,int * pLength)1949 SDOM_Exception SDOM_getNodeListLength(SablotSituation s, SDOM_NodeList l, int *pLength)
1950 {
1951 *pLength = ((CList*)l) -> number();
1952 return SDOM_OK;
1953 }
1954
SDOM_getNodeListItem(SablotSituation s,SDOM_NodeList l,int index,SDOM_Node * pItem)1955 SDOM_Exception SDOM_getNodeListItem(SablotSituation s, SDOM_NodeList l, int index, SDOM_Node *pItem)
1956 {
1957 if ((index < 0) || (index >= ((CList*)l) -> number()))
1958 SDOM_Err(s, SDOM_INDEX_SIZE_ERR);
1959 *pItem = ((CList*)l) -> operator[](index);
1960 return SDOM_OK;
1961 }
1962
SDOM_disposeNodeList(SablotSituation s,SDOM_NodeList l)1963 SDOM_Exception SDOM_disposeNodeList(SablotSituation s, SDOM_NodeList l)
1964 {
1965 if (!((CList*)l) -> decRefCount())
1966 delete (CList*)l;
1967 return SDOM_OK;
1968 }
1969
1970
1971 //
1972 //
1973 //
1974
SDOM_xql(SablotSituation s,const SDOM_char * query,SDOM_Node currentNode,SDOM_NodeList * pResult)1975 SDOM_Exception SDOM_xql(SablotSituation s, const SDOM_char *query, SDOM_Node currentNode, SDOM_NodeList *pResult)
1976 {
1977 RootNode &root = toV(currentNode) -> getOwner().getRoot();
1978
1979 // find the document element
1980 int i;
1981 for (i = 0; i < root.contents.number(); i++)
1982 if (isElement(root.contents[i])) break;
1983
1984 Element *docElement = (i < root.contents.number()) ?
1985 toE(root.contents[i]) : &root;
1986 Expression queryEx(*docElement);
1987 *pResult = NULL;
1988
1989 // parse the query string as a non-pattern
1990 if (queryEx.parse(SIT(s), (char*)query, FALSE, TRUE))
1991 SDOM_Err(s, SDOM_QUERY_PARSE_ERR);
1992
1993 // create an initial context
1994 GP( Context ) dummy = new Context(NULL); //_cn_ no current node
1995 GP( Context ) c;
1996 c.assign(dummy);
1997 (*c).set(toV(currentNode));
1998
1999 // create the result context
2000 if (queryEx.createContext(SIT(s), c))
2001 SDOM_Err(s, SDOM_QUERY_EXECUTION_ERR);
2002
2003 // preserve the CList
2004 (*c).getArrayForDOM() -> incRefCount();
2005 c.unkeep();
2006 *pResult = (SDOM_NodeList) (*c).getArrayForDOM();
2007 return SDOM_OK;
2008 }
2009
SDOM_xql_ns(SablotSituation s,const SDOM_char * query,SDOM_Node currentNode,char ** nsmap,SDOM_NodeList * pResult)2010 SDOM_Exception SDOM_xql_ns(SablotSituation s, const SDOM_char *query, SDOM_Node currentNode, char** nsmap, SDOM_NodeList *pResult)
2011 {
2012 //RootNode &root = toV(currentNode) -> getOwner().getRoot();
2013
2014 // find the document element
2015 //int i;
2016 //for (i = 0; i < root.contents.number(); i++)
2017 // if (isElement(root.contents[i])) break;
2018 GP( Tree ) tree = new Tree(Str("noscheme:dummy-tree"), false);
2019 QName q;
2020 q.setLocal((*tree).unexpand(Str("dummy-root")));
2021 Element *e = new(&((*tree).getArena())) Element(*tree, q);
2022 e -> setSubtreeInfo((*tree).getRootSubtree());
2023 char ** aux = nsmap;
2024 while (*aux) {
2025 char *pref = *aux;
2026 char *uri = *(aux + 1);
2027 NmSpace *nm = new(&((*tree).getArena()))
2028 NmSpace(*tree, (*tree).unexpand(pref), (*tree).unexpand(uri),
2029 false, NSKIND_DECLARED);
2030 e -> newChild(SIT(s), nm);
2031 aux += 2;
2032 }
2033
2034 Expression queryEx(*e);
2035 *pResult = NULL;
2036
2037 // parse the query string as a non-pattern
2038 if (queryEx.parse(SIT(s), (char*)query, FALSE, TRUE))
2039 SDOM_Err(s, SDOM_QUERY_PARSE_ERR);
2040
2041 // create an initial context
2042 GP( Context ) dummy = new Context(NULL); //_cn_ no current node
2043 GP( Context ) c;
2044 c.assign(dummy);
2045 (*c).set(toV(currentNode));
2046
2047 // create the result context
2048 if (queryEx.createContext(SIT(s), c))
2049 SDOM_Err(s, SDOM_QUERY_EXECUTION_ERR);
2050
2051 // preserve the CList
2052 (*c).getArrayForDOM() -> incRefCount();
2053 c.unkeep();
2054 *pResult = (SDOM_NodeList) (*c).getArrayForDOM();
2055 return SDOM_OK;
2056 }
2057
2058 //
2059 // exception retrieval
2060 //
2061
SDOM_getExceptionCode(SablotSituation s)2062 int SDOM_getExceptionCode(SablotSituation s)
2063 {
2064 return SIT(s).getSDOMExceptionCode();
2065 }
2066
SDOM_getExceptionMessage(SablotSituation s)2067 char* SDOM_getExceptionMessage(SablotSituation s)
2068 {
2069 return SDOM_newString(
2070 SDOM_ExceptionMsg[SDOM_getExceptionCode(s)]);
2071 }
2072
SDOM_getExceptionDetails(SablotSituation s,int * code,char ** message,char ** documentURI,int * fileLine)2073 void SDOM_getExceptionDetails(
2074 SablotSituation s,
2075 int *code,
2076 char **message,
2077 char **documentURI,
2078 int *fileLine)
2079 {
2080 Str message_, documentURI_;
2081 MsgCode code_;
2082 int fileLine_;
2083 SIT(s).getSDOMExceptionExtra(code_, message_, documentURI_, fileLine_);
2084 *code = code_;
2085 *fileLine = fileLine_;
2086 *documentURI = SDOM_newString(documentURI_);
2087 *message = SDOM_newString(message_);
2088 }
2089
2090
2091
2092 //
2093 // internal
2094 //
2095
SDOM_setNodeInstanceData(SDOM_Node n,void * data)2096 void SDOM_setNodeInstanceData(SDOM_Node n, void *data)
2097 {
2098 toV(n) -> setInstanceData(data);
2099 }
2100
SDOM_getNodeInstanceData(SDOM_Node n)2101 void* SDOM_getNodeInstanceData(SDOM_Node n)
2102 {
2103 return toV(n) -> getInstanceData();
2104 }
2105
SDOM_setDisposeCallback(SDOM_NodeCallback * f)2106 void SDOM_setDisposeCallback(SDOM_NodeCallback *f)
2107 {
2108 theDisposeCallback = f;
2109 }
2110
SDOM_getDisposeCallback()2111 SDOM_NodeCallback* SDOM_getDisposeCallback()
2112 {
2113 return theDisposeCallback;
2114 }
2115
2116
2117
2118 //_TH_ v
SDOM_tmpListDump(SDOM_Document doc,int p)2119 void SDOM_tmpListDump(SDOM_Document doc, int p)
2120 {
2121 getTmpList(doc).dump(p);
2122 }
2123 //_TH_ ^
2124
SDOM_compareNodes(SablotSituation s,SDOM_Node n1,SDOM_Node n2,int * res)2125 SDOM_Exception SDOM_compareNodes(SablotSituation s, SDOM_Node n1, SDOM_Node n2, int *res)
2126 {
2127 if (&(toV(n1) -> getOwner()) == &(toV(n2) -> getOwner()) ) //the same owner
2128 {
2129 int s1 = toV(n1) -> stamp;
2130 int s2 = toV(n2) -> stamp;
2131 if (s1 < s2)
2132 *res = -1;
2133 else if (s1 == s2)
2134 *res = 0;
2135 else
2136 *res = 1;
2137 }
2138 else
2139 {
2140 *res = strcmp( (char*)(toV(n1) -> getOwner().getURI()),
2141 (char*)(toV(n2) -> getOwner().getURI()) );
2142 }
2143 return SDOM_OK;
2144 }
2145
2146 #endif /* ENABLE_DOM */
2147