2003-06-25 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
[mono.git] / mcs / class / System.XML / System.Xml / XmlDocumentNavigator.cs
1 //
2 // System.Xml.XmlDocumentNavigator
3 //
4 // Author:
5 //   Jason Diamond <jason@injektilo.org>
6 //
7 // (C) 2002 Jason Diamond
8 //
9 \r
10 using System;\r
11 using System.Collections;\r
12 using System.Xml;\r
13 using System.Xml.XPath;\r
14 \r
15 namespace System.Xml\r
16 {\r
17         internal class XmlDocumentNavigator : XPathNavigator, IHasXmlNode\r
18         {\r
19                 #region Constructors\r
20 \r
21                 internal XmlDocumentNavigator(XmlNode node)\r
22                 {\r
23                         this.node = node;\r
24                         this.document = node.NodeType == XmlNodeType.Document ?\r
25                                 node as XmlDocument : node.OwnerDocument;\r
26                 }\r
27 \r
28                 #endregion\r
29 \r
30                 #region Fields\r
31 \r
32                 private XmlNode node;\r
33                 private XmlDocument document;\r
34                 private IEnumerator attributesEnumerator;\r
35 \r
36                 #endregion\r
37
38                 #region Properties
39
40                 public override string BaseURI {
41                         get {
42                                 return node.BaseURI;
43                         }
44                 }
45
46                 public override bool HasAttributes {
47                         get {
48                                 if (node.Attributes != null)
49                                         foreach (XmlAttribute attribute in node.Attributes)
50                                                 if (attribute.NamespaceURI != "http://www.w3.org/2000/xmlns/")
51                                                         return true;
52                                 return false;
53                         }
54                 }
55
56                 public override bool HasChildren {
57                         get {
58                                 XPathNodeType nodeType = NodeType;
59                                 bool canHaveChildren = nodeType == XPathNodeType.Root || nodeType == XPathNodeType.Element;
60                                 return canHaveChildren && node.FirstChild != null;
61                         }
62                 }
63
64                 public override bool IsEmptyElement {
65                         get {
66                                 return node.NodeType == XmlNodeType.Element 
67                                         && ((XmlElement) node).IsEmpty;
68                         }
69                 }
70
71                 public override string LocalName {
72                         get {
73                                 XPathNodeType nodeType = NodeType;
74                                 bool canHaveName = 
75                                         nodeType == XPathNodeType.Element || 
76                                         nodeType == XPathNodeType.Attribute || 
77                                         nodeType == XPathNodeType.ProcessingInstruction ||
78                                         nodeType == XPathNodeType.Namespace;
79                                 return canHaveName ? node.LocalName : String.Empty;
80                         }
81                 }
82
83                 public override string Name {
84                         get {
85                                 XPathNodeType nodeType = NodeType;
86                                 bool canHaveName = 
87                                         nodeType == XPathNodeType.Element || 
88                                         nodeType == XPathNodeType.Attribute || 
89                                         nodeType == XPathNodeType.ProcessingInstruction ||
90                                         nodeType == XPathNodeType.Namespace;
91                                 return canHaveName ? node.Name : String.Empty;
92                         }
93                 }
94
95                 public override string NamespaceURI {
96                         get {
97                                 return node.NamespaceURI;
98                         }
99                 }
100
101                 public override XmlNameTable NameTable {
102                         get {
103                                 return document.NameTable;
104                         }
105                 }
106
107                 public override XPathNodeType NodeType {
108                         get {
109                                 return node.XPathNodeType;
110                         }
111                 }
112
113                 public override string Prefix {
114                         get {
115                                 return node.Prefix;
116                         }
117                 }
118
119                 public override string Value {
120                         get {
121                                 switch (NodeType) {
122                                 case XPathNodeType.Attribute:
123                                 case XPathNodeType.Comment:
124                                 case XPathNodeType.ProcessingInstruction:
125                                 case XPathNodeType.Text:
126                                 case XPathNodeType.Whitespace:
127                                 case XPathNodeType.SignificantWhitespace:
128                                         return node.Value;
129                                 case XPathNodeType.Element:
130                                 case XPathNodeType.Root:
131                                         return node.InnerText;
132                                 }
133                                 return String.Empty;
134                         }
135                 }
136
137                 public override string XmlLang {
138                         get {
139                                 return node.XmlLang;
140                         }
141                 }
142
143                 #endregion
144
145                 #region Methods
146
147                 public override XPathNavigator Clone ()
148                 {
149                         return new XmlDocumentNavigator (node);
150                 }
151
152                 public override string GetAttribute (string localName, string namespaceURI)
153                 {
154                         XmlElement el = Node as XmlElement;
155                         return el != null ? el.GetAttribute (localName, namespaceURI) : String.Empty;
156                 }
157
158                 public override string GetNamespace (string name)
159                 {
160                         // MSDN says "String.Empty if a matching namespace 
161                         // node is not found or if the navigator is not 
162                         // positioned on an element node", but in fact it
163                         // returns actual namespace for the other nodes.
164                         return Node.GetNamespaceOfPrefix (name);
165                 }
166                 
167                 public override bool IsSamePosition (XPathNavigator other)
168                 {
169                         XmlDocumentNavigator otherDocumentNavigator = other as XmlDocumentNavigator;
170                         if (otherDocumentNavigator != null)
171                                 return node == otherDocumentNavigator.node;
172                         return false;
173                 }
174
175                 public override bool MoveTo (XPathNavigator other)
176                 {
177                         XmlDocumentNavigator otherDocumentNavigator = other as XmlDocumentNavigator;
178                         if (otherDocumentNavigator != null) {
179                                 if (document == otherDocumentNavigator.document) {
180                                         node = otherDocumentNavigator.node;
181                                         return true;
182                                 }
183                         }
184                         return false;
185                 }
186
187                 public override bool MoveToAttribute (string localName, string namespaceURI)
188                 {
189                         attributesEnumerator = node.Attributes.GetEnumerator ();
190                         while (attributesEnumerator.MoveNext ()) {
191                                 XmlAttribute attr = attributesEnumerator.Current as XmlAttribute;
192                                 if (attr.LocalName == localName && attr.NamespaceURI == namespaceURI) {
193                                         node = attr;
194                                         return true;
195                                 }
196                         }
197                         return false;
198                 }
199
200                 public override bool MoveToFirst ()
201                 {
202                         if (node.NodeType != XmlNodeType.Attribute && node.ParentNode != null) {
203                                 MoveToParent ();
204                                 // Follow these 2 steps so that we can skip 
205                                 // some types of nodes .
206                                 MoveToFirstChild ();
207                                 return true;
208                         }
209                         return false;
210                 }
211
212                 public override bool MoveToFirstAttribute ()
213                 {
214                         if (NodeType == XPathNodeType.Element) {
215                                 attributesEnumerator = node.Attributes.GetEnumerator ();
216                                 return MoveToNextAttribute ();
217                         }
218                         return false;
219                 }
220
221                 public override bool MoveToFirstChild ()
222                 {
223                         if (HasChildren) {
224                                 if (node == document) {
225                                         XmlNode n = node.FirstChild;
226                                         if (n == null)
227                                                 return false;
228                                         bool loop = true;
229                                         do {
230                                                 switch (n.NodeType) {
231                                                 case XmlNodeType.XmlDeclaration:
232                                                 case XmlNodeType.DocumentType:
233                                                         n = n.NextSibling;
234                                                         if (n == null)
235                                                                 return false;
236                                                         break;
237                                                 default:
238                                                         loop = false;
239                                                         break;
240                                                 }
241                                         } while (loop);
242                                         node = n;
243                                 }
244                                 else
245                                         node = node.FirstChild;
246                                 return true;
247                         }
248                         return false;
249                 }
250
251                 [MonoTODO]
252                 public override bool MoveToFirstNamespace (XPathNamespaceScope namespaceScope)
253                 {
254                         throw new NotImplementedException ();
255                 }
256
257                 public override bool MoveToId (string id)
258                 {
259                         XmlElement eltNew = document.GetElementById (id);
260                         if (eltNew == null)
261                                 return false;
262
263                         node = eltNew;
264                         return true;
265                 }
266
267                 [MonoTODO]
268                 public override bool MoveToNamespace (string name)
269                 {
270                         throw new NotImplementedException ();
271                 }
272
273                 public override bool MoveToNext ()
274                 {
275                         if (node.NextSibling != null) {
276                                 if (node.ParentNode != null && node.ParentNode.NodeType == XmlNodeType.Document) {
277                                         XmlNode n = node.NextSibling;
278                                         while (n != null) {
279                                                 switch (n.NodeType) {
280                                                 case XmlNodeType.DocumentType:
281                                                 case XmlNodeType.XmlDeclaration:
282                                                         n = n.NextSibling;
283                                                         continue;
284                                                 }
285                                                 break;
286                                         }
287                                         if (n != null)
288                                                 node = n;
289                                         else
290                                                 return false;
291                                 }
292                                 else
293                                         node = node.NextSibling;
294                                 return true;
295                         }
296                         else
297                                 return false;
298                 }
299
300                 public override bool MoveToNextAttribute ()
301                 {
302                         if (attributesEnumerator != null && attributesEnumerator.MoveNext ()) {
303                                 node = attributesEnumerator.Current as XmlAttribute;
304                                 return true;
305                         }
306                         return false;
307                 }
308
309                 [MonoTODO]
310                 public override bool MoveToNextNamespace (XPathNamespaceScope namespaceScope)
311                 {
312                         throw new NotImplementedException ();
313                 }
314
315                 public override bool MoveToParent ()
316                 {
317                         if (node.NodeType == XmlNodeType.Attribute) {
318                                 XmlElement ownerElement = ((XmlAttribute)node).OwnerElement;
319                                 if (ownerElement != null) {
320                                         node = ownerElement;
321                                         return true;
322                                 }
323                         } else if (node.ParentNode != null) {
324                                 node = node.ParentNode;
325                                 return true;
326                         }
327                         return false;
328                 }
329
330                 public override bool MoveToPrevious ()
331                 {
332                         if (node.PreviousSibling != null) {
333                                 node = node.PreviousSibling;
334                                 return true;
335                         }
336                         return false;
337                 }
338
339                 public override void MoveToRoot ()
340                 {
341                         node = document;
342                 }
343
344                 internal XmlNode Node { get { return node; } }
345
346                 XmlNode IHasXmlNode.GetNode ()
347                 {
348                         return node;
349                 }
350
351                 #endregion
352         }\r
353 }\r