1
2
3
4
5
6 using System;
7
8 namespace System.Xml
9 {
10 public enum NodeKind
11 {
12 attributeNode, documentFragmentNode, documentNode, elementNode, entityNode, entityReferenceNode, notationNode,
13 processingInstructionNode, textNode, cdataSectionNode, commentNode
14 }
15
16 public string NodeKindStr(NodeKind kind)
17 {
18 switch (kind)
19 {
20 case NodeKind.attributeNode: return "attributeNode";
21 case NodeKind.documentFragmentNode: return "documentFragementNode";
22 case NodeKind.documentNode: return "documentNode";
23 case NodeKind.elementNode: return "elementNode";
24 case NodeKind.entityNode: return "entityNode";
25 case NodeKind.entityReferenceNode: return "entityReferenceNode";
26 case NodeKind.notationNode: return "notationNode";
27 case NodeKind.processingInstructionNode: return "processingInstructionNode";
28 case NodeKind.textNode: return "textNode";
29 case NodeKind.cdataSectionNode: return "cdataSectionNode";
30 case NodeKind.commentNode: return "commentNode";
31 }
32 return "<unknown node kind>";
33 }
34
35 public abstract class Node
36 {
37 public Node(NodeKind kind_, const System.Lex.Span& span_, int fileIndex_, const string& name_) :
38 kind(kind_), span(span_), fileIndex(fileIndex_), name(name_), parent(null), prev(null), next(null), ownerDocument(null)
39 {
40 }
41 public virtual default ~Node();
42 public inline NodeKind Kind() const
43 {
44 return kind;
45 }
46 public const System.Lex.Span& Span() const
47 {
48 return span;
49 }
50 public inline int FileIndex() const
51 {
52 return fileIndex;
53 }
54 public const string& Name() const
55 {
56 return name;
57 }
58 public const string& NamespaceUri() const
59 {
60 return namespaceUri;
61 }
62 public void SetNamespaceUri(const string& namespaceUri_)
63 {
64 namespaceUri = namespaceUri_;
65 }
66 public inline bool IsAttributeNode() const
67 {
68 return kind == NodeKind.attributeNode;
69 }
70 public inline bool IsDocumentFragmentNode() const
71 {
72 return kind == NodeKind.documentFragmentNode;
73 }
74 public inline bool IsDocumentNode() const
75 {
76 return kind == NodeKind.documentNode;
77 }
78 public inline bool IsElementNode() const
79 {
80 return kind == NodeKind.elementNode;
81 }
82 public inline bool IsEntityNode() const
83 {
84 return kind == NodeKind.entityNode;
85 }
86 public inline bool IsEntityReferenceNode() const
87 {
88 return kind == NodeKind.entityReferenceNode;
89 }
90 public inline bool IsNotationNode() const
91 {
92 return kind == NodeKind.notationNode;
93 }
94 public inline bool IsProcessingInstructionNode() const
95 {
96 return kind == NodeKind.processingInstructionNode;
97 }
98 public inline bool IsTextNode() const
99 {
100 return kind == NodeKind.textNode;
101 }
102 public inline bool IsCDataSectionNode() const
103 {
104 return kind == NodeKind.cdataSectionNode;
105 }
106 public inline bool IsCommentNode() const
107 {
108 return kind == NodeKind.commentNode;
109 }
110 public ParentNode* Parent() const
111 {
112 return parent;
113 }
114 public void SetParent(ParentNode* parent_)
115 {
116 parent = parent_;
117 }
118 public Node* Prev() const
119 {
120 return prev;
121 }
122 public void SetPrev(Node* prev_)
123 {
124 prev = prev_;
125 }
126 public Node* Next() const
127 {
128 return next;
129 }
130 public void SetNext(Node* next_)
131 {
132 next = next_;
133 }
134 public void LinkBefore(Node* node)
135 {
136 if (prev != null)
137 {
138 prev->next = node;
139 }
140 node->prev = prev;
141 node->next = this;
142 prev = node;
143 }
144 public void LinkAfter(Node* node)
145 {
146 if (next != null)
147 {
148 next->prev = node;
149 }
150 node->prev = this;
151 node->next = next;
152 next = node;
153 }
154 public void Unlink()
155 {
156 if (prev != null)
157 {
158 prev->next = next;
159 }
160 if (next != null)
161 {
162 next->prev = prev;
163 }
164 }
165 public Document* OwnerDocument() const
166 {
167 return ownerDocument;
168 }
169 public void SetOwnerDocument(Document* ownerDocument_)
170 {
171 ownerDocument = ownerDocument_;
172 }
173 public string Prefix() const
174 {
175 if (IsElementNode() || IsAttributeNode())
176 {
177 auto colonPos = name.Find(':');
178 if (colonPos != -1)
179 {
180 return name.Substring(0, colonPos);
181 }
182 }
183 return string();
184 }
185 public void SetPrefix(const string& prefix)
186 {
187 if (IsElementNode() || IsAttributeNode())
188 {
189 auto colonPos = name.Find(':');
190 if (prefix.IsEmpty())
191 {
192 if (colonPos != -1)
193 {
194 name = name.Substring(colonPos + 1);
195 }
196 }
197 else
198 {
199 if (colonPos != -1)
200 {
201 name = prefix + ":" + name.Substring(colonPos + 1);
202 }
203 else
204 {
205 name = prefix + ":" + name;
206 }
207 }
208 }
209 }
210 public string LocalName() const
211 {
212 if (IsElementNode() || IsAttributeNode())
213 {
214 auto colonPos = name.Find(':');
215 if (colonPos != -1)
216 {
217 return name.Substring(colonPos + 1);
218 }
219 else
220 {
221 return name;
222 }
223 }
224 else
225 {
226 return string();
227 }
228 }
229 public virtual void Accept(Visitor& visitor)
230 {
231 }
232 public virtual bool HasChildNodes() const
233 {
234 return false;
235 }
236 public virtual bool HasAttributes() const
237 {
238 return false;
239 }
240 public virtual bool ValueContainsNewLine() const
241 {
242 return false;
243 }
244 public abstract Node* Clone(bool deep) const;
245 public abstract Result<bool> Write(System.Text.CodeFormatter& formatter);
246 public void Walk(NodeOperation& operation, Axis axis)
247 {
248 switch (axis)
249 {
250 case Axis.child:
251 {
252 WalkChildren(operation);
253 break;
254 }
255 case Axis.descendant:
256 {
257 WalkDescendant(operation);
258 break;
259 }
260 case Axis.descendantOrSelf:
261 {
262 WalkDescendantOrSelf(operation);
263 break;
264 }
265 case Axis.parent:
266 {
267 WalkParent(operation);
268 break;
269 }
270 case Axis.ancestor:
271 {
272 WalkAncestor(operation);
273 break;
274 }
275 case Axis.ancestorOrSelf:
276 {
277 WalkAncestorOrSelf(operation);
278 break;
279 }
280 case Axis.followingSibling:
281 {
282 WalkFollowingSibling(operation);
283 break;
284 }
285 case Axis.precedingSibling:
286 {
287 WalkPrecedingSibling(operation);
288 break;
289 }
290 case Axis.following:
291 {
292 WalkFollowing(operation);
293 break;
294 }
295 case Axis.preceding:
296 {
297 WalkPreceding(operation);
298 break;
299 }
300 case Axis.attribute:
301 {
302 WalkAttribute(operation);
303 break;
304 }
305 case Axis.self:
306 {
307 operation.Apply(this);
308 break;
309 }
310 }
311 }
312 public virtual void WalkChildren(NodeOperation& operation)
313 {
314 }
315 public virtual void WalkDescendant(NodeOperation& operation)
316 {
317 }
318 public virtual void WalkDescendantOrSelf(NodeOperation& operation)
319 {
320 operation.Apply(this);
321 }
322 public void WalkParent(NodeOperation& operation)
323 {
324 if (parent != null)
325 {
326 operation.Apply(parent);
327 }
328 }
329 public virtual void WalkFollowing(NodeOperation& operation)
330 {
331 Node* n = next;
332 if (n != null)
333 {
334 n->WalkDescendantOrSelf(operation);
335 }
336 }
337 public virtual void WalkPreceding(NodeOperation& operation)
338 {
339 }
340 public virtual void WalkPrecedingOrSelf(NodeOperation& operation)
341 {
342 operation.Apply(this);
343 }
344 public void WalkAncestor(NodeOperation& operation)
345 {
346 if (parent != null)
347 {
348 parent->WalkAncestorOrSelf(operation);
349 }
350 }
351 public void WalkAncestorOrSelf(NodeOperation& operation)
352 {
353 operation.Apply(this);
354 if (parent != null)
355 {
356 parent->WalkAncestorOrSelf(operation);
357 }
358 }
359 public void WalkFollowingSibling(NodeOperation& operation)
360 {
361 Node* n = next;
362 while (n != null)
363 {
364 operation.Apply(n);
365 n = n->next;
366 }
367 }
368 public void WalkPrecedingSibling(NodeOperation& operation)
369 {
370 Node* p = prev;
371 while (p != null)
372 {
373 operation.Apply(p);
374 p = p->prev;
375 }
376 }
377 public virtual void WalkAttribute(NodeOperation& operation)
378 {
379 }
380 private NodeKind kind;
381 private System.Lex.Span span;
382 private int fileIndex;
383 private string name;
384 private string namespaceUri;
385 private ParentNode* parent;
386 private Node* prev;
387 private Node* next;
388 private Document* ownerDocument;
389 }