|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Node functions implementation |
|
15 // |
|
16 |
|
17 #include <stdlib.h> |
|
18 |
|
19 #include <xml/dom/xmlengelement.h> |
|
20 #include <xml/dom/xmlengdocument.h> |
|
21 #include <xml/dom/xmlengnamespace.h> |
|
22 #include <xml/dom/xmlengtext.h> |
|
23 #include <xml/dom/xmlenguserdata.h> |
|
24 #include <xml/dom/xmlengnodelist.h> |
|
25 #include <stdapis/libxml2/libxml2_parser.h> |
|
26 #include <stdapis/libxml2/libxml2_globals.h> |
|
27 #include <stdapis/libxml2/libxml2_xmlio.h> |
|
28 #include "libxml2_xmlsave_private.h" |
|
29 #include "libxml2_tree_private.h" |
|
30 #include "xmlengdomdefs.h" |
|
31 #include <xml/dom/xmlengerrors.h> |
|
32 #include <xml/utils/xmlengmem.h> |
|
33 #include <xml/utils/xmlengxestrings.h> |
|
34 |
|
35 // --------------------------------------------------------------------------------------------- |
|
36 // Unlinks the internal libxml2's node from double-linked list. |
|
37 // Relinks neighbour nodes.The node stays virtually linked to its old neighbours! Use with care!! |
|
38 // |
|
39 // No checks are made; nor parent's, nor node's properties updated |
|
40 // --------------------------------------------------------------------------------------------- |
|
41 // |
|
42 void TXmlEngNode::DoUnlinkNode() |
|
43 { |
|
44 xmlNodePtr& next = LIBXML_NODE->next; |
|
45 xmlNodePtr& prev = LIBXML_NODE->prev; |
|
46 // Unlink this node; relink neighbors |
|
47 if (prev) |
|
48 { |
|
49 prev->next = next; |
|
50 } |
|
51 else |
|
52 { |
|
53 // Unlinked node is the first in the list |
|
54 // 'children' or 'properties' property of the parent node |
|
55 // must be updated (depending on the type of the node: content node or attribute) |
|
56 xmlNodePtr& parent = LIBXML_NODE->parent; |
|
57 // Ugly, but works :) |
|
58 xmlNodePtr* first = ((LIBXML_NODE->type == XML_ATTRIBUTE_NODE) |
|
59 ? reinterpret_cast<xmlNodePtr*>(&(parent->properties)) |
|
60 : &(parent->children)); |
|
61 *first = next; |
|
62 } |
|
63 if (next) |
|
64 { |
|
65 next->prev = prev; |
|
66 } |
|
67 else |
|
68 { |
|
69 // Unlinked node is the last in the list (of elements or attributes) |
|
70 // 'last' property of the parent element must be updated (for content nodes only) |
|
71 if(LIBXML_NODE->type != XML_ATTRIBUTE_NODE) |
|
72 { |
|
73 LIBXML_NODE->parent->last = prev; |
|
74 } |
|
75 } |
|
76 } |
|
77 |
|
78 |
|
79 // --------------------------------------------------------------------------------------------- |
|
80 // Inserts the node in a double-linked list of nodes before specified node. |
|
81 // |
|
82 // No checks are made; nor parent's, nor node's properties updated (except prev/next) |
|
83 // --------------------------------------------------------------------------------------------- |
|
84 // |
|
85 void TXmlEngNode::LinkBefore(TXmlEngNode aTargetNode) |
|
86 { |
|
87 xmlNodePtr node = INTERNAL_NODEPTR(aTargetNode); |
|
88 xmlNodePtr& prev = node->prev; |
|
89 LIBXML_NODE->next = node; |
|
90 LIBXML_NODE->prev = prev; |
|
91 prev->next = LIBXML_NODE; |
|
92 node->prev = LIBXML_NODE; |
|
93 } |
|
94 |
|
95 // --------------------------------------------------------------------------------------------- |
|
96 // Get innerXML string. This method return all content of the node. |
|
97 // Output text does not include node markup. |
|
98 // |
|
99 // @note Returned TString should be freed |
|
100 // --------------------------------------------------------------------------------------------- |
|
101 // |
|
102 EXPORT_C TInt TXmlEngNode::InnerXmlL(RBuf8& aBuffer) |
|
103 { |
|
104 if(aBuffer.Length()) |
|
105 { |
|
106 aBuffer.Close(); |
|
107 } |
|
108 if(IsNull()) |
|
109 { |
|
110 User::Leave(KXmlEngErrWrongUseOfAPI); |
|
111 } |
|
112 |
|
113 if(NodeType() == TXmlEngNode::EDocument) |
|
114 { |
|
115 return OwnerDocument().SaveL(aBuffer, OwnerDocument(), NULL); |
|
116 } |
|
117 aBuffer.FillZ(); |
|
118 RXmlEngNodeList<TXmlEngNode> nodeList; |
|
119 RBuf8 tmpStr; |
|
120 GetChildNodes(nodeList); |
|
121 TXmlEngNode tmpNode; |
|
122 while(nodeList.HasNext()) |
|
123 { |
|
124 tmpNode = nodeList.Next(); |
|
125 tmpNode.OuterXmlL(tmpStr); |
|
126 CleanupClosePushL(tmpStr); |
|
127 if((aBuffer.MaxSize() - aBuffer.Size()) < tmpStr.Size()) |
|
128 { |
|
129 aBuffer.ReAllocL(aBuffer.MaxSize() + tmpStr.Size() + 1); |
|
130 } |
|
131 aBuffer.Append(tmpStr); |
|
132 CleanupStack::PopAndDestroy(); |
|
133 } |
|
134 tmpStr.Close(); |
|
135 |
|
136 return aBuffer.Size(); |
|
137 } |
|
138 |
|
139 // --------------------------------------------------------------------------------------------- |
|
140 // Get outerXML string. This method return all content of the node. |
|
141 // Output text includes node markup. |
|
142 // |
|
143 // @note Returned TString should be freed |
|
144 // |
|
145 // --------------------------------------------------------------------------------------------- |
|
146 // |
|
147 EXPORT_C TInt TXmlEngNode::OuterXmlL(RBuf8& aBuffer) |
|
148 { |
|
149 TInt size = -1; |
|
150 if(aBuffer.Length()) |
|
151 { |
|
152 aBuffer.Close(); |
|
153 } |
|
154 if(IsNull()) |
|
155 { |
|
156 User::Leave(KXmlEngErrWrongUseOfAPI); |
|
157 } |
|
158 |
|
159 if(NodeType() == TXmlEngNode::EDocument) |
|
160 { |
|
161 return OwnerDocument().SaveL(aBuffer, OwnerDocument(), NULL); |
|
162 } |
|
163 |
|
164 xmlSaveCtxt ctxt; |
|
165 xmlOutputBufferPtr buf; |
|
166 |
|
167 /* |
|
168 * save the content to a temp buffer. |
|
169 */ |
|
170 buf = xmlAllocOutputBuffer(NULL); |
|
171 OOM_IF_NULL(buf); |
|
172 |
|
173 memset(&ctxt, 0, sizeof(ctxt)); |
|
174 ctxt.doc = LIBXML_NODE->doc; |
|
175 ctxt.buf = buf; |
|
176 ctxt.level = 0; |
|
177 ctxt.format = 0; |
|
178 |
|
179 xmlSaveCtxtInit(&ctxt); |
|
180 |
|
181 xmlNodeDumpOutputInternal(&ctxt, LIBXML_NODE); |
|
182 if(xmlOOMFlag()) |
|
183 { |
|
184 xmlOutputBufferClose(buf); |
|
185 OOM_HAPPENED; |
|
186 } |
|
187 |
|
188 size = buf->buffer->use; |
|
189 if(size > 0) |
|
190 { |
|
191 // frees any previous contents of aBuffer argument |
|
192 aBuffer.Assign(buf->buffer->content,size,size); |
|
193 // To prevent it from freeing |
|
194 buf->buffer->content = NULL; |
|
195 } |
|
196 xmlOutputBufferClose(buf); |
|
197 |
|
198 // Leaves with KErrNoMemory |
|
199 TEST_OOM_FLAG; |
|
200 if (size < 0) |
|
201 { |
|
202 XmlEngLeaveL(KXmlEngErrNegativeOutputSize); |
|
203 } |
|
204 |
|
205 return size; |
|
206 } |
|
207 |
|
208 // --------------------------------------------------------------------------------------------- |
|
209 // Moves the node to become the first in the list of its siblings |
|
210 // Node is expected to have a parent. |
|
211 // --------------------------------------------------------------------------------------------- |
|
212 // |
|
213 EXPORT_C void TXmlEngNode::SetAsFirstSibling() |
|
214 { |
|
215 if (LIBXML_NODE->type == XML_NAMESPACE_DECL) |
|
216 { |
|
217 return; |
|
218 } |
|
219 xmlNodePtr& prev = LIBXML_NODE->prev; |
|
220 if (prev) |
|
221 { |
|
222 DoUnlinkNode(); |
|
223 // Insert as first |
|
224 prev = NULL; |
|
225 xmlNodePtr& parent = LIBXML_NODE->parent; |
|
226 // Ugly, but works :) |
|
227 xmlNodePtr* first = ((LIBXML_NODE->type == XML_ATTRIBUTE_NODE) |
|
228 ? reinterpret_cast<xmlNodePtr*>(&(parent->properties)) |
|
229 : &(parent->children)); |
|
230 |
|
231 (*first)->prev = LIBXML_NODE; |
|
232 LIBXML_NODE->next = *first; |
|
233 *first = LIBXML_NODE; |
|
234 // NOTE: it is possible to cope without having parent defined, |
|
235 // it will need to iterate through sibling list to find the first one |
|
236 } |
|
237 } |
|
238 |
|
239 |
|
240 // --------------------------------------------------------------------------------------------- |
|
241 // Moves the node to become the last in the list of its siblings |
|
242 // Node is expected to have a parent. |
|
243 // --------------------------------------------------------------------------------------------- |
|
244 // |
|
245 EXPORT_C void TXmlEngNode::SetAsLastSibling() |
|
246 { |
|
247 if (LIBXML_NODE->type == XML_NAMESPACE_DECL) |
|
248 { |
|
249 return; |
|
250 } |
|
251 xmlNodePtr& next = LIBXML_NODE->next; |
|
252 if (next) |
|
253 { |
|
254 DoUnlinkNode(); |
|
255 xmlNodePtr& parent = LIBXML_NODE->parent; |
|
256 xmlNodePtr& prev = LIBXML_NODE->prev; |
|
257 if (LIBXML_NODE->type != XML_ATTRIBUTE_NODE) |
|
258 { |
|
259 if (!prev) |
|
260 parent->children = next; |
|
261 prev = parent->last; |
|
262 parent->last->next = LIBXML_NODE; |
|
263 parent->last = LIBXML_NODE; |
|
264 } |
|
265 else |
|
266 { |
|
267 if (!prev) |
|
268 parent->properties = (xmlAttrPtr)next; |
|
269 prev = next; // NOTE: 'next' is always different than NULL |
|
270 while (prev->next) |
|
271 prev = prev->next; |
|
272 prev->next = LIBXML_NODE; |
|
273 } |
|
274 next = NULL; |
|
275 } |
|
276 } |
|
277 |
|
278 // --------------------------------------------------------------------------------------------- |
|
279 // Moves the node in the list of sibling nodes before another node |
|
280 // Node is expected to have a parent. |
|
281 // Do nothing if aSiblingNode is not one of node's siblings |
|
282 // --------------------------------------------------------------------------------------------- |
|
283 // |
|
284 EXPORT_C void TXmlEngNode::MoveBeforeSibling( |
|
285 TXmlEngNode aSiblingNode ) |
|
286 { |
|
287 if (LIBXML_NODE->type == XML_NAMESPACE_DECL) |
|
288 { |
|
289 return; |
|
290 } |
|
291 xmlNodePtr node = INTERNAL_NODEPTR(aSiblingNode); |
|
292 if (!node->prev) |
|
293 { |
|
294 SetAsFirstSibling(); |
|
295 } |
|
296 else |
|
297 { |
|
298 DoUnlinkNode(); |
|
299 LinkBefore(aSiblingNode); |
|
300 } |
|
301 } |
|
302 |
|
303 // --------------------------------------------------------------------------------------------- |
|
304 // Moves the node in the list of sibling nodes after another node |
|
305 // Node is expected to have a parent. |
|
306 // Do nothing if aSiblingNode is not one of the node's siblings |
|
307 // --------------------------------------------------------------------------------------------- |
|
308 // |
|
309 EXPORT_C void TXmlEngNode::MoveAfterSibling( |
|
310 TXmlEngNode aSiblingNode) |
|
311 { |
|
312 if (LIBXML_NODE->type == XML_NAMESPACE_DECL) |
|
313 { |
|
314 return; |
|
315 } |
|
316 xmlNodePtr node = INTERNAL_NODEPTR(aSiblingNode); |
|
317 if (!node->next) |
|
318 { |
|
319 SetAsLastSibling(); |
|
320 } |
|
321 else |
|
322 { |
|
323 DoUnlinkNode(); |
|
324 LinkBefore(aSiblingNode.NextSibling()); |
|
325 } |
|
326 } |
|
327 |
|
328 // --------------------------------------------------------------------------------------------- |
|
329 // Retrieves a "handle" for namespace declaration that applies to the node's namespace |
|
330 // Note: DOM specs do not consider namespace declarations as a kind of nodes |
|
331 // This API adds TXmlEngNamespace type of nodes, which is derived from TXmlEngNode. |
|
332 // |
|
333 // @return Object that represents namespace declaration and prefix binding that |
|
334 // act on the node; returns NULL object (check using TXmlEngNamespace.IsNull() |
|
335 // or TXmlEngNamespace.NotNull()) if no namespace associated |
|
336 // --------------------------------------------------------------------------------------------- |
|
337 // |
|
338 EXPORT_C TXmlEngNamespace TXmlEngNode::NamespaceDeclaration() const |
|
339 { |
|
340 // |
|
341 switch(LIBXML_NODE->type) |
|
342 { |
|
343 case XML_ELEMENT_NODE: |
|
344 case XML_ATTRIBUTE_NODE: |
|
345 return TXmlEngNamespace(LIBXML_NODE->ns); |
|
346 default: |
|
347 return NULL; |
|
348 } |
|
349 } |
|
350 |
|
351 // --------------------------------------------------------------------------------------------- |
|
352 // Clones the node completely: all attributes and namespace declarations (for TXmlEngElement nodes), |
|
353 // values and children nodes are copied as well. |
|
354 // |
|
355 // Document nodes cannot be copied with this method: RXmlEngDocument::CloneDocumentL() must be used. |
|
356 // |
|
357 // @return Complete copy of a node or leaves. |
|
358 // @note The node should not be NULL! |
|
359 // --------------------------------------------------------------------------------------------- |
|
360 // |
|
361 EXPORT_C TXmlEngNode TXmlEngNode::CopyL() const |
|
362 { |
|
363 if ( !LIBXML_NODE ) |
|
364 { |
|
365 User::Leave(KXmlEngErrNullNode); |
|
366 } |
|
367 // Copying of RXmlEngDocument should be made with RXmlEngDocument::CloneDocumentL() |
|
368 if(NodeType() == TXmlEngNode::EDocument) |
|
369 return NULL; |
|
370 // |
|
371 xmlNodePtr copy = xmlStaticCopyNode( |
|
372 LIBXML_NODE, |
|
373 NULL /* doc */, |
|
374 NULL /* parent */, |
|
375 1); |
|
376 // |
|
377 if (xmlOOMFlag()) |
|
378 { |
|
379 if(copy) |
|
380 xmlFreeNode(copy); // it may be a partial copy |
|
381 OOM_HAPPENED; |
|
382 } |
|
383 TXmlEngNode ncopy(copy); |
|
384 OwnerDocument().TakeOwnership(ncopy); |
|
385 return ncopy; |
|
386 } |
|
387 |
|
388 // --------------------------------------------------------------------------------------------- |
|
389 // Creates a deep copy of the node and appends the subtree as a new child |
|
390 // to the provided parent node. |
|
391 // |
|
392 // @return Created copy of the node after linking it into the target document tree. |
|
393 // @note Document nodes cannot be copied with this method; use RXmlEngDocument::CloneDocumentL() |
|
394 // --------------------------------------------------------------------------------------------- |
|
395 // |
|
396 EXPORT_C TXmlEngNode TXmlEngNode::CopyToL( |
|
397 TXmlEngNode aParent ) const |
|
398 { |
|
399 if ( !LIBXML_NODE ) |
|
400 { |
|
401 User::Leave(KXmlEngErrNullNode); |
|
402 } |
|
403 if ( LIBXML_NODE->type == XML_DOCUMENT_NODE ) |
|
404 { |
|
405 User::Leave(KXmlEngErrWrongUseOfAPI); |
|
406 } |
|
407 if ( aParent.IsNull() ) |
|
408 { |
|
409 User::Leave(KXmlEngErrNullNode); |
|
410 } |
|
411 // |
|
412 TXmlEngNode ncopy = CopyL(); |
|
413 return aParent.AppendChildL(ncopy); |
|
414 } |
|
415 |
|
416 // --------------------------------------------------------------------------------------------- |
|
417 // Detaches a node from document tree |
|
418 // |
|
419 // @return This node, which is already not a part of any document |
|
420 // @note Remember to use ReconcileNamespacesL() later, if extracted node (subtree) |
|
421 // contains references to namespace declarations outside of the subtree. |
|
422 // @see ReconcileNamespacesL() |
|
423 // @note The document, from which the node is being unlinked, becomes an owner of the node |
|
424 // until it is linked elsewhere. |
|
425 // --------------------------------------------------------------------------------------------- |
|
426 // |
|
427 EXPORT_C TXmlEngNode TXmlEngNode::Unlink() |
|
428 { |
|
429 // |
|
430 if(LIBXML_NODE && ParentNode().NotNull()) |
|
431 { |
|
432 RXmlEngDocument tmpDoc = OwnerDocument(); |
|
433 xmlUnlinkNode(LIBXML_NODE); |
|
434 tmpDoc.TakeOwnership(*this); |
|
435 } |
|
436 return *this; |
|
437 } |
|
438 |
|
439 // --------------------------------------------------------------------------------------------- |
|
440 // Unlinks the node and destroys it; all child nodes are destroyed as well and all memory is freed |
|
441 // |
|
442 // @note Document nodes cannot be "removed" with this method, uses RXmlEngDocument-specific methods. |
|
443 // --------------------------------------------------------------------------------------------- |
|
444 // |
|
445 EXPORT_C void TXmlEngNode::Remove() |
|
446 { |
|
447 // |
|
448 if (!LIBXML_NODE || LIBXML_NODE->type == XML_DOCUMENT_NODE) |
|
449 { |
|
450 return; |
|
451 } |
|
452 if(ParentNode().NotNull()) |
|
453 { |
|
454 xmlUnlinkNode(LIBXML_NODE); |
|
455 } |
|
456 else |
|
457 { |
|
458 OwnerDocument().RemoveOwnership(*this); |
|
459 } |
|
460 if (LIBXML_NODE->type != XML_ATTRIBUTE_NODE) |
|
461 { |
|
462 xmlFreeNode(LIBXML_NODE); |
|
463 } |
|
464 else |
|
465 { |
|
466 xmlFreeProp(INTERNAL_ATTRPTR(iInternal)); |
|
467 } |
|
468 |
|
469 iInternal = 0; |
|
470 } |
|
471 |
|
472 // --------------------------------------------------------------------------------------------- |
|
473 // Ensures that namespaces referred to in the node and its descendants are |
|
474 // in the scope the node. |
|
475 // |
|
476 // * This method checks that all the namespaces declared within the given |
|
477 // * tree are properly declared. This is needed for example after Copy or Unlink |
|
478 // * and then Append operations. The subtree may still hold pointers to |
|
479 // * namespace declarations outside the subtree or they may be invalid/masked. As much |
|
480 // * as possible the function try to reuse the existing namespaces found in |
|
481 // * the new environment. If not possible, the new namespaces are redeclared |
|
482 // * on the top of the subtree. |
|
483 // |
|
484 // This method should be used after unlinking nodes and inserting to another |
|
485 // document tree or to a another part of the original tree, if some nodes of the subtree |
|
486 // are remove from the scope of a namespace declaration they refer to. |
|
487 // |
|
488 // When node is unlinked, it may still refer to namespace declarations from the previous location. |
|
489 // It is important to reconcile subtree's namespaces if previous parent tree is to be destroyed. |
|
490 // On the other hand, if the parent tree is not changed before pasting its unlinked part into another |
|
491 // tree, then reconciliation is needed only after paste operation. |
|
492 // --------------------------------------------------------------------------------------------- |
|
493 // |
|
494 EXPORT_C void TXmlEngNode::ReconcileNamespacesL() |
|
495 { |
|
496 xmlReconciliateNs(LIBXML_NODE->doc, LIBXML_NODE); |
|
497 TEST_OOM_FLAG; |
|
498 } |
|
499 |
|
500 // --------------------------------------------------------------------------------------------- |
|
501 // Current node is replaced with another node (subtree). |
|
502 // |
|
503 // The replacement node is linked into document tree instead of this node. |
|
504 // The replaced node is destroyed. |
|
505 // |
|
506 // @see SubstituteForL(TXmlEngNode) |
|
507 // |
|
508 // In both cases the argument node is unlinked from its previous location |
|
509 // (which can be NONE, i.e. not linked; SAME or ANOTHER document tree). |
|
510 // |
|
511 // @note Replacement of a node with NULL TXmlEngNode is legal and equivalent to removing the node. |
|
512 // @note Not applicable to document nodes |
|
513 // --------------------------------------------------------------------------------------------- |
|
514 // |
|
515 EXPORT_C void TXmlEngNode::ReplaceWithL(TXmlEngNode aNode) |
|
516 { |
|
517 if ( !LIBXML_NODE ) |
|
518 { |
|
519 User::Leave(KXmlEngErrNullNode); |
|
520 } |
|
521 if ( LIBXML_NODE->type == XML_DOCUMENT_NODE ) |
|
522 { |
|
523 User::Leave(KXmlEngErrWrongUseOfAPI); |
|
524 } |
|
525 |
|
526 if(aNode.ParentNode().IsNull()) |
|
527 { |
|
528 // new node is unlinked, so owned by some (maybe other than this) document |
|
529 // previous ownership must be withdrawn |
|
530 aNode.OwnerDocument().RemoveOwnership(aNode); |
|
531 } |
|
532 if(ParentNode().IsNull()) |
|
533 { |
|
534 // This node is unlinked, thus owned by its document |
|
535 // Ownership must be withdrawn before removing the node |
|
536 RXmlEngDocument doc = OwnerDocument(); |
|
537 doc.RemoveOwnership(*this); |
|
538 // Also, there is no place to link the new node! |
|
539 // So it will be unlinked, but owned by this node's document |
|
540 doc.TakeOwnership(aNode); |
|
541 } |
|
542 // put new node instead of 'this' node: it works with all combinations of linked/unlinked states of the nodes |
|
543 xmlFreeNode(xmlReplaceNode(LIBXML_NODE, INTERNAL_NODEPTR(aNode))); |
|
544 } |
|
545 |
|
546 EXPORT_C void TXmlEngNode::ReplaceWith(TXmlEngNode aNode) |
|
547 { |
|
548 if(!LIBXML_NODE || LIBXML_NODE->type == XML_DOCUMENT_NODE) |
|
549 return; |
|
550 if(aNode.ParentNode().IsNull()) |
|
551 { |
|
552 // new node is unlinked, so owned by some (maybe other than this) document |
|
553 // previous ownership must be withdrawn |
|
554 aNode.OwnerDocument().RemoveOwnership(aNode); |
|
555 } |
|
556 if(ParentNode().IsNull()) |
|
557 { |
|
558 // This node is unlinked, thus owned by its document |
|
559 // Ownership must be withdrawn before removing the node |
|
560 RXmlEngDocument doc = OwnerDocument(); |
|
561 doc.RemoveOwnership(*this); |
|
562 // Also, there is no place to link the new node! |
|
563 // So it will be unlinked, but owned by this node's document |
|
564 doc.TakeOwnership(aNode); |
|
565 } |
|
566 // put new node instead of 'this' node: it works with all combinations of linked/unlinked states of the nodes |
|
567 xmlFreeNode(xmlReplaceNode(LIBXML_NODE, INTERNAL_NODEPTR(aNode))); |
|
568 } |
|
569 |
|
570 // --------------------------------------------------------------------------------------------- |
|
571 // Another node is put instead of the current node. |
|
572 // |
|
573 // Does the same as ReplaceWith(TXmlEngNode) but does not free node and just returns it. |
|
574 // |
|
575 // @return Current node after unlinking it from document tree |
|
576 // @see ReplaceWith(TXmlEngNode) |
|
577 // |
|
578 // In both cases the argument node is unlinked from its previous location |
|
579 // (which can be NONE, i.e. not linked; SAME or ANOTHER document tree) |
|
580 // |
|
581 // It is possible to use NULL TXmlEngNode object as an argument. In such case |
|
582 // no new node will be put instead of unlinked one. |
|
583 // |
|
584 // @note Not applicable to document nodes |
|
585 // --------------------------------------------------------------------------------------------- |
|
586 // |
|
587 EXPORT_C TXmlEngNode TXmlEngNode::SubstituteForL(TXmlEngNode aNode) |
|
588 { |
|
589 if ( !LIBXML_NODE ) |
|
590 { |
|
591 User::Leave(KXmlEngErrNullNode); |
|
592 } |
|
593 if ( LIBXML_NODE->type == XML_DOCUMENT_NODE ) |
|
594 { |
|
595 User::Leave(KXmlEngErrWrongUseOfAPI); |
|
596 } |
|
597 // |
|
598 if(aNode.ParentNode().IsNull()) |
|
599 { |
|
600 // new node is unlinked, so owned by other document |
|
601 // it must not be owned to be linked |
|
602 aNode.OwnerDocument().RemoveOwnership(aNode); |
|
603 } |
|
604 if(ParentNode().IsNull()) |
|
605 { |
|
606 // this node is unlinked - nowhere to link new node: this node's document will own it |
|
607 OwnerDocument().TakeOwnership(aNode); |
|
608 // this node will stay as it is |
|
609 // new node will be unlinked by call to xmlReplaceNode |
|
610 } |
|
611 TXmlEngNode tmpNode = TXmlEngNode(xmlReplaceNode(LIBXML_NODE, INTERNAL_NODEPTR(aNode))); |
|
612 aNode.OwnerDocument().TakeOwnership(tmpNode); |
|
613 return tmpNode; |
|
614 } |
|
615 |
|
616 // --------------------------------------------------------------------------------------------- |
|
617 // DOM Level 3 Core |
|
618 // --------------------------------------------------------------------------------------------- |
|
619 |
|
620 // --------------------------------------------------------------------------------------------- |
|
621 //Initializes a node list with all children of the node |
|
622 // --------------------------------------------------------------------------------------------- |
|
623 // |
|
624 EXPORT_C void TXmlEngNode::GetChildNodes(RXmlEngNodeList<TXmlEngNode>& aList) const |
|
625 { |
|
626 aList.Open(LIBXML_NODE->children, TDOMNODETYPENONE); |
|
627 } |
|
628 |
|
629 // --------------------------------------------------------------------------------------------- |
|
630 // @return Parent node of the node or NULL if no parent |
|
631 // --------------------------------------------------------------------------------------------- |
|
632 // |
|
633 EXPORT_C TXmlEngNode TXmlEngNode::ParentNode() const |
|
634 { |
|
635 // |
|
636 return TXmlEngNode(LIBXML_NODE->parent); |
|
637 } |
|
638 |
|
639 // --------------------------------------------------------------------------------------------- |
|
640 // @return The first child node or NULL if no children |
|
641 // --------------------------------------------------------------------------------------------- |
|
642 // |
|
643 EXPORT_C TXmlEngNode TXmlEngNode::FirstChild() const |
|
644 { |
|
645 // |
|
646 return TXmlEngNode(LIBXML_NODE->children); |
|
647 } |
|
648 |
|
649 // --------------------------------------------------------------------------------------------- |
|
650 // @return The last child node or NULL if no children |
|
651 // --------------------------------------------------------------------------------------------- |
|
652 // |
|
653 EXPORT_C TXmlEngNode TXmlEngNode::LastChild() const |
|
654 { |
|
655 // |
|
656 return TXmlEngNode(LIBXML_NODE->last); |
|
657 } |
|
658 |
|
659 // --------------------------------------------------------------------------------------------- |
|
660 // @return Previous node in a child list or NULL if no sibling before |
|
661 // --------------------------------------------------------------------------------------------- |
|
662 // |
|
663 EXPORT_C TXmlEngNode TXmlEngNode::PreviousSibling() const |
|
664 { |
|
665 if(!LIBXML_NODE->parent) |
|
666 { |
|
667 return NULL; |
|
668 } |
|
669 return TXmlEngNode(LIBXML_NODE->prev); |
|
670 } |
|
671 |
|
672 // --------------------------------------------------------------------------------------------- |
|
673 // @return Following node in a child list or NULL if no sibling after |
|
674 // --------------------------------------------------------------------------------------------- |
|
675 // |
|
676 EXPORT_C TXmlEngNode TXmlEngNode::NextSibling() const |
|
677 { |
|
678 if(!LIBXML_NODE->parent) |
|
679 { |
|
680 return NULL; |
|
681 } |
|
682 return TXmlEngNode(LIBXML_NODE->next); |
|
683 } |
|
684 |
|
685 // --------------------------------------------------------------------------------------------- |
|
686 // @return A document node of the DOM tree this node belongs to |
|
687 // @note An instance of RXmlEngDocument class returns itself |
|
688 // --------------------------------------------------------------------------------------------- |
|
689 // |
|
690 EXPORT_C RXmlEngDocument TXmlEngNode::OwnerDocument() const |
|
691 { |
|
692 // |
|
693 return RXmlEngDocument(LIBXML_NODE->doc); |
|
694 } |
|
695 |
|
696 // --------------------------------------------------------------------------------------------- |
|
697 // Append a child node. |
|
698 // |
|
699 // This is universal operation for any types of nodes. |
|
700 // Note, that some types of nodes cannot have children and |
|
701 // some types of nodes are not allowed to be children of some other types. |
|
702 // |
|
703 // @return Appended node, which could changed as a result of adding it to |
|
704 // list of child nodes (e.g. text nodes can coalesce together) |
|
705 // --------------------------------------------------------------------------------------------- |
|
706 // |
|
707 EXPORT_C TXmlEngNode TXmlEngNode::AppendChildL( |
|
708 TXmlEngNode aNewChild) |
|
709 { |
|
710 if ( !LIBXML_NODE || aNewChild.IsNull() ) |
|
711 { |
|
712 User::Leave(KXmlEngErrNullNode); |
|
713 } |
|
714 // |
|
715 if(aNewChild.ParentNode().IsNull()) |
|
716 { |
|
717 aNewChild.OwnerDocument().RemoveOwnership(aNewChild); |
|
718 } |
|
719 else |
|
720 { |
|
721 xmlUnlinkNode(INTERNAL_NODEPTR(aNewChild)); |
|
722 } |
|
723 xmlNodePtr child = xmlAddChild(LIBXML_NODE, INTERNAL_NODEPTR(aNewChild)); |
|
724 |
|
725 TEST_OOM_FLAG; |
|
726 return child; |
|
727 } |
|
728 |
|
729 // --------------------------------------------------------------------------------------------- |
|
730 // @return Type of the node |
|
731 // |
|
732 // Use NodeType() to find out the type of the node prior to casting object |
|
733 // of TXmlEngNode class to one of its derived subclasses (TXmlEngElement, TXmlEngAttr, TXmlEngTextNode, etc.) |
|
734 // |
|
735 // @see TXmlEngDOMNodeType |
|
736 // --------------------------------------------------------------------------------------------- |
|
737 // |
|
738 EXPORT_C TXmlEngNode::TXmlEngDOMNodeType TXmlEngNode::NodeType() const |
|
739 { |
|
740 // |
|
741 if((TXmlEngDOMNodeType)LIBXML_NODE->type == EText && TEXT_NODE_DATA_TYPE) |
|
742 { |
|
743 return (TXmlEngDOMNodeType)(TUint)TEXT_NODE_DATA_TYPE; |
|
744 } |
|
745 return (TXmlEngDOMNodeType)LIBXML_NODE->type; |
|
746 } |
|
747 |
|
748 // Note: "" is used for undefined name; 0 means "to use libxml node's name field" |
|
749 static const char* const KNodeNames[]={ |
|
750 0, |
|
751 0, // EElement = 1, |
|
752 0, // EAttribute = 2, |
|
753 "#text", // EText = 3, |
|
754 "#cdata-section", // ECDATASection = 4, |
|
755 0, // EEntityReference = 5, |
|
756 "", // EEntity = 6, |
|
757 0, // EProcessingInstruction = 7, |
|
758 "#comment", // EComment = 8, |
|
759 0, // EDocument = 9, |
|
760 0, // EDocumentType = 10, |
|
761 "#document-fragment", // EDocumentFragment = 11, |
|
762 "", // ENotation = 12, |
|
763 0, // ENamespaceDeclaration = 18 // not in use |
|
764 "", // EBinaryContainer = 30, |
|
765 "", // EChunkContainer = 31, |
|
766 "" // EFileContainer = 32 |
|
767 }; |
|
768 |
|
769 const TInt KNodeNamesSize = sizeof(KNodeNames); |
|
770 |
|
771 // --------------------------------------------------------------------------------------------- |
|
772 // @return Name of the node |
|
773 // |
|
774 // This method generally follows DOM spec : |
|
775 // \verbatim |
|
776 // ------------------------------------------------------------------------------- |
|
777 // The values of nodeName, nodeValue, and attributes vary according to the node |
|
778 // type as follows: |
|
779 // |
|
780 // interface nodeName nodeValue attributes |
|
781 // ------------------------------------------------------------------------------- |
|
782 // Attr = Attr.name = Attr.value = null |
|
783 // CDATASection = "#cdata-section" = CharacterData.data = null |
|
784 // Comment = "#comment" = CharacterData.data = null |
|
785 // Document = "#document" = null = null |
|
786 // DocumentFragment = "#document-fragment" = null = null |
|
787 // DocumentType = DocumentType.name = null = null |
|
788 // Element = Element.tagName = null = NamedNodeMap |
|
789 // Entity = entity name = null = null |
|
790 // EntityReference = name of entity referenced = null = null |
|
791 // Notation = notation name = null = null |
|
792 // ProcessingInstruction = target = data = null |
|
793 // Text = "#text" = CharacterData.data = null |
|
794 // ------------------------------------------------------------------------------- |
|
795 // \endverbatim |
|
796 // --------------------------------------------------------------------------------------------- |
|
797 // |
|
798 EXPORT_C TPtrC8 TXmlEngNode::Name() const |
|
799 { |
|
800 // DONE: OPTIMIZE: Create static array of names with nodetype as index |
|
801 // Use NULL if name is not constant and then use such switch.. |
|
802 // |
|
803 TUint type = (TUint) LIBXML_NODE->type; |
|
804 if (type < KNodeNamesSize /sizeof(char*)) |
|
805 { |
|
806 const char* KName = KNodeNames[type]; |
|
807 if(KName) |
|
808 { |
|
809 return TXmlEngConstString(KName).PtrC8(); |
|
810 } |
|
811 return TXmlEngConstString((char*)LIBXML_NODE->name).PtrC8(); |
|
812 } |
|
813 return KNullDesC8(); |
|
814 } |
|
815 |
|
816 |
|
817 // --------------------------------------------------------------------------------------------- |
|
818 // Fetches value of this node, depending on its type. |
|
819 // |
|
820 // @note It is better to always cast nodes to specific type and then use specific |
|
821 // method for getting "node value" |
|
822 // |
|
823 // @return Node value |
|
824 // --------------------------------------------------------------------------------------------- |
|
825 // |
|
826 EXPORT_C TPtrC8 TXmlEngNode::Value() const |
|
827 { |
|
828 if (iInternal) |
|
829 { |
|
830 switch(LIBXML_NODE->type) |
|
831 { |
|
832 // The content of first Text child is returned |
|
833 case XML_ATTRIBUTE_NODE: |
|
834 return AsAttr().Value(); |
|
835 // Note: in DOM spec element's value is Null, but we can |
|
836 // access it: the content of first TXmlEngTextNode child node is returned |
|
837 case XML_ELEMENT_NODE: |
|
838 return AsElement().Text(); |
|
839 // TXmlEngTextNode, TXmlEngCDATASection, TXmlEngProcessingInstruction and Comments store |
|
840 // content in the same way. |
|
841 case XML_TEXT_NODE: |
|
842 case XML_CDATA_SECTION_NODE: |
|
843 case XML_COMMENT_NODE: |
|
844 case XML_PI_NODE: |
|
845 return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(LIBXML_NODE->content)).PtrC8(); |
|
846 |
|
847 default: |
|
848 ; |
|
849 } |
|
850 } |
|
851 return NULL; |
|
852 } |
|
853 // --------------------------------------------------------------------------------------------- |
|
854 // Sets value of this node. |
|
855 // --------------------------------------------------------------------------------------------- |
|
856 // |
|
857 EXPORT_C void TXmlEngNode::SetValueL( |
|
858 const TDesC8& aValue ) |
|
859 { |
|
860 if (iInternal) |
|
861 { |
|
862 switch(LIBXML_NODE->type) |
|
863 { |
|
864 // The content of first TXmlEngTextNode child is returned |
|
865 case XML_ATTRIBUTE_NODE: |
|
866 case XML_ELEMENT_NODE: |
|
867 // Note: in DOM spec element's value is Null, but we can |
|
868 // access it: the content of first TXmlEngTextNode child node is returned |
|
869 AsAttr().SetValueL(aValue); // same as TXmlEngElement::SetTextL(aValue); |
|
870 return; |
|
871 // TXmlEngTextNode, TXmlEngCDATASection, TXmlEngProcessingInstruction and Comments store |
|
872 // content in the same way. |
|
873 case XML_TEXT_NODE: |
|
874 case XML_CDATA_SECTION_NODE: |
|
875 case XML_COMMENT_NODE: |
|
876 case XML_PI_NODE: |
|
877 AsText().SetContentsL(aValue); |
|
878 return; |
|
879 default: |
|
880 ; |
|
881 } |
|
882 } |
|
883 } |
|
884 |
|
885 |
|
886 // --------------------------------------------------------------------------------------------- |
|
887 // @return Whether the value of the node is presented by only one TXmlEngTextNode node |
|
888 // |
|
889 // If the value is <i>"simple text"</i> then it is possible to access it as TDOMString |
|
890 // without making copy, which combines values of all text nodes and entity reference nodes. |
|
891 // |
|
892 // @see TXmlEngNode::Value(), TXmlEngAttr::Value(), TXmlEngElement::Text() |
|
893 // |
|
894 // This method is applicable to TXmlEngElement and TXmlEngAttr nodes. On other nodes FALSE is returned. |
|
895 // |
|
896 // @note |
|
897 // Values (contents) of TXmlEngComment, TXmlEngCDATASection, TXmlEngTextNode, ProcessingInstuction data are |
|
898 // always "simple". |
|
899 // |
|
900 // When the returned result is FALSE, getting value of the node would not returned |
|
901 // whole contents because of either entity references present in the contents or |
|
902 // the contents is mixed (for TXmlEngElement node). In this case WholeTextContentsCopyL() |
|
903 // should be used. |
|
904 // |
|
905 // @see TXmlEngNode::WholeTextContentsCopyL() |
|
906 // --------------------------------------------------------------------------------------------- |
|
907 // |
|
908 EXPORT_C TBool TXmlEngNode::IsSimpleTextContents() const |
|
909 { |
|
910 if (!LIBXML_NODE) |
|
911 return false; |
|
912 xmlElementType type = LIBXML_NODE->type; |
|
913 if (type == XML_ELEMENT_NODE || |
|
914 type == XML_ATTRIBUTE_NODE) |
|
915 { |
|
916 xmlNodePtr children = LIBXML_NODE->children; |
|
917 |
|
918 return children && children->type == XML_TEXT_NODE && |
|
919 !(children->next); |
|
920 } |
|
921 return false; // incorrect type node |
|
922 } |
|
923 |
|
924 // --------------------------------------------------------------------------------------------- |
|
925 // @return the content of the node |
|
926 // |
|
927 // What is returned depends on the node type. |
|
928 // Method caller is responsible for freeing returned string. |
|
929 // --------------------------------------------------------------------------------------------- |
|
930 // |
|
931 EXPORT_C void TXmlEngNode::WholeTextContentsCopyL(RBuf8& aOutput) const |
|
932 { |
|
933 XE_ASSERT_DEBUG(LIBXML_NODE); |
|
934 // |
|
935 xmlChar* text = xmlNodeGetContent(LIBXML_NODE); |
|
936 if (xmlOOMFlag()) |
|
937 { |
|
938 if(text) |
|
939 xmlFree(text); |
|
940 OOM_HAPPENED; |
|
941 } |
|
942 xmlCharAssignToRbuf8L(aOutput,text); |
|
943 } |
|
944 // ----------------------------------------------------------------------------- |
|
945 |
|
946 EXPORT_C TBool TXmlEngNode::HasChildNodes() const |
|
947 { |
|
948 // |
|
949 return (TBool)LIBXML_NODE->children; |
|
950 } |
|
951 |
|
952 // --------------------------------------------------------------------------------------------- |
|
953 // @return Namespace URI of a node |
|
954 // - NULL is returned for elements and attributes that do not |
|
955 // belong to any namespace. |
|
956 // - bound namespace URI is returned for namespace declaration nodes (instances of TXmlEngNamespace). |
|
957 // - NULL is returned to all other types of node. |
|
958 // @note use IsNull() and NotNull() for testing returned result on the subject |
|
959 // of having some URI |
|
960 // --------------------------------------------------------------------------------------------- |
|
961 // |
|
962 EXPORT_C TPtrC8 TXmlEngNode::NamespaceUri() const |
|
963 { |
|
964 // |
|
965 switch(LIBXML_NODE->type) |
|
966 { |
|
967 case XML_ELEMENT_NODE: |
|
968 case XML_ATTRIBUTE_NODE: |
|
969 return TXmlEngNamespace(LIBXML_NODE->ns).Uri(); |
|
970 case XML_NAMESPACE_DECL: |
|
971 return AsNamespace().Uri(); |
|
972 default: |
|
973 return NULL; |
|
974 } |
|
975 } |
|
976 |
|
977 // --------------------------------------------------------------------------------------------- |
|
978 // @return Prefix of a node |
|
979 // |
|
980 // Returns NULL for elements and attributes that do not have prefix |
|
981 // (node belongs to the default namespace or does not belong to any namespace) |
|
982 // NULL is also returned for all types of node other than TXmlEngElement or TXmlEngAttr |
|
983 // --------------------------------------------------------------------------------------------- |
|
984 // |
|
985 EXPORT_C TPtrC8 TXmlEngNode::Prefix() const |
|
986 { |
|
987 if (LIBXML_NODE->type < XML_TEXT_NODE) // NOTE: XML_ELEMENT_NODE = 1 and XML_ATTRIBUTE_NODE = 2 |
|
988 { |
|
989 xmlNs* ns = LIBXML_NODE->ns; |
|
990 if (ns) |
|
991 return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(ns->prefix)).PtrC8(); |
|
992 } |
|
993 return KNullDesC8(); |
|
994 } |
|
995 |
|
996 |
|
997 // --------------------------------------------------------------------------------------------- |
|
998 // @return True if the node is TXmlEngElement and has at least one attribute |
|
999 // |
|
1000 // @note Namespace-to-prefix bindings are not attributes. |
|
1001 // --------------------------------------------------------------------------------------------- |
|
1002 // |
|
1003 EXPORT_C TBool TXmlEngNode::HasAttributes() const |
|
1004 { |
|
1005 return iInternal && |
|
1006 LIBXML_NODE->type == XML_ELEMENT_NODE && |
|
1007 LIBXML_NODE->properties; |
|
1008 } |
|
1009 |
|
1010 // --------------------------------------------------------------------------------------------- |
|
1011 // Evaluates active base URI for the node by processing xml:base attributes of parents |
|
1012 // |
|
1013 // @return A copy of effective base URI for the node |
|
1014 // @note It's up to the caller to free the string with TDOMString::Free() |
|
1015 // --------------------------------------------------------------------------------------------- |
|
1016 // |
|
1017 EXPORT_C void TXmlEngNode::BaseUriL(RBuf8& aBaseUri) const |
|
1018 { |
|
1019 // |
|
1020 xmlChar* uri = xmlNodeGetBase(LIBXML_NODE->doc, LIBXML_NODE); |
|
1021 if (xmlOOMFlag()) |
|
1022 { |
|
1023 if(uri) |
|
1024 xmlFree(uri); // partial construction is possible |
|
1025 OOM_HAPPENED; |
|
1026 } |
|
1027 xmlCharAssignToRbuf8L(aBaseUri,uri); |
|
1028 } |
|
1029 |
|
1030 // --------------------------------------------------------------------------------------------- |
|
1031 // Searches the prefix that is bound to the given aNamespaceUri and |
|
1032 // applicable in the scope of this TXmlEngNode. |
|
1033 // |
|
1034 // @return A sought prefix or NULL if not found or aNamespaceUri is the default namespace |
|
1035 // @see TXmlEngElement::LookupNamespaceByUri(TXmlEngNode,TDOMString) |
|
1036 // --------------------------------------------------------------------------------------------- |
|
1037 // |
|
1038 EXPORT_C TPtrC8 TXmlEngNode::LookupPrefixL( |
|
1039 const TDesC8& aNamespaceUri ) const |
|
1040 { |
|
1041 if ( !LIBXML_NODE ) |
|
1042 { |
|
1043 User::Leave(KXmlEngErrNullNode); |
|
1044 } |
|
1045 // |
|
1046 if (LIBXML_NODE->type == XML_ATTRIBUTE_NODE || |
|
1047 LIBXML_NODE->type == XML_ELEMENT_NODE) |
|
1048 { |
|
1049 return AsElement().LookupNamespaceByUriL(aNamespaceUri).Prefix(); |
|
1050 } |
|
1051 if(!ParentNode().IsNull()) |
|
1052 { |
|
1053 return ParentNode().AsElement().LookupNamespaceByUriL(aNamespaceUri).Prefix(); |
|
1054 } |
|
1055 return KNullDesC8(); |
|
1056 } |
|
1057 |
|
1058 // --------------------------------------------------------------------------------------------- |
|
1059 // @return True if given namespace URI is a default one for the node (applicable to elements only) |
|
1060 // |
|
1061 // @note "" or NULL can be used to denote undefined namespace |
|
1062 // --------------------------------------------------------------------------------------------- |
|
1063 // |
|
1064 EXPORT_C TBool TXmlEngNode::IsDefaultNamespaceL( |
|
1065 const TDesC8& aNamespaceUri ) const |
|
1066 { |
|
1067 if (LIBXML_NODE->type == XML_ELEMENT_NODE) // No default namespaces for attributes |
|
1068 { |
|
1069 return !AsElement().DefaultNamespaceL().Uri().Compare(aNamespaceUri); |
|
1070 } |
|
1071 return false; |
|
1072 } |
|
1073 |
|
1074 // --------------------------------------------------------------------------------------------- |
|
1075 // Searches the namespace URI that is bound to the given prefix. |
|
1076 // |
|
1077 // @return - a sought URI or NULL if the prefix is not bound |
|
1078 // @see TXmlEngElement::LookupNamespaceByPrefix(TXmlEngNode,TDOMString) |
|
1079 // --------------------------------------------------------------------------------------------- |
|
1080 // |
|
1081 EXPORT_C TPtrC8 TXmlEngNode::LookupNamespaceUriL( |
|
1082 const TDesC8& aPrefix ) const |
|
1083 { |
|
1084 if ( !LIBXML_NODE ) |
|
1085 { |
|
1086 User::Leave(KXmlEngErrNullNode); |
|
1087 } |
|
1088 // |
|
1089 if (LIBXML_NODE->type == XML_ATTRIBUTE_NODE || |
|
1090 LIBXML_NODE->type == XML_ELEMENT_NODE) |
|
1091 { |
|
1092 return AsElement().LookupNamespaceByPrefixL(aPrefix).Uri(); |
|
1093 } |
|
1094 if(!ParentNode().IsNull()) |
|
1095 { |
|
1096 return ParentNode().AsElement().LookupNamespaceByPrefixL(aPrefix).Uri(); |
|
1097 } |
|
1098 return KNullDesC8(); |
|
1099 } |
|
1100 |
|
1101 // --------------------------------------------------------------------------------------------- |
|
1102 // Returns the user data object attached to this node. Ownership is not transferred. |
|
1103 // |
|
1104 // @return Pointer to data object or NULL if it doesn't exist. |
|
1105 // --------------------------------------------------------------------------------------------- |
|
1106 // |
|
1107 EXPORT_C MXmlEngUserData* TXmlEngNode::UserData() const |
|
1108 { |
|
1109 return |
|
1110 (LIBXML_NODE && |
|
1111 (LIBXML_NODE->type == XML_ATTRIBUTE_NODE || |
|
1112 LIBXML_NODE->type == XML_ELEMENT_NODE)) |
|
1113 ? |
|
1114 static_cast<MXmlEngUserData*>(LIBXML_NODE->_private) |
|
1115 : |
|
1116 NULL; |
|
1117 } |
|
1118 |
|
1119 // --------------------------------------------------------------------------------------------- |
|
1120 // Removes the user data onject attached to this node. Ownership is transferred |
|
1121 // (the object is not deleted). |
|
1122 // |
|
1123 // @return Pointer to data object or NULL if it doesn't exist. |
|
1124 // --------------------------------------------------------------------------------------------- |
|
1125 // |
|
1126 EXPORT_C MXmlEngUserData* TXmlEngNode::RemoveUserData() |
|
1127 { |
|
1128 MXmlEngUserData* data = UserData(); |
|
1129 if (data) |
|
1130 { |
|
1131 // node type has been checked by UserData() |
|
1132 LIBXML_NODE->_private = NULL; |
|
1133 } |
|
1134 return data; |
|
1135 } |
|
1136 |
|
1137 // --------------------------------------------------------------------------------------------- |
|
1138 // Attaches a user data object to this node. The ownership of the object is transferred. |
|
1139 // When the (underlying) node is deleted the Destroy method of the MXmlEngUserData class will be |
|
1140 // called. If there already is a user data object associated with this node, it will be |
|
1141 // deleted before attaching the new object. Notet that only TXmlEngElement and Attribute nodes |
|
1142 // currently support this feature. |
|
1143 // |
|
1144 // @param[in] aData Pointer to the data object. |
|
1145 // @return true if successful, false if for example underlying node type doesn't support |
|
1146 // attaching user data. |
|
1147 // --------------------------------------------------------------------------------------------- |
|
1148 // |
|
1149 EXPORT_C TBool TXmlEngNode::AddUserData( |
|
1150 MXmlEngUserData* aData ) |
|
1151 { |
|
1152 TBool ret = false; |
|
1153 if (iInternal) |
|
1154 { |
|
1155 if (LIBXML_NODE->type == XML_ATTRIBUTE_NODE || |
|
1156 LIBXML_NODE->type == XML_ELEMENT_NODE) |
|
1157 { |
|
1158 // release previous data |
|
1159 if (LIBXML_NODE->_private) |
|
1160 { |
|
1161 MXmlEngUserData* oldData = RemoveUserData(); |
|
1162 oldData->Destroy(); |
|
1163 } |
|
1164 LIBXML_NODE->_private = aData; |
|
1165 ret = true; |
|
1166 } |
|
1167 } |
|
1168 return ret; |
|
1169 } |
|
1170 |