2003-06-10 Duncan Mak <duncan@ximian.com>
[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 && !HasChildren;
67                         }
68                 }
69
70                 public override string LocalName {
71                         get {
72                                 XPathNodeType nodeType = NodeType;
73                                 bool canHaveName = 
74                                         nodeType == XPathNodeType.Element || 
75                                         nodeType == XPathNodeType.Attribute || 
76                                         nodeType == XPathNodeType.ProcessingInstruction ||
77                                         nodeType == XPathNodeType.Namespace;
78                                 return canHaveName ? node.LocalName : String.Empty;
79                         }
80                 }
81
82                 public override string Name {
83                         get {
84                                 XPathNodeType nodeType = NodeType;
85                                 bool canHaveName = 
86                                         nodeType == XPathNodeType.Element || 
87                                         nodeType == XPathNodeType.Attribute || 
88                                         nodeType == XPathNodeType.ProcessingInstruction ||
89                                         nodeType == XPathNodeType.Namespace;
90                                 return canHaveName ? node.Name : String.Empty;
91                         }
92                 }
93
94                 public override string NamespaceURI {
95                         get {
96                                 return node.NamespaceURI;
97                         }
98                 }
99
100                 public override XmlNameTable NameTable {
101                         get {
102                                 return document.NameTable;
103                         }
104                 }
105
106                 public override XPathNodeType NodeType {
107                         get {
108                                 return node.XPathNodeType;
109                         }
110                 }
111
112                 public override string Prefix {
113                         get {
114                                 return node.Prefix;
115                         }
116                 }
117
118                 public override string Value {
119                         get {
120                                 switch (NodeType) {
121                                 case XPathNodeType.Attribute:
122                                 case XPathNodeType.Comment:
123                                 case XPathNodeType.ProcessingInstruction:
124                                 case XPathNodeType.Text:
125                                 case XPathNodeType.Whitespace:
126                                 case XPathNodeType.SignificantWhitespace:
127                                         return node.Value;
128                                 case XPathNodeType.Element:
129                                 case XPathNodeType.Root:
130                                         return node.InnerText;
131                                 }
132                                 return String.Empty;
133                         }
134                 }
135
136                 public override string XmlLang {
137                         get {
138                                 return node.XmlLang;
139                         }
140                 }
141
142                 #endregion
143
144                 #region Methods
145
146                 public override XPathNavigator Clone ()
147                 {
148                         return new XmlDocumentNavigator (node);
149                 }
150
151                 public override string GetAttribute (string localName, string namespaceURI)
152                 {
153                         XmlElement el = Node as XmlElement;
154                         return (el != null) ? el.GetAttribute (localName, namespaceURI) : String.Empty;
155                 }
156
157                 public override string GetNamespace (string name)
158                 {
159                         // MSDN says "String.Empty if a matching namespace 
160                         // node is not found or if the navigator is not 
161                         // positioned on an element node", but in fact it
162                         // returns actual namespace for the other nodes.
163                         return Node.GetNamespaceOfPrefix (name);
164                 }
165                 
166                 public override bool IsSamePosition (XPathNavigator other)
167                 {
168                         XmlDocumentNavigator otherDocumentNavigator = other as XmlDocumentNavigator;
169                         if (otherDocumentNavigator != null)
170                                 return node == otherDocumentNavigator.node;
171                         return false;
172                 }
173
174                 public override bool MoveTo (XPathNavigator other)
175                 {
176                         XmlDocumentNavigator otherDocumentNavigator = other as XmlDocumentNavigator;
177                         if (otherDocumentNavigator != null) {
178                                 if (document == otherDocumentNavigator.document) {
179                                         node = otherDocumentNavigator.node;
180                                         return true;
181                                 }
182                         }
183                         return false;
184                 }
185
186                 public override bool MoveToAttribute (string localName, string namespaceURI)
187                 {
188                         attributesEnumerator = node.Attributes.GetEnumerator ();
189                         while (attributesEnumerator.MoveNext ()) {
190                                 XmlAttribute attr = attributesEnumerator.Current as XmlAttribute;
191                                 if (attr.LocalName == localName && attr.NamespaceURI == namespaceURI) {
192                                         node = attr;
193                                         return true;
194                                 }
195                         }
196                         return false;
197                 }
198
199                 public override bool MoveToFirst ()
200                 {
201                         if (node.NodeType != XmlNodeType.Attribute && node.ParentNode != null) {
202                                 node = node.ParentNode.FirstChild;
203                                 return true;
204                         }
205                         return false;
206                 }
207
208                 public override bool MoveToFirstAttribute ()
209                 {
210                         if (NodeType == XPathNodeType.Element) {
211                                 attributesEnumerator = node.Attributes.GetEnumerator ();
212                                 return MoveToNextAttribute ();
213                         }
214                         return false;
215                 }
216
217                 public override bool MoveToFirstChild ()
218                 {
219                         if (HasChildren) {
220                                 if (node == document) {
221                                         XmlNode n = node.FirstChild;
222                                         if (n == null)
223                                                 return false;
224                                         bool loop = true;
225                                         do {
226                                                 switch (n.NodeType) {
227                                                 case XmlNodeType.XmlDeclaration:
228                                                 case XmlNodeType.DocumentType:
229                                                         n = n.NextSibling;
230                                                         if (n == null)
231                                                                 return false;
232                                                         break;
233                                                 default:
234                                                         loop = false;
235                                                         break;
236                                                 }
237                                         } while (loop);
238                                         node = n;
239                                 }
240                                 else
241                                         node = node.FirstChild;
242                                 return true;
243                         }
244                         return false;
245                 }
246
247                 [MonoTODO]
248                 public override bool MoveToFirstNamespace (XPathNamespaceScope namespaceScope)
249                 {
250                         throw new NotImplementedException ();
251                 }
252
253                 public override bool MoveToId (string id)
254                 {
255                         XmlElement eltNew = document.GetElementById (id);
256                         if (eltNew == null)
257                                 return false;
258
259                         node = eltNew;
260                         return true;
261                 }
262
263                 [MonoTODO]
264                 public override bool MoveToNamespace (string name)
265                 {
266                         throw new NotImplementedException ();
267                 }
268
269                 public override bool MoveToNext ()
270                 {
271                         if (node.NextSibling != null) {
272                                 node = node.NextSibling;
273                                 return true;
274                         }
275                         return false;
276                 }
277
278                 public override bool MoveToNextAttribute ()
279                 {
280                         if (attributesEnumerator != null && attributesEnumerator.MoveNext ()) {
281                                 node = attributesEnumerator.Current as XmlAttribute;
282                                 return true;
283                         }
284                         return false;
285                 }
286
287                 [MonoTODO]
288                 public override bool MoveToNextNamespace (XPathNamespaceScope namespaceScope)
289                 {
290                         throw new NotImplementedException ();
291                 }
292
293                 public override bool MoveToParent ()
294                 {
295                         if (node.NodeType == XmlNodeType.Attribute) {
296                                 XmlElement ownerElement = ((XmlAttribute)node).OwnerElement;
297                                 if (ownerElement != null) {
298                                         node = ownerElement;
299                                         return true;
300                                 }
301                         } else if (node.ParentNode != null) {
302                                 node = node.ParentNode;
303                                 return true;
304                         }
305                         return false;
306                 }
307
308                 public override bool MoveToPrevious ()
309                 {
310                         if (node.PreviousSibling != null) {
311                                 node = node.PreviousSibling;
312                                 return true;
313                         }
314                         return false;
315                 }
316
317                 public override void MoveToRoot ()
318                 {
319                         node = document;
320                 }
321
322                 internal XmlNode Node { get { return node; } }
323
324                 XmlNode IHasXmlNode.GetNode ()
325                 {
326                         return node;
327                 }
328
329                 #endregion
330         }\r
331 }\r