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
35 #define SablotAsExport
46 #define getTmpList(v) (toV(v) -> getOwner().tmpList)
48 char* SDOM_ExceptionMsg[] =
53 // SDOM_INDEX_SIZE_ERR 1
54 (char *) "list index out of bounds",
56 // SDOM_DOMSTRING_SIZE_ERR 2
57 (char *) "invalid size of string",
59 // SDOM_HIERARCHY_REQUEST_ERR 3
60 (char *) "hierarchy request error",
62 // SDOM_WRONG_DOCUMENT_ERR 4
63 (char *) "node used in a document that did not create it",
65 // SDOM_INVALID_CHARACTER_ERR 5
66 (char *) "invalid character in string",
68 // SDOM_NO_DATA_ALLOWED_ERR 6
69 (char *) "data not allowed",
71 // SDOM_NO_MODIFICATION_ALLOWED_ERR 7
72 (char *) "modification not allowed",
74 // SDOM_NOT_FOUND_ERR 8
75 (char *) "reference to a non-existent node",
77 // SDOM_NOT_FOUND_ERR 9
78 (char *) "functionality not supported",
80 // SDOM_INUSE_ATTRIBUTE_ERR 10
81 (char *) "attribute is inuse",
83 // SDOM_NOT_FOUND_ERR 10
84 (char *) "attribute is inuse",
86 // SDOM_INVALID_STATE_ERR 11
87 (char *) "invalid state",
90 (char *) "syntax error",
92 // SDOM_INVALID_MODIFICATION_ERR 13
93 (char *) "invalid modification",
95 // SDOM_NAMESPACE_ERR 14
96 (char *) "namespace error",
98 // SDOM_INVALID_ACCESS_ERR 15
99 (char *) "invalid access",
102 (char *) "invalid node type",
104 // SDOM_QUERY_PARSE_ERR
105 (char *) "query parsing error",
107 // SDOM_QUERY_EXECUTION_ERR
108 (char *) "query execution error",
111 (char *) "general exception"
114 #define SDOM_Err(SITUA, CODE) { SIT( SITUA ).setSDOMExceptionCode( CODE );\
115 SIT( SITUA ).message(\
116 MT_ERROR, E2_SDOM, CODE, SDOM_ExceptionMsg[CODE]); return CODE; }
118 #define SE(statement) {SDOM_Exception code__ = statement; \
119 if (code__) return code__;}
121 #define SIT(PTR) (*(Situation*)PTR)
123 #define isXMLNS_(qn, resolver) \
124 (qn.getPrefix() == resolver -> getOwner().stdPhrase(PHRASE_XMLNS) || \
125 (qn.getPrefix() == UNDEF_PHRASE && \
126 qn.getLocal() == resolver -> getOwner().stdPhrase(PHRASE_XMLNS)))
132 SDOM_NodeCallback* theDisposeCallback = NULL;
133 #define ownerDoc(NODE) ( &(toV(NODE)->getOwner().getRoot()) )
135 char* SDOM_newString(const Str& strg)
137 int len = strg.length();
138 char *p = new char[len + 1];
139 strcpy(p, (char*)(const char*)strg);
145 // helper functions for namespace handling
146 SDOM_Exception ___SDOM_swallowParentNSrec(SablotSituation s, SDOM_Node n, Tree* t, NSList* parentNs)
148 // inherits from parentNs to begin of n->namespaces with respect to scoping
149 // do it recursively for all child elements
150 if ( isElement(toV(n)) ) {
151 NSList* currentNs = &(toE(n) -> namespaces);
153 const int imax = parentNs->number() - 1;
154 for (int i = imax; i >= 0; i--) {
155 nm = toNS((*parentNs)[i]);
156 if (currentNs -> findNdx(nm -> prefix) == -1) {
157 nm = new(&(NZ(t) -> getArena())) NmSpace(*t, nm -> prefix, nm -> uri,
159 currentNs -> append(toV(nm));
160 nm -> parent = toV(n);
163 //zero in args => all appended namespaces will have kind == NSKIND_PARENT
164 //parentNs->giveCurrent(SIT(s), *currentNs, t, 0);
165 SDOM_Node checkedNode;
166 SE( SDOM_getFirstChild(s, n, &checkedNode) );
167 while (checkedNode) {
168 SE( ___SDOM_swallowParentNSrec(s, checkedNode, t, currentNs) );
169 SE( SDOM_getNextSibling(s, checkedNode, &checkedNode) );
175 SDOM_Exception __SDOM_swallowParentNS(SablotSituation s, SDOM_Node n)
177 // inherits from parent's NSList to begin of n->namespaces with respect to scoping
178 // do it recursively for all child elements
179 if ( n && isElement(toV(n)) && toE(n) -> parent ) {
180 NSList* parentNs = &(toE(toE(n) -> parent) -> namespaces);
181 Tree* t = toTree( n );
182 SE( ___SDOM_swallowParentNSrec(s, n, t, parentNs) );
187 SDOM_Exception __SDOM_dropParentNS(SablotSituation s, SDOM_Node n)
189 // removes inherited namespaces from n->namespaces
190 // and from all child elements recursively
191 if ( n && isElement(toV(n)) ) {
192 NSList *checkedNs = &(toE(n) -> namespaces);
194 const int imax = checkedNs->number() - 1;
195 for (int i = imax; i >= 0; i--) {
196 nm = toNS((*checkedNs)[i]);
197 if ( nm -> usageCount == 0 && nm -> kind == NSKIND_PARENT ) {
200 getTmpList(toE(n)).append(nm);
203 SDOM_Node checkedNode;
204 SE( SDOM_getFirstChild(s, n, &checkedNode) );
205 while (checkedNode) {
206 SE( __SDOM_dropParentNS(s, checkedNode) );
207 SE( SDOM_getNextSibling(s, checkedNode, &checkedNode) );
213 SDOM_Exception __SDOM_refreshNS(SablotSituation s, SDOM_Node n, NmSpace* nmspace)
215 // appends or changes nmspace in all child elements recursively
216 // with respect to scoping
217 SDOM_Node checkedNode;
220 SE( SDOM_getFirstChild(s, n, &checkedNode) );
221 while (checkedNode) {
222 if ( isElement(checkedNode) ) {
223 nm = toE(checkedNode) -> namespaces.find(nmspace -> prefix);
225 if ( nm -> usageCount == 0 && nm -> kind == NSKIND_PARENT ) {
226 nm -> uri = nmspace -> uri;
227 SE( __SDOM_refreshNS(s, checkedNode, nmspace) );
230 //t = toTree(ownerDoc(toE(n)));
231 t = &(toE(n) -> getOwner());
232 nm = new(&(t -> getArena())) NmSpace(*t, nmspace -> prefix,
235 toE(checkedNode) -> namespaces.append(nm);
236 nm -> setParent(toE(checkedNode));
237 SE( __SDOM_refreshNS(s, checkedNode, nmspace) );
240 SE( SDOM_getNextSibling(s, checkedNode, &checkedNode) );
245 SDOM_Exception __SDOM_canChangeUriNS(SablotSituation s, SDOM_Node n, NmSpace* nmspace, const SDOM_char *uri)
247 // order of tests has meaning
248 if ( !n || nmspace->usageCount == 0 )
249 // namespace without parent is changeable
250 // not used namespace is changeable
253 Str olduri = toV(nmspace)->getOwner().expand(nmspace->uri);
254 if ( !strcmp((char*)olduri,(char*)uri) )
255 return SDOM_OK;// no change will be done
257 return SDOM_NAMESPACE_ERR;
261 SDOM_Exception __SDOM_touchNS(SablotSituation s, SDOM_Node n, Phrase prefix, Phrase uri, NsKind kind, unsigned int maxUsageCount)
263 //appends or changes n.namespaces to push prefix:uri into scope
264 //potentially refreshes childrens' namespaces
265 //suppose if kind == NSKIND_DECLARED then nm will NOT be immediatelly used
266 //suppose if kind == NSKIND_PARENT then nm will be immediatelly used
267 NmSpace *nm = toE(n)->namespaces.find(prefix);
269 //nm->prefix == prefix
270 if (nm->uri == uri) {
271 if (kind == NSKIND_PARENT) nm -> usageCount++;
272 else nm -> kind = kind;
274 if ( kind == NSKIND_PARENT ) {
275 if (nm -> kind == NSKIND_PARENT && nm -> usageCount <= maxUsageCount) {
277 return __SDOM_refreshNS(s, n, nm);
279 return SDOM_NAMESPACE_ERR;//_JP_ not in spec - namespace collision
282 if (nm -> usageCount <= maxUsageCount) {
285 return __SDOM_refreshNS(s, n, nm);
287 return SDOM_NAMESPACE_ERR;//_JP_ not in spec - namespace collision
292 //nm with prefix not exists
294 //Tree *auxt = NZ(toTree(ownerDoc(toE(n))));
295 Tree *auxt = &(toE(n) -> getOwner());
296 nm = new(&(auxt -> getArena()))
297 NmSpace(toE(n) -> getOwner(),prefix, uri, kind);
298 if (kind == NSKIND_PARENT) nm -> usageCount = 1;
299 toE(n) -> namespaces.append(nm);
300 toV(nm) -> setParent(toE(n));
306 SDOM_Exception __SDOM_touchNSByChar(SablotSituation s, SDOM_Node n, SDOM_char* prefix, SDOM_char* uri, NsKind kind, int maxUsageCount)
308 //appends or changes n.namespaces to push prefix:uri into scope
309 //potentially refreshes childrens' namespaces
310 Phrase ph_prefix = prefix && strcmp((char*)prefix,"xmlns") ? toE(ownerDoc(toE(n)))->dict().insert((const char*)prefix) : UNDEF_PHRASE;
311 Phrase ph_uri = uri ? toE(ownerDoc(toE(n)))->dict().insert((const char*)uri) : UNDEF_PHRASE;
312 return __SDOM_touchNS(s, n, ph_prefix, ph_uri, kind, maxUsageCount);
319 SDOM_Exception SDOM_createElement(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *tagName)
322 //try to find the document element
324 for (int i = 0; i < toRoot(d) -> contents.number(); i++)
326 if (isElement(toRoot(d) -> contents[i]))
328 e = toE(toRoot(d) -> contents[i]);
332 if (!e) e = toRoot(d);
334 e -> setLogical(SIT(s), q, tagName, TRUE);
335 *pn = new(&(toTree(d) -> getArena())) Element(*toTree(d), q);
337 getTmpList(d).append(*pn);
343 SDOM_Exception SDOM_createElementNS(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *uri, const SDOM_char *qName)
345 if ( !isValidQName((char*)qName) )
346 return SDOM_INVALID_CHARACTER_ERR;
349 const char *colon = strchr((char*)qName,':');
352 if ( colon ) { //qName has prefix
355 return SDOM_NAMESPACE_ERR;
357 prefix.nset((char*)qName, (int)colon - (int)qName);
359 if ( !strcmp((const char*)prefix,"xml") && strcmp(theXMLNamespace,uri) )
360 //redefinition of xml-namespace
361 return SDOM_NAMESPACE_ERR;
363 q.setPrefix(toE(d)->dict().insert((const char*)prefix));
364 q.setLocal(toE(d)->dict().insert((const char*)((int)colon + 1)));
365 q.setUri(toE(d)->dict().insert((const char*)uri));
369 q.setPrefix(UNDEF_PHRASE);
370 q.setLocal(toE(d)->dict().insert((const char*)qName));
372 if ( uri && strcmp((char*)uri,"") ) {
373 q.setUri(toE(d)->dict().insert((const char*)uri));
375 q.setUri(UNDEF_PHRASE);
379 *pn = new(&(toTree(d) -> getArena())) Element(*toTree(d), q);
380 // no parent, no childs, no attributes => only 1 namespace:
381 NmSpace* newNS = new(&(toTree(d) -> getArena())) NmSpace(*toTree(d),
385 newNS -> usageCount = 1;
386 toE(*pn) -> namespaces.append(newNS);
387 toV(newNS) -> setParent(toE(*pn));
389 getTmpList(d).append(*pn);
395 SDOM_Exception _SDOM_createAttributeWithParent(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *name, SDOM_Node parent)
399 // uses parent's NSList, if exists
401 toE(parent) -> setLogical(SIT(s), q, name, FALSE);
403 toRoot(d) -> setLogical(SIT(s), q, name, FALSE);
405 if ( !isXMLNS_(q, toRoot(d)) ) {
406 *pn = new(&(toTree(d) -> getArena()))
407 Attribute(*toTree(d), q, (char*)"", XSLA_NONE);
409 toE(parent)->namespaces.incPrefixUsage(q.getPrefix());
411 *pn = new(&(toTree(d) -> getArena()))
413 q.getPrefix() == UNDEF_PHRASE ? UNDEF_PHRASE : q.getLocal(),
417 getTmpList(d).append(*pn);
422 SDOM_Exception SDOM_createAttribute(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *name)
424 return _SDOM_createAttributeWithParent(s, d, pn, name, NULL);
428 SDOM_Exception SDOM_createAttributeNS(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *uri, const SDOM_char *qName)
430 if ( !isValidQName((char*)qName) )
431 return SDOM_INVALID_CHARACTER_ERR;
434 const char *colon = strchr((char*)qName,':');
437 if ( colon ) { //qName has prefix
440 return SDOM_NAMESPACE_ERR;
442 prefix.nset((char*)qName, (int)colon - (int)qName);
444 if ( !strcmp((const char*)prefix,"xml") && strcmp(theXMLNamespace,uri) )
445 //redefinition of xml namespace
446 return SDOM_NAMESPACE_ERR;
448 if ( !strcmp((const char*)prefix,"xmlns") && strcmp(theXMLNSNamespace,uri) )
449 //redefinition of xmlns namespace
450 return SDOM_NAMESPACE_ERR;
452 q.setPrefix(toE(d)->dict().insert((const char*)prefix));
453 q.setLocal(toE(d)->dict().insert((const char*)((int)colon + 1)));
454 q.setUri(toE(d)->dict().insert((const char*)uri));
458 q.setPrefix(UNDEF_PHRASE);
459 q.setLocal(toE(d)->dict().insert((const char*)qName));
460 if ( uri && strcmp((char*)uri,"") ) {
461 q.setUri(toE(d)->dict().insert((const char*)uri));
463 q.setUri(UNDEF_PHRASE);
467 if ( !isXMLNS_(q, toRoot(d)) )
468 *pn = new(&(toTree(d) -> getArena()))
469 Attribute(*toTree(d), q, (char*)"", XSLA_NONE);
471 *pn = new(&(toTree(d) -> getArena()))
478 getTmpList(d).append(*pn);
484 SDOM_Exception SDOM_createTextNode(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *data)
486 *pn = new(&(toTree(d) -> getArena())) Text(*toTree(d), (char*) data);
488 getTmpList(d).append(*pn);
493 SDOM_Exception SDOM_createCDATASection(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *data)
495 SE( SDOM_createTextNode(s, d, pn, data) );
496 toText(toV(*pn)) -> beCDATA();
500 SDOM_Exception SDOM_createComment(
504 const SDOM_char *data)
506 *pn = new(&(toTree(d) -> getArena())) Comment(*toTree(d), (char*) data);
508 getTmpList(d).append(*pn);
513 SDOM_Exception SDOM_createProcessingInstruction(
517 const SDOM_char *target,
518 const SDOM_char *data)
520 *pn = new(&(toTree(d) -> getArena())) ProcInstr(
522 toTree(d) -> unexpand((char*) target),
525 getTmpList(d).append(*pn);
530 SDOM_Exception SDOM_disposeNode(SablotSituation s, SDOM_Node n)
533 switch(v -> vt & VT_BASE)
536 ccdelete(v, toE(v)); break;
538 ccdelete(v, toA(v)); break;
540 ccdelete(v, toNS(v)); break;
542 ccdelete(v, toPI(v)); break;
543 case VT_TEXT: // and CDATA
544 ccdelete(v, toText(v)); break;
546 ccdelete(v, toX(v)); break;
548 ccdelete(v, toComment(v)); break;
550 assert(!"disposeSDOM_Node");
555 SDOM_Exception SDOM_getNodeType(SablotSituation s, SDOM_Node n, SDOM_NodeType *pType)
561 *pType = SDOM_DOCUMENT_NODE; break;
563 *pType = SDOM_ELEMENT_NODE; break;
565 *pType = SDOM_ATTRIBUTE_NODE; break;
568 if (toText(v) -> isCDATA())
569 *pType = SDOM_CDATA_SECTION_NODE;
571 *pType = SDOM_TEXT_NODE;
574 *pType = SDOM_COMMENT_NODE; break;
576 *pType = SDOM_PROCESSING_INSTRUCTION_NODE; break;
578 *pType = SDOM_ATTRIBUTE_NODE; break;
580 *pType = SDOM_OTHER_NODE;
585 SDOM_Exception SDOM_getNodeName(SablotSituation s, SDOM_Node n, SDOM_char **pName)
589 switch(v -> vt & VT_BASE)
593 v -> getOwner().expandQStr(toE(v) -> getName(), fullName);
594 *pName = SDOM_newString(fullName);
599 v -> getOwner().expandQStr(toA(v) -> getName(), fullName);
600 *pName = SDOM_newString(fullName);
605 v -> getOwner().expandQStr(toNS(v) -> getName(), fullName);
606 DStr fullName2 = "xmlns";
607 if ( strcmp(fullName,"") ) {
609 fullName2 += fullName;
611 *pName = SDOM_newString(fullName2);
614 case VT_TEXT: // and CDATA
616 if (toText(v) -> isCDATA())
617 *pName = SDOM_newString("#cdata-section");
619 *pName = SDOM_newString("#text");
622 *pName = SDOM_newString("#comment"); break;
624 *pName = SDOM_newString("#document"); break;
626 *pName = SDOM_newString(toPI(v) -> getOwner().expand(toPI(v) -> getName().getLocal())); break;
634 SDOM_Exception SDOM_getNodeNSUri(SablotSituation s, SDOM_Node n, SDOM_char **pName)
638 switch(v -> vt & VT_BASE)
642 value = v -> getOwner().expand(toE(v) -> getName().getUri());
643 *pName = SDOM_newString(value);
648 value = v -> getOwner().expand(toA(v) -> getName().getUri());
649 *pName = SDOM_newString(value);
654 *pName = SDOM_newString(theXMLNSNamespace);
663 SDOM_Exception SDOM_getNodePrefix(SablotSituation s, SDOM_Node n, SDOM_char **pName)
667 switch(v -> vt & VT_BASE)
671 value = v -> getOwner().expand(toE(v) -> getName().getPrefix());
672 *pName = SDOM_newString(value);
677 value = v -> getOwner().expand(toA(v) -> getName().getPrefix());
678 *pName = SDOM_newString(value);
683 v -> getOwner().expandQStr(toNS(v) -> getName(), value);
684 if ( !strcmp(value,"") ) {
685 *pName = SDOM_newString("");
687 *pName = SDOM_newString("xmlns");
697 SDOM_Exception SDOM_getNodeLocalName(SablotSituation s, SDOM_Node n, SDOM_char **pName)
701 switch(v -> vt & VT_BASE)
705 value = v -> getOwner().expand(toE(v) -> getName().getLocal());
706 *pName = SDOM_newString(value);
711 value = v -> getOwner().expand(toA(v) -> getName().getLocal());
712 *pName = SDOM_newString(value);
717 v -> getOwner().expandQStr(toNS(v) -> getName(), value);
718 if ( !strcmp(value,"") ) {
719 *pName = SDOM_newString("xmlns");
721 value = v -> getOwner().expand(toNS(v) -> getName().getLocal());
722 *pName = SDOM_newString(value);
734 SDOM_Exception SDOM_setNodeName(SablotSituation s, SDOM_Node n, const SDOM_char *name)
739 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
740 switch (v -> vt & VT_BASE)
743 toE(v) -> setLogical(SIT(s), q, name, TRUE);
748 toE(v -> parent) -> setLogical(SIT(s), q, name, FALSE);
750 v -> getOwner().getRoot().setLogical(SIT(s), q, name, FALSE);
754 switch(v -> vt & VT_BASE)
757 if ( q.getPrefix() != UNDEF_PHRASE && !toE(v) -> namespaces.find(q.getPrefix()) )
758 SDOM_Err(s, SDOM_NAMESPACE_ERR);
759 toE(v) -> namespaces.decPrefixUsage(toE(v) -> name.getPrefix());
761 toE(v) -> namespaces.incPrefixUsage(q.getPrefix());
764 if ( toA(v) -> parent ) {
765 Phrase curPrefix = toA(v) -> name.getPrefix();
766 Phrase newPrefix = q.getPrefix();
767 if ( (newPrefix != UNDEF_PHRASE
768 && !toE(toA(v) -> parent) -> namespaces.find(newPrefix))
770 (newPrefix == toA(v)-> getOwner().stdPhrase(PHRASE_XMLNS)
771 || !strcmp(name,"xmlns")) ){
772 //attempt to change attribute to namespace
773 SDOM_Err(s, SDOM_NAMESPACE_ERR);
775 if ( curPrefix != UNDEF_PHRASE)
776 toE(toA(v) -> parent) -> namespaces.decPrefixUsage(curPrefix);
778 if ( newPrefix != UNDEF_PHRASE)
779 toE(toA(v) -> parent) -> namespaces.incPrefixUsage(newPrefix);
785 if ( strcmp(name,"xmlns") ) {
786 if ( !(q.getPrefix() == toNS(v)-> getOwner().stdPhrase(PHRASE_XMLNS)) ) {
787 //attempt to change namespace to attribute
788 SDOM_Err(s, SDOM_NAMESPACE_ERR);
792 q.setLocal(UNDEF_PHRASE);
794 q.setPrefix(UNDEF_PHRASE);
795 if ( !(toNS(v) -> name == q) ) {
796 if ( toNS(v) -> usageCount != 0 ) {
797 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
799 toNS(v) -> prefix = q.getLocal();
808 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
813 SDOM_Exception SDOM_getNodeValue(SablotSituation s, SDOM_Node n, SDOM_char **pValue)
816 switch(v -> vt & VT_BASE)
819 *pValue = SDOM_newString(toA(v) -> cont);
822 *pValue = SDOM_newString(v -> getOwner().expand(toNS(v) -> uri));
824 case VT_TEXT: // and CDATA section
825 *pValue = SDOM_newString(toText(v) -> cont);
828 *pValue = SDOM_newString(toComment(v) -> cont);
831 *pValue = SDOM_newString(toPI(v) -> cont);
834 // element and document (root) have void value
840 SDOM_Exception SDOM_setNodeValue(SablotSituation s, SDOM_Node n, const SDOM_char *value)
843 switch(v -> vt & VT_BASE)
846 toA(v) -> cont = value;
849 SE( __SDOM_canChangeUriNS(s, toNS(v) -> parent, toNS(v), value) );
850 toNS(v) -> uri = v -> getOwner().unexpand(value);
852 case VT_TEXT: // and CDATA section
853 toText(v) -> cont = value;
856 toComment(v) -> cont = value;
859 toPI(v) -> cont = value;
862 // element and document (root) have void value
863 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
868 SDOM_Exception SDOM_getParentNode(SablotSituation s, SDOM_Node n, SDOM_Node *pParent)
871 if (isRoot(v) || isAttr(v) || isNS(v))
874 *pParent = v -> parent;
878 SDOM_Exception SDOM_getFirstChild(SablotSituation s, SDOM_Node n, SDOM_Node *pFirstChild)
881 if (!isElement(v) && !isRoot(v))
885 int childCount = toE(v) -> contents.number();
887 *pFirstChild = (SDOM_Node)(toE(v) -> contents[0]);
894 SDOM_Exception SDOM_getLastChild(SablotSituation s, SDOM_Node n, SDOM_Node *pLastChild)
897 if (!isElement(v) && !isRoot(v))
901 int childCount = toE(v) -> contents.number();
903 *pLastChild = (SDOM_Node)(toE(v) -> contents.last());
910 SDOM_Exception SDOM_getPreviousSibling(SablotSituation s, SDOM_Node n, SDOM_Node *pPreviousSibling)
912 switch(toV(n) -> vt & VT_BASE)
917 *pPreviousSibling = NULL;
920 *pPreviousSibling = toV(n) -> getPreviousSibling();
925 SDOM_Exception SDOM_getNextSibling(SablotSituation s, SDOM_Node n, SDOM_Node *pNextSibling)
927 switch(toV(n) -> vt & VT_BASE)
932 *pNextSibling = NULL;
935 *pNextSibling = toV(n) -> getNextSibling();
940 SDOM_Exception SDOM_getChildNodeIndex(SablotSituation s, SDOM_Node n, int index, SDOM_Node *pChildNode)
943 if ( (!isElement(v) && !isRoot(v))
945 || index >= toE(v) -> contents.number() )
948 *pChildNode = (SDOM_Node)(toE(n) -> contents[index]);
952 SDOM_Exception SDOM_getChildNodeCount(SablotSituation s, SDOM_Node n, int *count)
955 if ( !isElement(v) && !isRoot(v) )
958 *count = toE(v) -> contents.number();
962 SDOM_Exception SDOM_getOwnerDocument(SablotSituation s, SDOM_Node n, SDOM_Document *pOwnerDocument)
965 *pOwnerDocument = NULL;
967 *pOwnerDocument = ownerDoc(n);
971 Bool hasElementChild(RootNode *r)
973 for (int i = 0; i < r -> contents.number(); i++)
974 if (isElement(r -> contents[i]))
979 // is first ancestor of second?
980 Bool isAncestor(Vertex *first, Vertex *second)
982 for (Vertex *p = second; p; p = p -> parent)
983 if (p == first) return TRUE;
987 SDOM_Exception SDOM_insertBefore(SablotSituation s, SDOM_Node n, SDOM_Node newChild, SDOM_Node refChild)
991 // check if v is an element (or root)
993 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
995 // check the type of newChild
997 SDOM_Err(s, SDOM_NOT_FOUND_ERR)
999 switch(basetype(newChild))
1004 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1006 // check if newChild is from the same doc
1007 if ((isRoot(v) && ownerDoc(newChild) != v) ||
1008 (!isRoot(v) && ownerDoc(v) != ownerDoc(newChild)))
1009 SDOM_Err(s, SDOM_WRONG_DOCUMENT_ERR);
1011 // check type of the reference child
1013 switch(toV(refChild) -> vt & VT_BASE)
1018 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1021 // check if newChild is not an ancestor of n
1022 if (isAncestor(toV(newChild), toV(n)))
1023 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1025 // check if not attempting to have more doc elements
1026 if (isRoot(v) && isElement(newChild) && hasElementChild(toRoot(v)))
1027 SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1029 // see if newChild needs to be removed from tree
1031 if (NULL != (parent = toV(newChild) -> parent))
1032 SE( SDOM_removeChild(s, parent, newChild) );
1035 // int ndx = toE(v) -> contents.getIndex(toV(newChild));
1037 // toE(v) -> contents.rm(ndx);
1040 // getTmpList(n).rmP(newChild);
1042 int ndx = toE(v) -> contents.getIndex(toV(newChild));
1044 toE(v) -> contents.rm(ndx);
1046 getTmpList(n).rmP(newChild);
1050 ndx = toE(v) -> contents.getIndex(toV(refChild));
1052 SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1053 toE(v) -> contents.insertBefore(toV(newChild), ndx);
1056 toE(v) -> contents.append(toV(newChild));
1057 // toE(v) -> contents.appendAndSetOrdinal(toV(newChild));
1058 toV(newChild) -> setParent(v);
1060 //old_parent's not used namespaces was cleaned by SDOM_removeChild
1061 SE( __SDOM_swallowParentNS(s, newChild) );
1066 SDOM_Exception SDOM_removeChild(SablotSituation s, SDOM_Node n, SDOM_Node oldChild)
1070 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1071 switch(toV(oldChild) -> vt & VT_BASE)
1076 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1078 if (toV(oldChild) -> parent != toV(n))
1079 SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1081 SE( __SDOM_dropParentNS(s, oldChild) );
1083 toE(v) -> removeChild(toV(oldChild));
1085 getTmpList(n).append(oldChild);
1090 SDOM_Exception SDOM_replaceChild(SablotSituation s, SDOM_Node n, SDOM_Node newChild, SDOM_Node oldChild)
1093 SE( SDOM_getParentNode(s, newChild, &tmp) );
1094 if (tmp) SE( SDOM_removeChild(s, tmp, newChild) );
1096 SE( SDOM_getNextSibling(s, oldChild, &tmp) );
1097 SE( SDOM_removeChild(s, n, oldChild) );
1098 SE( SDOM_insertBefore(s, n, newChild, tmp) );
1100 //_JP_ old version not satisfying DOM spec:
1101 //SE( SDOM_insertBefore(s, n, newChild, oldChild) );
1102 //SE( SDOM_removeChild(s, n, oldChild) );
1107 SDOM_Exception SDOM_appendChild(SablotSituation s, SDOM_Node n, SDOM_Node newChild)
1109 return SDOM_insertBefore(s, n, newChild, NULL);
1112 SDOM_Exception cloneVertex(SablotSituation, Tree *, Vertex *, int, Vertex **);
1114 SDOM_Exception cloneVertexList(SablotSituation s, Tree *t, VertexList *vlForeign, int deep, Element *tParent)
1117 for (int i = 0; i < vlForeign -> number(); i++)
1119 SE( cloneVertex(s, t, (*vlForeign)[i], deep, &newVertex) );
1120 // the following also handles atts and namespaces correctly
1121 tParent -> newChild(SIT(s), newVertex);
1126 SDOM_Exception cloneVertex(SablotSituation s, Tree *t, Vertex *foreign, int deep, Vertex **clone)
1128 Tree *tForeign = &(foreign -> getOwner());
1132 if (basetype(foreign) == VT_ROOT)
1133 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1135 // get the correctly unexpanded name
1136 if (basetype(foreign) == VT_ELEMENT ||
1137 basetype(foreign) == VT_ATTRIBUTE ||
1138 basetype(foreign) == VT_PI ||
1139 basetype(foreign) == VT_NAMESPACE)
1141 switch(basetype(foreign))
1144 tForeign -> expandQ(toE(foreign) -> getName(), expanded);
1147 tForeign -> expandQ(toA(foreign) -> getName(), expanded);
1150 tForeign -> expandQ(toNS(foreign) -> getName(), expanded);
1153 tForeign -> expandQ(toPI(foreign) -> getName(), expanded);
1156 q.setLocal(t -> unexpand(expanded.getLocal()));
1157 q.setPrefix(t -> unexpand(expanded.getPrefix()));
1158 q.setUri(t -> unexpand(expanded.getUri()));
1161 // create the actual copy
1162 switch(basetype(foreign))
1165 *clone = new(&(t -> getArena()))
1169 *clone = new(&(t -> getArena()))
1170 Attribute(*t, q, toA(foreign) -> cont, XSLA_NONE);
1173 *clone = new(&(t -> getArena())) NmSpace(*t,
1174 t -> unexpand(tForeign -> expand(toNS(foreign) -> prefix)),
1175 t -> unexpand(tForeign -> expand(toNS(foreign) -> uri)),
1176 toNS(foreign) -> kind);
1178 toNS(*clone) -> usageCount = toNS(foreign) -> usageCount;
1182 *clone = new(&(t -> getArena())) ProcInstr(*t, q.getLocal(), toPI(foreign) -> cont);
1185 *clone = new(&(t -> getArena())) Comment(*t, toComment(foreign) -> cont);
1189 *clone = new(&(t -> getArena())) Text(*t, toText(foreign) -> cont);
1190 if (toText(foreign) -> isCDATA())
1191 toText(*clone) -> beCDATA();
1195 if (isElement(foreign))
1197 // must clone atts and namespaces in any case
1198 assert(isElement(*clone));
1199 cloneVertexList(s, t, &(toE(foreign) -> atts), deep, toE(*clone));
1200 cloneVertexList(s, t, &(toE(foreign) -> namespaces), deep, toE(*clone));
1202 // if deep then recurse
1204 cloneVertexList(s, t, &(toE(foreign) -> contents), deep, toE(*clone));
1209 SDOM_Exception SDOM_cloneForeignNode(SablotSituation s, SDOM_Document d, SDOM_Node n, int deep, SDOM_Node *clone)
1211 SDOM_Exception se = cloneVertex(s, toTree(d), toV(n), deep, (Vertex**) clone);
1213 se = (se != SDOM_OK) ? se : __SDOM_dropParentNS(s, *clone);
1216 getTmpList(d).append(*clone);
1221 SDOM_Exception SDOM_cloneNode(SablotSituation s, SDOM_Node n, int deep, SDOM_Node *clone)
1223 return SDOM_cloneForeignNode(s, ownerDoc(n), n, deep, clone);
1226 SDOM_Exception SDOM_getAttribute(SablotSituation s, SDOM_Node n, const SDOM_char *name, SDOM_char **pValue)
1229 if (!isElement(toV(n)))
1230 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1231 Element *e = toE(toV(n));
1233 e -> setLogical(SIT(s), q, name, FALSE);
1235 Bool isXMLNS = isXMLNS_(q, e);
1237 v = e -> atts.find(q);
1239 v = e -> namespaces.find(
1240 q.getLocal() != UNDEF_PHRASE ? q.getLocal() : UNDEF_PHRASE);
1242 *pValue = SDOM_newString("");
1246 *pValue = SDOM_newString(toA(v) -> cont);
1248 *pValue = SDOM_newString(e -> getOwner().expand(toNS(v) -> uri));
1253 SDOM_Exception SDOM_getAttributeNS(SablotSituation s, SDOM_Node n, SDOM_char *uri, SDOM_char *local, SDOM_char **pValue)
1256 if (!isElement(toV(n)))
1257 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1258 Element *e = toE(toV(n));
1261 Bool isXMLNS = ( !strcmp((char*)uri,theXMLNSNamespace) );
1263 const int attcount = e -> atts.number();
1264 for (int i = 0; i < attcount; i++) {
1265 q = toA(e->atts[i]) -> name;
1266 if (!strcmp((char*)local, (char*)(e -> getOwner().expand(q.getLocal())))
1267 && !strcmp((char*)uri, (char*)(e -> getOwner().expand(q.getUri())))) {
1273 const int nscount = e -> namespaces.number();
1274 for (int i = 0; i < nscount; i++) {
1275 q = toNS(e->namespaces[i]) -> name;
1276 if (!strcmp((char*)local, (char*)(e -> getOwner().expand(toNS(e->namespaces[i])->prefix)))) {
1277 v = e -> namespaces[i];
1283 *pValue = SDOM_newString("");
1287 *pValue = SDOM_newString(toA(v) -> cont);
1289 *pValue = SDOM_newString(e -> getOwner().expand(toNS(v) -> uri));
1294 SDOM_Exception SDOM_getAttributeNode(SablotSituation s, SDOM_Node n, const SDOM_char *name, SDOM_Node *attr)
1297 if ( !isElement(toV(n)) )
1298 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1299 Element *e = toE(toV(n));
1301 e -> setLogical(SIT(s), q, name, FALSE);
1303 Bool isXMLNS = isXMLNS_(q, e);
1305 v = e -> atts.find(q);
1308 v = e -> namespaces.find(
1309 q.getLocal() != e -> getOwner().stdPhrase(PHRASE_XMLNS)?
1310 q.getLocal() : UNDEF_PHRASE);
1316 *attr = (SDOM_Node)v;
1321 SDOM_Exception SDOM_getAttributeNodeNS(SablotSituation s, SDOM_Node n, SDOM_char *uri, SDOM_char *local, SDOM_Node *attr)
1324 if (!isElement(toV(n)))
1325 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1326 Element *e = toE(toV(n));
1329 if ( strcmp((char*)uri,theXMLNSNamespace) ) {
1331 const int attcount = e -> atts.number();
1332 for (int i = 0; i < attcount; i++) {
1333 q = toA(e->atts[i]) -> name;
1334 if (!strcmp((char*)local, (char*)(e -> getOwner().expand(q.getLocal())))
1335 && !strcmp((char*)uri, (char*)(e -> getOwner().expand(q.getUri())))) {
1342 const int nscount = e -> namespaces.number();
1344 if ( !strcmp(local,"xmlns") )
1349 for (int i = 0; i < nscount; i++) {
1350 q = toNS(e->namespaces[i]) -> name;
1351 if (!strcmp(pre, (char*)(e -> getOwner().expand(toNS(e->namespaces[i])->prefix)))) {
1352 v = e -> namespaces[i];
1361 SDOM_Exception SDOM_getAttributeNodeIndex(SablotSituation s, SDOM_Node n, const int index, SDOM_Node *attr)
1363 if (!isElement(toV(n)))
1364 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1365 Element *e = toE(toV(n));
1366 int nscount = e -> namespaces.number();
1368 if (index < 0 || index >= nscount + e -> atts.number() )
1371 if (index < nscount)
1372 *attr = (SDOM_Node)(e -> namespaces[index]);
1374 *attr = (SDOM_Node)(e -> atts[index-nscount]);
1378 SDOM_Exception SDOM_getAttributeNodeCount(SablotSituation s, SDOM_Node n, int *count)
1380 if (!isElement(toV(n)))
1381 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1382 Element *e = toE(toV(n));
1383 *count = e -> namespaces.number() + e -> atts.number();
1388 SDOM_Exception SDOM_setAttribute(SablotSituation s, SDOM_Node n, const SDOM_char *attName, const SDOM_char *attValue)
1391 if (!isElement(toV(n)))
1392 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1393 Element *e = toE(toV(n));
1395 e -> setLogical(SIT(s), q, attName, FALSE);
1397 if ( !isXMLNS_(q, e) ) {
1398 v = e -> atts.find(q);
1400 SE( _SDOM_createAttributeWithParent(s, ownerDoc(e), (SDOM_Node*) &v, attName, e));
1402 getTmpList(n).rmP(v);
1404 e -> atts.append(toA(v));
1405 toV(v) -> setParent(e);
1407 SE( SDOM_setNodeValue(s, v, attValue) );
1408 } else { //attribute is namespace declaration
1409 v = e -> namespaces.find(q.getLocal() != e -> getOwner().stdPhrase(PHRASE_XMLNS) ? q.getLocal() : UNDEF_PHRASE);
1411 SE( _SDOM_createAttributeWithParent(s, ownerDoc(e), (SDOM_Node*) &v, attName, e));
1413 getTmpList(n).rmP(v);
1415 e -> namespaces.append(toNS(v));
1416 toV(v) -> setParent(e);
1418 SE( SDOM_setNodeValue(s, v, attValue) );
1420 toNS(v) -> kind = NSKIND_DECLARED;
1421 SE( __SDOM_refreshNS(s, n, toNS(v)) );
1429 SDOM_Exception SDOM_setAttributeNS(SablotSituation s, SDOM_Node n, const SDOM_char *uri, const SDOM_char *qName, const SDOM_char *value)
1431 if (!isElement(toV(n)))
1432 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1434 if ( !isValidQName((char*)qName) )
1435 SDOM_Err(s, SDOM_INVALID_CHARACTER_ERR);
1438 Element *e = toE(toV(n));
1440 char *colon = strchr((char*)qName,':');
1442 if ( colon ) { //qName has prefix
1445 SDOM_Err(s, SDOM_NAMESPACE_ERR);
1447 prefix.nset((char*)qName, (int)colon - (int)qName);
1449 if ( !strcmp((const char*)prefix,"xml") && strcmp(theXMLNamespace,uri) )
1450 //redefinition of xml-namespace
1451 SDOM_Err(s, SDOM_NAMESPACE_ERR);
1453 if ( !strcmp((const char*)prefix,"xmlns") && strcmp(theXMLNSNamespace,uri) )
1454 //redefinition of xmlns-namespace
1455 SDOM_Err(s, SDOM_NAMESPACE_ERR);
1457 q.setPrefix(ownerDoc(toE(n))->dict().insert((const char*)prefix));
1458 q.setLocal(ownerDoc(toE(n))->dict().insert((const char*)((int)colon + 1)));
1459 q.setUri(ownerDoc(toE(n))->dict().insert((const char*)uri));
1463 q.setPrefix(UNDEF_PHRASE);
1464 q.setLocal(ownerDoc(toE(n))->dict().insert((const char*)qName));
1466 if ( uri && strcmp((char*)uri,"") ) {
1467 q.setUri(ownerDoc(toE(n))->dict().insert((const char*)uri));
1469 q.setUri(UNDEF_PHRASE);
1474 SE( SDOM_getAttributeNodeNS(s, n,
1475 (SDOM_char*)(e -> getOwner().expand(q.getUri())),
1476 (SDOM_char*)(e -> getOwner().expand(q.getLocal())),
1479 if ( strcmp((char*)uri, theXMLNSNamespace) ) {
1482 //attr with the same uri:local found
1483 if ( q.getPrefix() == toA(replaced)->name.getPrefix() ) {
1486 //prefix != replaced.prefix
1487 if ( q.getPrefix() != UNDEF_PHRASE ) {
1488 SE( __SDOM_touchNS(s, n,
1491 NSKIND_PARENT, 0) );
1492 e -> namespaces.decPrefixUsage(toA(replaced)->name.getPrefix());
1494 toA(replaced)->name.setPrefix(q.getPrefix());
1497 //attr with the same uri:local NOT found
1498 if ( q.getPrefix() != UNDEF_PHRASE )
1499 SE( __SDOM_touchNS(s, n,
1502 NSKIND_PARENT, 0) );
1503 replaced = new(&(toTree(ownerDoc(e)) -> getArena()))
1504 Attribute(*toTree(ownerDoc(e)), q, (char*)"", XSLA_NONE);
1505 e -> atts.append(toA(replaced));
1506 toV(replaced) -> setParent(e);
1508 SE( SDOM_setNodeValue(s, replaced, value) );
1512 SE( __SDOM_touchNSByChar(s, n,
1513 (SDOM_char*)(e -> getOwner().expand(q.getLocal())),
1515 NSKIND_DECLARED, 0) );
1521 SDOM_Exception SDOM_setAttributeNode(SablotSituation s, SDOM_Node n, SDOM_Node attnode, SDOM_Node *replaced)
1523 if ( !( isElement(toV(n)) && (isAttr(toV(attnode))
1524 || isNS(toV(attnode))) ) )
1525 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1526 if ( ownerDoc(n) != ownerDoc(attnode) )
1527 SDOM_Err(s, SDOM_WRONG_DOCUMENT_ERR);
1528 if ( toV(attnode) -> parent )
1529 SDOM_Err(s, SDOM_INUSE_ATTRIBUTE_ERR);
1530 Element *e = toE(toV(n));
1532 if ( isAttr(toV(attnode)) ) {
1534 e -> getOwner().expandQStr(toA(attnode) -> getName(), attname);
1535 SE( SDOM_getAttributeNode(s, n, (SDOM_char*)attname, replaced) );
1537 //attr with the same prefix:local found
1538 if ( toA(attnode)->name.getUri() == toA(*replaced)->name.getUri() ) {
1540 // int ndx = e -> atts.findNdx(toA(*replaced)->name);
1541 // toV(*replaced) -> parent = NULL;
1543 // getTmpList(n).append(*replaced);
1545 // e -> atts[ndx] = toV(attnode);
1547 int ndx = toV(*replaced) -> ordinal;
1548 toV(*replaced) -> parent = NULL;
1550 getTmpList(n).append(*replaced);
1551 getTmpList(n).rmP(attnode);
1553 e -> atts[ndx] = toV(attnode);
1554 toV(attnode) -> ordinal = ndx;
1557 //attnode.uri != replaced.uri
1558 if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1559 SE( __SDOM_touchNS(s, n,
1560 toA(attnode)->name.getPrefix(),
1561 toA(attnode)->name.getUri(),
1562 NSKIND_PARENT, 1) );
1563 // int ndx = e -> atts.findNdx(toA(*replaced)->name);
1564 // toV(*replaced) -> parent = NULL;
1566 // getTmpList(n).append(*replaced);
1568 // e -> atts[ndx] = toV(attnode);
1570 int ndx = toV(*replaced) -> ordinal;
1571 toV(*replaced) -> parent = NULL;
1573 getTmpList(n).append(*replaced);
1574 getTmpList(n).rmP(attnode);
1576 e -> atts[ndx] = toV(attnode);
1577 toV(attnode) -> ordinal = ndx;
1581 //attr with the same prefix:local NOT found
1582 if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1583 SE( __SDOM_touchNS(s, n,
1584 toA(attnode)->name.getPrefix(),
1585 toA(attnode)->name.getUri(),
1586 NSKIND_PARENT, 0) );
1588 getTmpList(n).rmP(attnode);
1590 e -> atts.append(toA(attnode));
1592 toV(attnode) -> setParent(e);
1595 // attnode is namespace
1596 int ndx = e -> namespaces.findNdx(toNS(attnode)->prefix);
1598 //namespace with the attnode.prefix exists
1599 NmSpace *nm = toNS(e -> namespaces[ndx]);
1600 if ( nm -> uri == toNS(attnode) -> uri ) {
1601 //namespace with attnode.prefix has attnode.uri
1603 getTmpList(n).rmP(attnode);
1605 toV(nm) -> parent = NULL;
1607 getTmpList(n).append(nm);
1609 e -> namespaces[ndx] = toV(attnode);
1610 toV(attnode) -> setParent(e);
1611 toV(attnode) -> ordinal = ndx;
1612 toNS(attnode)->kind = nm->kind;
1613 toNS(attnode)->usageCount = nm->usageCount;
1614 *replaced = (SDOM_Node)nm;
1616 //namespace with attnode.prefix has NOT attnode.uri
1617 if ( nm -> usageCount != 0 || nm -> kind == NSKIND_DECLARED ) {
1619 SDOM_Err(s, SDOM_NAMESPACE_ERR);
1621 // namespace NOT used
1623 getTmpList(n).rmP(attnode);
1625 toV(nm) -> parent = NULL;
1627 getTmpList(n).append(nm);
1629 e -> namespaces[ndx] = toV(attnode);
1630 toV(attnode) -> setParent(e);
1631 toV(attnode) -> ordinal = ndx;
1632 toNS(attnode)->kind = NSKIND_DECLARED;
1633 toNS(attnode)->usageCount = 0;
1634 *replaced = (SDOM_Node)nm;
1638 //namespace with attnode.prefix NOT exists
1640 toNS(attnode)->kind = NSKIND_DECLARED;
1641 toNS(attnode)->usageCount = 0;
1643 getTmpList(n).rmP(attnode);
1645 e -> namespaces.append(toNS(attnode));
1646 toV(attnode) -> setParent(e);
1647 SE( __SDOM_refreshNS(s, n, toNS(attnode)) );
1653 SDOM_Exception SDOM_setAttributeNodeNS(SablotSituation s, SDOM_Node n, SDOM_Node attnode, SDOM_Node *replaced)
1655 if ( !( isElement(toV(n)) && (isAttr(toV(attnode))
1656 || isNS(toV(attnode))) ) )
1657 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1658 if ( ownerDoc(n) != ownerDoc(attnode) )
1659 SDOM_Err(s, SDOM_WRONG_DOCUMENT_ERR);
1660 if ( toV(attnode) -> parent )
1661 SDOM_Err(s, SDOM_INUSE_ATTRIBUTE_ERR);
1662 Element *e = toE(toV(n));
1664 if ( isAttr(toV(attnode)) ) {
1666 e -> getOwner().expandQStr(toA(attnode) -> getName(), attname);
1667 SE( SDOM_getAttributeNodeNS(s, n,
1668 (SDOM_char*)(e -> getOwner().expand(toA(attnode)->name.getUri())),
1669 (SDOM_char*)(e -> getOwner().expand(toA(attnode)->name.getLocal())),
1672 //attr with the same uri:local found
1673 if ( toA(attnode)->name.getPrefix() == toA(*replaced)->name.getPrefix() ) {
1675 // int ndx = e -> atts.findNdx(toA(*replaced)->name);
1676 // toV(*replaced) -> parent = NULL;
1678 // getTmpList(n).append(*replaced);
1680 // e -> atts[ndx] = toV(attnode);
1682 int ndx = toV(*replaced) -> ordinal;
1683 toV(*replaced) -> parent = NULL;
1685 getTmpList(n).append(*replaced);
1686 getTmpList(n).rmP(attnode);
1688 e -> atts[ndx] = toV(attnode);
1689 toV(attnode) -> ordinal = ndx;
1694 //attnode.prefix != replaced.prefix
1695 if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1696 SE( __SDOM_touchNS(s, n,
1697 toA(attnode)->name.getPrefix(),
1698 toA(attnode)->name.getUri(),
1699 NSKIND_PARENT, 1) );
1700 if ( toA(*replaced)->name.getPrefix() != UNDEF_PHRASE )
1701 e -> namespaces.decPrefixUsage(toA(*replaced)->name.getPrefix());
1702 // int ndx = e -> atts.findNdx(toA(*replaced)->name);
1703 // toV(*replaced) -> parent = NULL;
1705 // getTmpList(n).append(*replaced);
1707 // e -> atts[ndx] = toV(attnode);
1709 int ndx = toV(*replaced) -> ordinal;
1710 toV(*replaced) -> parent = NULL;
1712 getTmpList(n).rmP(attnode);
1713 getTmpList(n).append(*replaced);
1715 e -> atts[ndx] = toV(attnode);
1716 toV(attnode) -> ordinal = ndx;
1720 //attr with the same uri:local NOT found
1721 if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1722 SE( __SDOM_touchNS(s, n,
1723 toA(attnode)->name.getPrefix(),
1724 toA(attnode)->name.getUri(),
1725 NSKIND_PARENT, 0) );
1727 getTmpList(n).rmP(attnode);
1729 e -> atts.append(toA(attnode));
1731 toV(attnode) -> setParent(e);
1734 // attnode is namespace
1735 int ndx = e -> namespaces.findNdx(toNS(attnode)->prefix);
1737 //namespace with the attnode.prefix exists
1738 NmSpace *nm = toNS(e -> namespaces[ndx]);
1739 if ( nm -> uri == toNS(attnode) -> uri ) {
1740 //namespace with attnode.prefix has attnode.uri
1742 getTmpList(n).rmP(attnode);
1744 toV(nm) -> parent = NULL;
1746 getTmpList(n).append(nm);
1748 e -> namespaces[ndx] = toV(attnode);
1749 toV(attnode) -> setParent(e);
1750 toV(attnode) -> ordinal = ndx;
1751 toNS(attnode)->kind = nm->kind;
1752 toNS(attnode)->usageCount = nm->usageCount;
1753 *replaced = (SDOM_Node)nm;
1755 //namespace with attnode.prefix has NOT attnode.uri
1756 if ( nm -> usageCount != 0 || nm -> kind == NSKIND_DECLARED ) {
1758 return SDOM_NAMESPACE_ERR;
1760 // namespace NOT used
1762 getTmpList(n).rmP(attnode);
1764 toV(nm) -> parent = NULL;
1766 getTmpList(n).append(nm);
1768 e -> namespaces[ndx] = toV(attnode);
1769 toV(attnode) -> setParent(e);
1770 toV(attnode) -> ordinal = ndx;
1771 toNS(attnode)->kind = NSKIND_DECLARED;
1772 toNS(attnode)->usageCount = 0;
1773 *replaced = (SDOM_Node)nm;
1777 //namespace with attnode.prefix NOT exists
1779 toNS(attnode)->kind = NSKIND_DECLARED;
1780 toNS(attnode)->usageCount = 0;
1782 getTmpList(n).rmP(attnode);
1784 e -> namespaces.append(toNS(attnode));
1785 toV(attnode) -> setParent(e);
1786 SE( __SDOM_refreshNS(s, n, toNS(attnode)) );
1793 SDOM_Exception SDOM_removeAttributeNode(SablotSituation s, SDOM_Node n, SDOM_Node attnode, SDOM_Node *removed)
1795 if (!isElement(toV(n)))
1796 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1797 Element *e = toE(toV(n));
1799 if (isAttr(attnode))
1801 int attNdx = e -> atts.findNdx(toA(attnode)->name);
1805 Vertex *tmp = e -> atts[attNdx];
1807 tmp -> parent = NULL;
1808 e -> atts.rm(attNdx);
1810 getTmpList(n).append(tmp);
1812 if (toA(tmp) -> name.getPrefix() != UNDEF_PHRASE)
1813 e -> namespaces.decPrefixUsage(toA(tmp) -> name.getPrefix());
1816 SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1821 int attNdx = e -> namespaces.findNdx(toNS(attnode)->prefix);
1824 if (toNS(e -> namespaces[attNdx]) -> usageCount != 0)
1825 SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
1827 Vertex *tmp = e -> namespaces[attNdx];
1829 tmp -> parent = NULL;
1830 e -> namespaces.rm(attNdx);
1832 getTmpList(n).append(tmp);
1836 SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1844 SDOM_Exception SDOM_removeAttribute(SablotSituation s, SDOM_Node n, const SDOM_char *name)
1847 if (!isElement(toV(n)))
1848 SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1849 Element *e = toE(toV(n));
1851 e -> setLogical(SIT(s), q, name, FALSE);
1852 if (!isXMLNS_(q, e))
1854 int attNdx = e -> atts.findNdx(q);
1858 Vertex *tmp = e -> atts[attNdx];
1860 e -> atts[attNdx] -> parent = NULL;
1861 e -> atts.rm(attNdx);
1863 getTmpList(n).append(tmp);
1866 if (toA(tmp) -> name.getPrefix() != UNDEF_PHRASE)
1867 e -> namespaces.decPrefixUsage(toA(tmp) -> name.getPrefix());
1873 int attNdx = e -> namespaces.findNdx(
1874 q.getLocal() != e -> getOwner().stdPhrase(PHRASE_XMLNS) ?
1875 q.getLocal() : UNDEF_PHRASE);
1879 if (toNS(e -> namespaces[attNdx]) -> usageCount != 0)
1880 return SDOM_NO_MODIFICATION_ALLOWED_ERR;
1882 e -> namespaces[attNdx] -> parent = NULL;
1883 e -> namespaces.rm(attNdx);
1890 SDOM_Exception SDOM_getAttributeElement(SablotSituation s, SDOM_Node attr, SDOM_Node *owner)
1892 Vertex *v = toV(attr);
1893 if ( isAttr(v) | isNS(v) )
1895 *owner = v -> parent;
1899 return SDOM_HIERARCHY_REQUEST_ERR;
1902 SDOM_Exception SDOM_getAttributeList(SablotSituation s, SDOM_Node n, SDOM_NodeList *pAttrList)
1904 *pAttrList = new CList;
1905 if (isElement(toV(n)))
1908 NSList& namespaces = toE(toV(n)) -> namespaces;
1909 for (i = 0; i < namespaces.number(); i++)
1910 ((CList*)(*pAttrList)) -> append(namespaces[i]);
1911 AttList& atts = toE(toV(n)) -> atts;
1912 for (i = 0; i < atts.number(); i++)
1913 ((CList*)(*pAttrList)) -> append(atts[i]);
1922 SDOM_Exception SDOM_docToString(SablotSituation s, SDOM_Document d, SDOM_char **pSerialized)
1924 // using explicit temp because of BeOS
1925 char *serializedTemp = NULL;
1926 toTree(d) -> serialize(SIT(s), serializedTemp);
1927 *pSerialized = serializedTemp;
1932 SDOM_Exception SDOM_nodeToString(SablotSituation s, SDOM_Document d,
1934 SDOM_char **pSerialized)
1936 char *serializedTemp = NULL;
1937 toTree(d) -> serializeNode(SIT(s), toE(n), serializedTemp);
1938 *pSerialized = serializedTemp;
1946 SDOM_Exception SDOM_getNodeListLength(SablotSituation s, SDOM_NodeList l, int *pLength)
1948 *pLength = ((CList*)l) -> number();
1952 SDOM_Exception SDOM_getNodeListItem(SablotSituation s, SDOM_NodeList l, int index, SDOM_Node *pItem)
1954 if ((index < 0) || (index >= ((CList*)l) -> number()))
1955 SDOM_Err(s, SDOM_INDEX_SIZE_ERR);
1956 *pItem = ((CList*)l) -> operator[](index);
1960 SDOM_Exception SDOM_disposeNodeList(SablotSituation s, SDOM_NodeList l)
1962 if (!((CList*)l) -> decRefCount())
1972 SDOM_Exception SDOM_xql(SablotSituation s, const SDOM_char *query, SDOM_Node currentNode, SDOM_NodeList *pResult)
1974 RootNode &root = toV(currentNode) -> getOwner().getRoot();
1976 // find the document element
1978 for (i = 0; i < root.contents.number(); i++)
1979 if (isElement(root.contents[i])) break;
1981 Element *docElement = (i < root.contents.number()) ?
1982 toE(root.contents[i]) : &root;
1983 Expression queryEx(*docElement);
1986 // parse the query string as a non-pattern
1987 if (queryEx.parse(SIT(s), (char*)query, FALSE, TRUE))
1988 SDOM_Err(s, SDOM_QUERY_PARSE_ERR);
1990 // create an initial context
1991 GP( Context ) dummy = new Context(NULL); //_cn_ no current node
1994 (*c).set(toV(currentNode));
1996 // create the result context
1997 if (queryEx.createContext(SIT(s), c))
1998 SDOM_Err(s, SDOM_QUERY_EXECUTION_ERR);
2000 // preserve the CList
2001 (*c).getArrayForDOM() -> incRefCount();
2003 *pResult = (SDOM_NodeList) (*c).getArrayForDOM();
2007 SDOM_Exception SDOM_xql_ns(SablotSituation s, const SDOM_char *query, SDOM_Node currentNode, char** nsmap, SDOM_NodeList *pResult)
2009 //RootNode &root = toV(currentNode) -> getOwner().getRoot();
2011 // find the document element
2013 //for (i = 0; i < root.contents.number(); i++)
2014 // if (isElement(root.contents[i])) break;
2015 GP( Tree ) tree = new Tree(Str("noscheme:dummy-tree"), false);
2017 q.setLocal((*tree).unexpand(Str("dummy-root")));
2018 Element *e = new(&((*tree).getArena())) Element(*tree, q);
2019 e -> setSubtreeInfo((*tree).getRootSubtree());
2020 char ** aux = nsmap;
2023 char *uri = *(aux + 1);
2024 NmSpace *nm = new(&((*tree).getArena()))
2025 NmSpace(*tree, (*tree).unexpand(pref), (*tree).unexpand(uri),
2026 false, NSKIND_DECLARED);
2027 e -> newChild(SIT(s), nm);
2031 Expression queryEx(*e);
2034 // parse the query string as a non-pattern
2035 if (queryEx.parse(SIT(s), (char*)query, FALSE, TRUE))
2036 SDOM_Err(s, SDOM_QUERY_PARSE_ERR);
2038 // create an initial context
2039 GP( Context ) dummy = new Context(NULL); //_cn_ no current node
2042 (*c).set(toV(currentNode));
2044 // create the result context
2045 if (queryEx.createContext(SIT(s), c))
2046 SDOM_Err(s, SDOM_QUERY_EXECUTION_ERR);
2048 // preserve the CList
2049 (*c).getArrayForDOM() -> incRefCount();
2051 *pResult = (SDOM_NodeList) (*c).getArrayForDOM();
2056 // exception retrieval
2059 int SDOM_getExceptionCode(SablotSituation s)
2061 return SIT(s).getSDOMExceptionCode();
2064 char* SDOM_getExceptionMessage(SablotSituation s)
2066 return SDOM_newString(
2067 SDOM_ExceptionMsg[SDOM_getExceptionCode(s)]);
2070 void SDOM_getExceptionDetails(
2077 Str message_, documentURI_;
2080 SIT(s).getSDOMExceptionExtra(code_, message_, documentURI_, fileLine_);
2082 *fileLine = fileLine_;
2083 *documentURI = SDOM_newString(documentURI_);
2084 *message = SDOM_newString(message_);
2093 void SDOM_setNodeInstanceData(SDOM_Node n, void *data)
2095 toV(n) -> setInstanceData(data);
2098 void* SDOM_getNodeInstanceData(SDOM_Node n)
2100 return toV(n) -> getInstanceData();
2103 void SDOM_setDisposeCallback(SDOM_NodeCallback *f)
2105 theDisposeCallback = f;
2108 SDOM_NodeCallback* SDOM_getDisposeCallback()
2110 return theDisposeCallback;
2116 void SDOM_tmpListDump(SDOM_Document doc, int p)
2118 getTmpList(doc).dump(p);
2122 SDOM_Exception SDOM_compareNodes(SablotSituation s, SDOM_Node n1, SDOM_Node n2, int *res)
2124 if (&(toV(n1) -> getOwner()) == &(toV(n2) -> getOwner()) ) //the same owner
2126 int s1 = toV(n1) -> stamp;
2127 int s2 = toV(n2) -> stamp;
2137 *res = strcmp( (char*)(toV(n1) -> getOwner().getURI()),
2138 (char*)(toV(n2) -> getOwner().getURI()) );
2143 #endif /* ENABLE_DOM */