1 using System;
2 using System.Collections;
3 using System.Text;
4
5
6
7
8
9 namespace System.Dom
10 {
11 public enum NodeType
12 {
13 attributeNode, documentFragmentNode, documentNode, elementNode, entityNode, entityReferenceNode, notationNode, processingInstructionNode, textNode, cdataSectionNode, commentNode
14 }
15 public class Visitor
16 {
17 public virtual void BeginVisit(Document* document)
18 {
19 }
20 public virtual void EndVisit(Document* document)
21 {
22 }
23 public virtual void BeginVisit(Element* element)
24 {
25 }
26 public virtual void EndVisit(Element* element)
27 {
28 }
29 public virtual void Visit(Text* text)
30 {
31 }
32 public virtual void Visit(CDataSection* cdataSection)
33 {
34 }
35 public virtual void Visit(Comment* comment)
36 {
37 }
38 public virtual void Visit(EntityReference* entityReference)
39 {
40 }
41 public virtual void Visit(ProcessingInstruction* processingInstruction)
42 {
43 }
44 }
45 public class NodeOp
46 {
47 public virtual ~NodeOp()
48 {
49 }
50 public virtual void Apply(Node* node)
51 {
52 }
53 }
54 public enum Axis
55 {
56 child, descendant, parent, ancestor, followingSibling, precedingSibling, following, preceding, attribute, ns, self, descendantOrSelf, ancestorOrSelf
57 }
58 public abstract class Node
59 {
60 public suppress Node(const Node&);
61 public suppress Node(Node&&);
62 public Node(NodeType nodeType_, const ustring& name_) :
63 nodeType(nodeType_), name(name_), parent(null), previousSibling(null), nextSibling(null), ownerDocument(null)
64 {
65 }
66 public virtual ~Node()
67 {
68 }
69 public suppress Node& operator=(const Node&);
70 public suppress Node& operator=(Node&&);
71 public NodeType GetNodeType() const
72 {
73 return nodeType;
74 }
75 public const ustring& Name() const
76 {
77 return name;
78 }
79 public const ustring& NamespaceUri() const
80 {
81 return namespaceUri;
82 }
83 public Node* PreviousSibling() const
84 {
85 return previousSibling;
86 }
87 public Node* NextSibling() const
88 {
89 return nextSibling;
90 }
91 public ParentNode* Parent() const
92 {
93 return parent;
94 }
95 public Document* OwnerDocument() const
96 {
97 return ownerDocument;
98 }
99 public void InternalSetParent(ParentNode* parent_)
100 {
101 parent = parent_;
102 }
103 public void InternalSetOwnerDocument(Document* ownerDocument_)
104 {
105 ownerDocument = ownerDocument_;
106 }
107 public ustring Prefix() const
108 {
109 if (nodeType == NodeType.elementNode || nodeType == NodeType.attributeNode)
110 {
111 long colonPos = name.Find(':');
112 if (colonPos != -1)
113 {
114 return name.Substring(0, colonPos);
115 }
116 }
117 return ustring();
118 }
119 public void SetPrefix(const ustring& prefix)
120 {
121 if (nodeType == NodeType.elementNode || nodeType == NodeType.attributeNode)
122 {
123 long colonPos = name.Find(':');
124 if (prefix.IsEmpty())
125 {
126 if (colonPos != -1)
127 {
128 name = name.Substring(colonPos + 1);
129 }
130 }
131 else
132 {
133 if (colonPos != -1)
134 {
135 name = prefix + u":" + name.Substring(colonPos + 1);
136 }
137 else
138 {
139 name = prefix + u":" + name;
140 }
141 }
142 }
143 else
144 {
145 throw DomException("cannot set prefix for this node type");
146 }
147 }
148 public ustring LocalName() const
149 {
150 if (nodeType == NodeType.elementNode || nodeType == NodeType.attributeNode)
151 {
152 long colonPos = name.Find(':');
153 if (colonPos != -1)
154 {
155 return name.Substring(colonPos + 1);
156 }
157 else
158 {
159 return name;
160 }
161 }
162 else
163 {
164 return ustring();
165 }
166 }
167 public void Walk(NodeOp& nodeOp, Axis axis)
168 {
169 switch (axis)
170 {
171 case Axis.child: WalkChildren(nodeOp);
172 break;
173 case Axis.descendant: WalkDescendant(nodeOp);
174 break;
175 case Axis.descendantOrSelf: WalkDescendantOrSelf(nodeOp);
176 break;
177 case Axis.parent: WalkParent(nodeOp);
178 break;
179 case Axis.ancestor: WalkAncestor(nodeOp);
180 break;
181 case Axis.ancestorOrSelf: WalkAncestorOrSelf(nodeOp);
182 break;
183 case Axis.followingSibling: WalkFollowingSibling(nodeOp);
184 break;
185 case Axis.precedingSibling: WalkPrecedingSibling(nodeOp);
186 break;
187 case Axis.following: WalkFollowing(nodeOp);
188 break;
189 case Axis.preceding: WalkPreceding(nodeOp);
190 break;
191 case Axis.attribute: WalkAttribute(nodeOp);
192 break;
193 case Axis.self: nodeOp.Apply(this);
194 break;
195 }
196 }
197 public void WalkParent(NodeOp& nodeOp)
198 {
199 if ((parent != null))
200 {
201 nodeOp.Apply(parent);
202 }
203 }
204 public void WalkAncestor(NodeOp& nodeOp)
205 {
206 if ((parent != null))
207 {
208 parent->WalkAncestorOrSelf(nodeOp);
209 }
210 }
211 public void WalkAncestorOrSelf(NodeOp& nodeOp)
212 {
213 nodeOp.Apply(this);
214 if ((parent != null))
215 {
216 parent->WalkAncestorOrSelf(nodeOp);
217 }
218 }
219 public void WalkFollowingSibling(NodeOp& nodeOp)
220 {
221 Node* ns = nextSibling;
222 if ((ns != null))
223 {
224 nodeOp.Apply(ns);
225 ns = ns->nextSibling;
226 }
227 }
228 public void WalkPrecedingSibling(NodeOp& nodeOp)
229 {
230 Node* ps = previousSibling;
231 if ((ps != null))
232 {
233 nodeOp.Apply(ps);
234 ps = ps->previousSibling;
235 }
236 }
237 public void InternalLinkBefore(Node* newNode)
238 {
239 newNode->previousSibling = previousSibling;
240 newNode->nextSibling = this;
241 previousSibling = newNode;
242 }
243 public void InternalLinkAfter(Node* newNode)
244 {
245 newNode->previousSibling = this;
246 newNode->nextSibling = nextSibling;
247 nextSibling = newNode;
248 }
249 public void InternalUnlink()
250 {
251 if ((previousSibling != null))
252 {
253 previousSibling->nextSibling = nextSibling;
254 }
255 if ((nextSibling != null))
256 {
257 nextSibling->previousSibling = previousSibling;
258 }
259 }
260 public void InternalSetNamespaceUri(const ustring& namespaceUri_)
261 {
262 namespaceUri = namespaceUri_;
263 }
264 public abstract UniquePtr<Node> CloneNode(bool deep);
265 public virtual bool HasChildNodes() const
266 {
267 return false;
268 }
269 public virtual bool HasAttributes() const
270 {
271 return false;
272 }
273 public abstract void Write(CodeFormatter& formatter);
274 public virtual bool ValueContainsNewLine() const
275 {
276 return false;
277 }
278 public virtual void Accept(Visitor& visitor)
279 {
280 }
281 public virtual void WalkChildren(NodeOp& nodeOp)
282 {
283 }
284 public virtual void WalkDescendant(NodeOp& nodeOp)
285 {
286 }
287 public virtual void WalkDescendantOrSelf(NodeOp& nodeOp)
288 {
289 nodeOp.Apply(this);
290 }
291 public virtual void WalkFollowing(NodeOp& nodeOp)
292 {
293 Node* ns = nextSibling;
294 if ((ns != null))
295 {
296 ns->WalkDescendantOrSelf(nodeOp);
297 ns = ns->nextSibling;
298 }
299 }
300 public virtual void WalkPreceding(NodeOp& nodeOp)
301 {
302 }
303 public virtual void WalkPrecedingOrSelf(NodeOp& nodeOp)
304 {
305 nodeOp.Apply(this);
306 }
307 public virtual void WalkAttribute(NodeOp& nodeOp)
308 {
309 }
310 private NodeType nodeType;
311 private ustring name;
312 private ustring namespaceUri;
313 private ParentNode* parent;
314 private Node* previousSibling;
315 private Node* nextSibling;
316 private Document* ownerDocument;
317 }
318 public abstract class ParentNode : Node
319 {
320 public suppress ParentNode(const Node&);
321 public suppress ParentNode(ParentNode&&);
322 public ParentNode(NodeType nodeType_, const ustring& name_) :
323 base(nodeType_, name_), firstChild(null), lastChild(null)
324 {
325 }
326 public override ~ParentNode()
327 {
328 Node* child = firstChild;
329 while (child != null)
330 {
331 Node* toDel = child;
332 child = child->NextSibling();
333 delete toDel;
334 }
335 }
336 public suppress ParentNode& operator=(const Node&);
337 public suppress ParentNode& operator=(ParentNode&&);
338 public Node* FirstChild() const
339 {
340 return firstChild;
341 }
342 public Node* LastChild() const
343 {
344 return lastChild;
345 }
346 public NodeList ChildNodes() const
347 {
348 NodeList result;
349 Node* child = firstChild;
350 while (child != null)
351 {
352 result.InternalAddNode(child);
353 child = child->NextSibling();
354 }
355 return result;
356 }
357 public void CloneChildrenTo(ParentNode* clone) const
358 {
359 Node* child = firstChild;
360 while (child != null)
361 {
362 clone->AppendChild(child->CloneNode(true));
363 child = child->NextSibling();
364 }
365 }
366 public override bool HasChildNodes() const
367 {
368 return firstChild != null;
369 }
370 public override void Write(CodeFormatter& formatter)
371 {
372 Node* child = firstChild;
373 while (child != null)
374 {
375 child->Write(formatter);
376 child = child->NextSibling();
377 }
378 }
379 public virtual Node* InsertBefore(UniquePtr<Node>&& newChild, Node* refChild)
380 {
381 if (refChild == null)
382 {
383 return AppendChild(Rvalue(newChild));
384 }
385 else
386 {
387 if ((OwnerDocument() != null))
388 {
389 OwnerDocument()->InternalInvalidateIndex();
390 }
391 if (newChild->GetNodeType() == NodeType.documentFragmentNode)
392 {
393 DocumentFragment* documentFragment = cast<DocumentFragment*>(newChild.Get());
394 Node* docFragChild = documentFragment->FirstChild();
395 Node* nodeInserted = null;
396 while (docFragChild != null)
397 {
398 UniquePtr<Node> docFragChildRemoved = documentFragment->RemoveChild(docFragChild);
399 nodeInserted = InsertBefore(Rvalue(docFragChildRemoved), refChild);
400 docFragChild = documentFragment->FirstChild();
401 }
402 return nodeInserted;
403 }
404 else
405 {
406 if ((newChild->Parent() != null))
407 {
408 newChild.Reset(newChild->Parent()->RemoveChild(newChild.Get()).Release());
409 }
410 if (firstChild == refChild)
411 {
412 firstChild = newChild.Get();
413 }
414 newChild->InternalSetParent(this);
415 newChild->InternalSetOwnerDocument(OwnerDocument());
416 Node* nodeInserted = newChild.Get();
417 refChild->InternalLinkBefore(newChild.Release());
418 return nodeInserted;
419 }
420 }
421 }
422 public virtual UniquePtr<Node> RemoveChild(Node* oldChild)
423 {
424 if (!(oldChild != null))
425 {
426 throw DomException("could not remove node: given old child is null");
427 }
428 if (oldChild->Parent() != this)
429 {
430 throw DomException("could not remove node: given old child is not child of this node");
431 }
432 if ((OwnerDocument() != null))
433 {
434 OwnerDocument()->InternalInvalidateIndex();
435 }
436 oldChild->InternalUnlink();
437 if (oldChild == firstChild)
438 {
439 firstChild = oldChild->NextSibling();
440 }
441 if (oldChild == lastChild)
442 {
443 lastChild = oldChild->PreviousSibling();
444 }
445 UniquePtr<Node> removedNode = UniquePtr<Node>(oldChild);
446 removedNode->InternalSetOwnerDocument(null);
447 removedNode->InternalSetParent(null);
448 return removedNode;
449 }
450 public virtual UniquePtr<Node> ReplaceChild(UniquePtr<Node>&& newChild, Node* oldChild)
451 {
452 if (!(oldChild != null))
453 {
454 throw DomException("could not replace node: given old child is null");
455 }
456 if (oldChild->Parent() != this)
457 {
458 throw DomException("could not replace node: given old child is not child of this node");
459 }
460 if ((OwnerDocument() != null))
461 {
462 OwnerDocument()->InternalInvalidateIndex();
463 }
464 if ((newChild->Parent() != null))
465 {
466 newChild.Reset(newChild->Parent()->RemoveChild(newChild.Get()).Release());
467 }
468 InsertBefore(Rvalue(newChild), oldChild);
469 return RemoveChild(oldChild);
470 }
471 public virtual Node* AppendChild(UniquePtr<Node>&& newChild)
472 {
473 if ((OwnerDocument() != null))
474 {
475 OwnerDocument()->InternalInvalidateIndex();
476 }
477 if ((newChild->Parent() != null))
478 {
479 newChild.Reset(newChild->Parent()->RemoveChild(newChild.Get()).Release());
480 }
481 if (newChild->GetNodeType() == NodeType.documentFragmentNode)
482 {
483 DocumentFragment* documentFragment = cast<DocumentFragment*>(newChild.Get());
484 Node* docFragChild = documentFragment->FirstChild();
485 Node* nodeInserted = null;
486 while (docFragChild != null)
487 {
488 UniquePtr<Node> docFragChildRemoved = documentFragment->RemoveChild(docFragChild);
489 nodeInserted = AppendChild(Rvalue(docFragChildRemoved));
490 docFragChild = documentFragment->FirstChild();
491 }
492 return nodeInserted;
493 }
494 else
495 {
496 if ((lastChild != null))
497 {
498 lastChild->InternalLinkAfter(newChild.Get());
499 }
500 if (!(firstChild != null))
501 {
502 firstChild = newChild.Get();
503 }
504 newChild->InternalSetOwnerDocument(OwnerDocument());
505 newChild->InternalSetParent(this);
506 lastChild = newChild.Release();
507 return lastChild;
508 }
509 }
510 public override void Accept(Visitor& visitor)
511 {
512 Node* child = firstChild;
513 while (child != null)
514 {
515 child->Accept(visitor);
516 child = child->NextSibling();
517 }
518 }
519 public override void WalkChildren(NodeOp& nodeOp)
520 {
521 Node* child = firstChild;
522 while (child != null)
523 {
524 nodeOp.Apply(child);
525 child = child->NextSibling();
526 }
527 }
528 public override void WalkDescendant(NodeOp& nodeOp)
529 {
530 Node* child = firstChild;
531 while (child != null)
532 {
533 child->WalkDescendantOrSelf(nodeOp);
534 child = child->NextSibling();
535 }
536 }
537 public override void WalkDescendantOrSelf(NodeOp& nodeOp)
538 {
539 base->WalkDescendantOrSelf(nodeOp);
540 Node* child = firstChild;
541 while (child != null)
542 {
543 child->WalkDescendantOrSelf(nodeOp);
544 child = child->NextSibling();
545 }
546 }
547 public override void WalkPrecedingOrSelf(NodeOp& nodeOp)
548 {
549 base->WalkPrecedingOrSelf(nodeOp);
550 Node* child = lastChild;
551 while (child != null)
552 {
553 child->WalkPrecedingOrSelf(nodeOp);
554 child = child->PreviousSibling();
555 }
556 }
557 public override void WalkPreceding(NodeOp& nodeOp)
558 {
559 Node* preceding = PreviousSibling();
560 if ((preceding != null))
561 {
562 preceding->WalkPrecedingOrSelf(nodeOp);
563 }
564 }
565 private Node* firstChild;
566 private Node* lastChild;
567 }
568 public class NodeList
569 {
570 public Node* Item(int index) const
571 {
572 return nodes[index];
573 }
574 public Node* operator[](int index) const
575 {
576 return nodes[index];
577 }
578 public int Length() const
579 {
580 return cast<int>(nodes.Count());
581 }
582 public void InternalAddNode(Node* node)
583 {
584 if (Find(nodes.Begin(), nodes.End(), node) == nodes.End())
585 {
586 nodes.Add(node);
587 }
588 }
589 private List<Node*> nodes;
590 }
591 public ustring AxisName(Axis axis)
592 {
593 switch (axis)
594 {
595 case Axis.child: return u"child";
596 case Axis.descendant: return u"descendant";
597 case Axis.parent: return u"parent";
598 case Axis.ancestor: return u"ancestor";
599 case Axis.followingSibling: return u"followingSibling";
600 case Axis.precedingSibling: return u"precedingSibling";
601 case Axis.following: return u"following";
602 case Axis.preceding: return u"preceding";
603 case Axis.attribute: return u"attribute";
604 case Axis.ns: return u"namespace";
605 case Axis.self: return u"self";
606 case Axis.descendantOrSelf: return u"descendantOrSelf";
607 case Axis.ancestorOrSelf: return u"ancestorOrSelf";
608 }
609 return ustring();
610 }
611 }