Fix eglib targets and filters.
[mono.git] / docs / HtmlAgilityPack / HtmlNodeNavigator.cs
1 // HtmlAgilityPack V1.0 - Simon Mourier <simon underscore mourier at hotmail dot com>\r
2 using System;\r
3 using System.Diagnostics;\r
4 using System.IO;\r
5 using System.Text;\r
6 using System.Xml;\r
7 using System.Xml.XPath;\r
8 \r
9 namespace HtmlAgilityPack\r
10 {\r
11     /// <summary>\r
12     /// Represents an HTML navigator on an HTML document seen as a data store.\r
13     /// </summary>\r
14     public class HtmlNodeNavigator : XPathNavigator\r
15     {\r
16         #region Fields\r
17 \r
18         private int _attindex;\r
19         private HtmlNode _currentnode;\r
20         private HtmlDocument _doc = new HtmlDocument();\r
21         private HtmlNameTable _nametable = new HtmlNameTable();\r
22 \r
23         internal bool Trace;\r
24 \r
25         #endregion\r
26 \r
27         #region Constructors\r
28 \r
29         internal HtmlNodeNavigator()\r
30         {\r
31             Reset();\r
32         }\r
33 \r
34         internal HtmlNodeNavigator(HtmlDocument doc, HtmlNode currentNode)\r
35         {\r
36             if (currentNode == null)\r
37             {\r
38                 throw new ArgumentNullException("currentNode");\r
39             }\r
40             if (currentNode.OwnerDocument != doc)\r
41             {\r
42                 throw new ArgumentException(HtmlDocument.HtmlExceptionRefNotChild);\r
43             }\r
44             InternalTrace(null);\r
45 \r
46             _doc = doc;\r
47             Reset();\r
48             _currentnode = currentNode;\r
49         }\r
50 \r
51         private HtmlNodeNavigator(HtmlNodeNavigator nav)\r
52         {\r
53             if (nav == null)\r
54             {\r
55                 throw new ArgumentNullException("nav");\r
56             }\r
57             InternalTrace(null);\r
58 \r
59             _doc = nav._doc;\r
60             _currentnode = nav._currentnode;\r
61             _attindex = nav._attindex;\r
62             _nametable = nav._nametable; // REVIEW: should we do this?\r
63         }\r
64 \r
65         /// <summary>\r
66         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a stream.\r
67         /// </summary>\r
68         /// <param name="stream">The input stream.</param>\r
69         public HtmlNodeNavigator(Stream stream)\r
70         {\r
71             _doc.Load(stream);\r
72             Reset();\r
73         }\r
74 \r
75         /// <summary>\r
76         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a stream.\r
77         /// </summary>\r
78         /// <param name="stream">The input stream.</param>\r
79         /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the stream.</param>\r
80         public HtmlNodeNavigator(Stream stream, bool detectEncodingFromByteOrderMarks)\r
81         {\r
82             _doc.Load(stream, detectEncodingFromByteOrderMarks);\r
83             Reset();\r
84         }\r
85 \r
86         /// <summary>\r
87         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a stream.\r
88         /// </summary>\r
89         /// <param name="stream">The input stream.</param>\r
90         /// <param name="encoding">The character encoding to use.</param>\r
91         public HtmlNodeNavigator(Stream stream, Encoding encoding)\r
92         {\r
93             _doc.Load(stream, encoding);\r
94             Reset();\r
95         }\r
96 \r
97         /// <summary>\r
98         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a stream.\r
99         /// </summary>\r
100         /// <param name="stream">The input stream.</param>\r
101         /// <param name="encoding">The character encoding to use.</param>\r
102         /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the stream.</param>\r
103         public HtmlNodeNavigator(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks)\r
104         {\r
105             _doc.Load(stream, encoding, detectEncodingFromByteOrderMarks);\r
106             Reset();\r
107         }\r
108 \r
109         /// <summary>\r
110         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a stream.\r
111         /// </summary>\r
112         /// <param name="stream">The input stream.</param>\r
113         /// <param name="encoding">The character encoding to use.</param>\r
114         /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the stream.</param>\r
115         /// <param name="buffersize">The minimum buffer size.</param>\r
116         public HtmlNodeNavigator(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize)\r
117         {\r
118             _doc.Load(stream, encoding, detectEncodingFromByteOrderMarks, buffersize);\r
119             Reset();\r
120         }\r
121 \r
122         /// <summary>\r
123         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a TextReader.\r
124         /// </summary>\r
125         /// <param name="reader">The TextReader used to feed the HTML data into the document.</param>\r
126         public HtmlNodeNavigator(TextReader reader)\r
127         {\r
128             _doc.Load(reader);\r
129             Reset();\r
130         }\r
131 \r
132         /// <summary>\r
133         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a file.\r
134         /// </summary>\r
135         /// <param name="path">The complete file path to be read.</param>\r
136         public HtmlNodeNavigator(string path)\r
137         {\r
138             _doc.Load(path);\r
139             Reset();\r
140         }\r
141 \r
142         /// <summary>\r
143         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a file.\r
144         /// </summary>\r
145         /// <param name="path">The complete file path to be read.</param>\r
146         /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the file.</param>\r
147         public HtmlNodeNavigator(string path, bool detectEncodingFromByteOrderMarks)\r
148         {\r
149             _doc.Load(path, detectEncodingFromByteOrderMarks);\r
150             Reset();\r
151         }\r
152 \r
153         /// <summary>\r
154         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a file.\r
155         /// </summary>\r
156         /// <param name="path">The complete file path to be read.</param>\r
157         /// <param name="encoding">The character encoding to use.</param>\r
158         public HtmlNodeNavigator(string path, Encoding encoding)\r
159         {\r
160             _doc.Load(path, encoding);\r
161             Reset();\r
162         }\r
163 \r
164         /// <summary>\r
165         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a file.\r
166         /// </summary>\r
167         /// <param name="path">The complete file path to be read.</param>\r
168         /// <param name="encoding">The character encoding to use.</param>\r
169         /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the file.</param>\r
170         public HtmlNodeNavigator(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks)\r
171         {\r
172             _doc.Load(path, encoding, detectEncodingFromByteOrderMarks);\r
173             Reset();\r
174         }\r
175 \r
176         /// <summary>\r
177         /// Initializes a new instance of the HtmlNavigator and loads an HTML document from a file.\r
178         /// </summary>\r
179         /// <param name="path">The complete file path to be read.</param>\r
180         /// <param name="encoding">The character encoding to use.</param>\r
181         /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the file.</param>\r
182         /// <param name="buffersize">The minimum buffer size.</param>\r
183         public HtmlNodeNavigator(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize)\r
184         {\r
185             _doc.Load(path, encoding, detectEncodingFromByteOrderMarks, buffersize);\r
186             Reset();\r
187         }\r
188 \r
189         #endregion\r
190 \r
191         #region Properties\r
192 \r
193         /// <summary>\r
194         /// Gets the base URI for the current node.\r
195         /// Always returns string.Empty in the case of HtmlNavigator implementation.\r
196         /// </summary>\r
197         public override string BaseURI\r
198         {\r
199             get\r
200             {\r
201                 InternalTrace(">");\r
202                 return _nametable.GetOrAdd(string.Empty);\r
203             }\r
204         }\r
205 \r
206         /// <summary>\r
207         /// Gets the current HTML document.\r
208         /// </summary>\r
209         public HtmlDocument CurrentDocument\r
210         {\r
211             get { return _doc; }\r
212         }\r
213 \r
214         /// <summary>\r
215         /// Gets the current HTML node.\r
216         /// </summary>\r
217         public HtmlNode CurrentNode\r
218         {\r
219             get { return _currentnode; }\r
220         }\r
221 \r
222         /// <summary>\r
223         /// Gets a value indicating whether the current node has child nodes.\r
224         /// </summary>\r
225         public override bool HasAttributes\r
226         {\r
227             get\r
228             {\r
229                 InternalTrace(">" + (_currentnode.Attributes.Count > 0));\r
230                 return (_currentnode.Attributes.Count > 0);\r
231             }\r
232         }\r
233 \r
234         /// <summary>\r
235         /// Gets a value indicating whether the current node has child nodes.\r
236         /// </summary>\r
237         public override bool HasChildren\r
238         {\r
239             get\r
240             {\r
241                 InternalTrace(">" + (_currentnode.ChildNodes.Count > 0));\r
242                 return (_currentnode.ChildNodes.Count > 0);\r
243             }\r
244         }\r
245 \r
246         /// <summary>\r
247         /// Gets a value indicating whether the current node is an empty element.\r
248         /// </summary>\r
249         public override bool IsEmptyElement\r
250         {\r
251             get\r
252             {\r
253                 InternalTrace(">" + !HasChildren);\r
254                 // REVIEW: is this ok?\r
255                 return !HasChildren;\r
256             }\r
257         }\r
258 \r
259         /// <summary>\r
260         /// Gets the name of the current HTML node without the namespace prefix.\r
261         /// </summary>\r
262         public override string LocalName\r
263         {\r
264             get\r
265             {\r
266                 if (_attindex != -1)\r
267                 {\r
268                     InternalTrace("att>" + _currentnode.Attributes[_attindex].Name);\r
269                     return _nametable.GetOrAdd(_currentnode.Attributes[_attindex].Name);\r
270                 }\r
271                 InternalTrace("node>" + _currentnode.Name);\r
272                 return _nametable.GetOrAdd(_currentnode.Name);\r
273             }\r
274         }\r
275 \r
276         /// <summary>\r
277         /// Gets the qualified name of the current node.\r
278         /// </summary>\r
279         public override string Name\r
280         {\r
281             get\r
282             {\r
283                 InternalTrace(">" + _currentnode.Name);\r
284                 return _nametable.GetOrAdd(_currentnode.Name);\r
285             }\r
286         }\r
287 \r
288         /// <summary>\r
289         /// Gets the namespace URI (as defined in the W3C Namespace Specification) of the current node.\r
290         /// Always returns string.Empty in the case of HtmlNavigator implementation.\r
291         /// </summary>\r
292         public override string NamespaceURI\r
293         {\r
294             get\r
295             {\r
296                 InternalTrace(">");\r
297                 return _nametable.GetOrAdd(string.Empty);\r
298             }\r
299         }\r
300 \r
301         /// <summary>\r
302         /// Gets the <see cref="XmlNameTable"/> associated with this implementation.\r
303         /// </summary>\r
304         public override XmlNameTable NameTable\r
305         {\r
306             get\r
307             {\r
308                 InternalTrace(null);\r
309                 return _nametable;\r
310             }\r
311         }\r
312 \r
313         /// <summary>\r
314         /// Gets the type of the current node.\r
315         /// </summary>\r
316         public override XPathNodeType NodeType\r
317         {\r
318             get\r
319             {\r
320                 switch (_currentnode.NodeType)\r
321                 {\r
322                     case HtmlNodeType.Comment:\r
323                         InternalTrace(">" + XPathNodeType.Comment);\r
324                         return XPathNodeType.Comment;\r
325 \r
326                     case HtmlNodeType.Document:\r
327                         InternalTrace(">" + XPathNodeType.Root);\r
328                         return XPathNodeType.Root;\r
329 \r
330                     case HtmlNodeType.Text:\r
331                         InternalTrace(">" + XPathNodeType.Text);\r
332                         return XPathNodeType.Text;\r
333 \r
334                     case HtmlNodeType.Element:\r
335                         {\r
336                             if (_attindex != -1)\r
337                             {\r
338                                 InternalTrace(">" + XPathNodeType.Attribute);\r
339                                 return XPathNodeType.Attribute;\r
340                             }\r
341                             InternalTrace(">" + XPathNodeType.Element);\r
342                             return XPathNodeType.Element;\r
343                         }\r
344 \r
345                     default:\r
346                         throw new NotImplementedException("Internal error: Unhandled HtmlNodeType: " +\r
347                                                           _currentnode.NodeType);\r
348                 }\r
349             }\r
350         }\r
351 \r
352         /// <summary>\r
353         /// Gets the prefix associated with the current node.\r
354         /// Always returns string.Empty in the case of HtmlNavigator implementation.\r
355         /// </summary>\r
356         public override string Prefix\r
357         {\r
358             get\r
359             {\r
360                 InternalTrace(null);\r
361                 return _nametable.GetOrAdd(string.Empty);\r
362             }\r
363         }\r
364 \r
365         /// <summary>\r
366         /// Gets the text value of the current node.\r
367         /// </summary>\r
368         public override string Value\r
369         {\r
370             get\r
371             {\r
372                 InternalTrace("nt=" + _currentnode.NodeType);\r
373                 switch (_currentnode.NodeType)\r
374                 {\r
375                     case HtmlNodeType.Comment:\r
376                         InternalTrace(">" + ((HtmlCommentNode) _currentnode).Comment);\r
377                         return ((HtmlCommentNode) _currentnode).Comment;\r
378 \r
379                     case HtmlNodeType.Document:\r
380                         InternalTrace(">");\r
381                         return "";\r
382 \r
383                     case HtmlNodeType.Text:\r
384                         InternalTrace(">" + ((HtmlTextNode) _currentnode).Text);\r
385                         return ((HtmlTextNode) _currentnode).Text;\r
386 \r
387                     case HtmlNodeType.Element:\r
388                         {\r
389                             if (_attindex != -1)\r
390                             {\r
391                                 InternalTrace(">" + _currentnode.Attributes[_attindex].Value);\r
392                                 return _currentnode.Attributes[_attindex].Value;\r
393                             }\r
394                             return _currentnode.InnerText;\r
395                         }\r
396 \r
397                     default:\r
398                         throw new NotImplementedException("Internal error: Unhandled HtmlNodeType: " +\r
399                                                           _currentnode.NodeType);\r
400                 }\r
401             }\r
402         }\r
403 \r
404         /// <summary>\r
405         /// Gets the xml:lang scope for the current node.\r
406         /// Always returns string.Empty in the case of HtmlNavigator implementation.\r
407         /// </summary>\r
408         public override string XmlLang\r
409         {\r
410             get\r
411             {\r
412                 InternalTrace(null);\r
413                 return _nametable.GetOrAdd(string.Empty);\r
414             }\r
415         }\r
416 \r
417         #endregion\r
418 \r
419         #region Public Methods\r
420 \r
421         /// <summary>\r
422         /// Creates a new HtmlNavigator positioned at the same node as this HtmlNavigator.\r
423         /// </summary>\r
424         /// <returns>A new HtmlNavigator object positioned at the same node as the original HtmlNavigator.</returns>\r
425         public override XPathNavigator Clone()\r
426         {\r
427             InternalTrace(null);\r
428             return new HtmlNodeNavigator(this);\r
429         }\r
430 \r
431         /// <summary>\r
432         /// Gets the value of the HTML attribute with the specified LocalName and NamespaceURI.\r
433         /// </summary>\r
434         /// <param name="localName">The local name of the HTML attribute.</param>\r
435         /// <param name="namespaceURI">The namespace URI of the attribute. Unsupported with the HtmlNavigator implementation.</param>\r
436         /// <returns>The value of the specified HTML attribute. String.Empty or null if a matching attribute is not found or if the navigator is not positioned on an element node.</returns>\r
437         public override string GetAttribute(string localName, string namespaceURI)\r
438         {\r
439             InternalTrace("localName=" + localName + ", namespaceURI=" + namespaceURI);\r
440             HtmlAttribute att = _currentnode.Attributes[localName];\r
441             if (att == null)\r
442             {\r
443                 InternalTrace(">null");\r
444                 return null;\r
445             }\r
446             InternalTrace(">" + att.Value);\r
447             return att.Value;\r
448         }\r
449 \r
450         /// <summary>\r
451         /// Returns the value of the namespace node corresponding to the specified local name.\r
452         /// Always returns string.Empty for the HtmlNavigator implementation.\r
453         /// </summary>\r
454         /// <param name="name">The local name of the namespace node.</param>\r
455         /// <returns>Always returns string.Empty for the HtmlNavigator implementation.</returns>\r
456         public override string GetNamespace(string name)\r
457         {\r
458             InternalTrace("name=" + name);\r
459             return string.Empty;\r
460         }\r
461 \r
462         /// <summary>\r
463         /// Determines whether the current HtmlNavigator is at the same position as the specified HtmlNavigator.\r
464         /// </summary>\r
465         /// <param name="other">The HtmlNavigator that you want to compare against.</param>\r
466         /// <returns>true if the two navigators have the same position, otherwise, false.</returns>\r
467         public override bool IsSamePosition(XPathNavigator other)\r
468         {\r
469             HtmlNodeNavigator nav = other as HtmlNodeNavigator;\r
470             if (nav == null)\r
471             {\r
472                 InternalTrace(">false");\r
473                 return false;\r
474             }\r
475             InternalTrace(">" + (nav._currentnode == _currentnode));\r
476             return (nav._currentnode == _currentnode);\r
477         }\r
478 \r
479         /// <summary>\r
480         /// Moves to the same position as the specified HtmlNavigator.\r
481         /// </summary>\r
482         /// <param name="other">The HtmlNavigator positioned on the node that you want to move to.</param>\r
483         /// <returns>true if successful, otherwise false. If false, the position of the navigator is unchanged.</returns>\r
484         public override bool MoveTo(XPathNavigator other)\r
485         {\r
486             HtmlNodeNavigator nav = other as HtmlNodeNavigator;\r
487             if (nav == null)\r
488             {\r
489                 InternalTrace(">false (nav is not an HtmlNodeNavigator)");\r
490                 return false;\r
491             }\r
492             InternalTrace("moveto oid=" + nav.GetHashCode()\r
493                           + ", n:" + nav._currentnode.Name\r
494                           + ", a:" + nav._attindex);\r
495 \r
496             if (nav._doc == _doc)\r
497             {\r
498                 _currentnode = nav._currentnode;\r
499                 _attindex = nav._attindex;\r
500                 InternalTrace(">true");\r
501                 return true;\r
502             }\r
503             // we don't know how to handle that\r
504             InternalTrace(">false (???)");\r
505             return false;\r
506         }\r
507 \r
508         /// <summary>\r
509         /// Moves to the HTML attribute with matching LocalName and NamespaceURI.\r
510         /// </summary>\r
511         /// <param name="localName">The local name of the HTML attribute.</param>\r
512         /// <param name="namespaceURI">The namespace URI of the attribute. Unsupported with the HtmlNavigator implementation.</param>\r
513         /// <returns>true if the HTML attribute is found, otherwise, false. If false, the position of the navigator does not change.</returns>\r
514         public override bool MoveToAttribute(string localName, string namespaceURI)\r
515         {\r
516             InternalTrace("localName=" + localName + ", namespaceURI=" + namespaceURI);\r
517             int index = _currentnode.Attributes.GetAttributeIndex(localName);\r
518             if (index == -1)\r
519             {\r
520                 InternalTrace(">false");\r
521                 return false;\r
522             }\r
523             _attindex = index;\r
524             InternalTrace(">true");\r
525             return true;\r
526         }\r
527 \r
528         /// <summary>\r
529         /// Moves to the first sibling of the current node.\r
530         /// </summary>\r
531         /// <returns>true if the navigator is successful moving to the first sibling node, false if there is no first sibling or if the navigator is currently positioned on an attribute node.</returns>\r
532         public override bool MoveToFirst()\r
533         {\r
534             if (_currentnode.ParentNode == null)\r
535             {\r
536                 InternalTrace(">false");\r
537                 return false;\r
538             }\r
539             if (_currentnode.ParentNode.FirstChild == null)\r
540             {\r
541                 InternalTrace(">false");\r
542                 return false;\r
543             }\r
544             _currentnode = _currentnode.ParentNode.FirstChild;\r
545             InternalTrace(">true");\r
546             return true;\r
547         }\r
548 \r
549         /// <summary>\r
550         /// Moves to the first HTML attribute.\r
551         /// </summary>\r
552         /// <returns>true if the navigator is successful moving to the first HTML attribute, otherwise, false.</returns>\r
553         public override bool MoveToFirstAttribute()\r
554         {\r
555             if (!HasAttributes)\r
556             {\r
557                 InternalTrace(">false");\r
558                 return false;\r
559             }\r
560             _attindex = 0;\r
561             InternalTrace(">true");\r
562             return true;\r
563         }\r
564 \r
565         /// <summary>\r
566         /// Moves to the first child of the current node.\r
567         /// </summary>\r
568         /// <returns>true if there is a first child node, otherwise false.</returns>\r
569         public override bool MoveToFirstChild()\r
570         {\r
571             if (!_currentnode.HasChildNodes)\r
572             {\r
573                 InternalTrace(">false");\r
574                 return false;\r
575             }\r
576             _currentnode = _currentnode.ChildNodes[0];\r
577             InternalTrace(">true");\r
578             return true;\r
579         }\r
580 \r
581         /// <summary>\r
582         /// Moves the XPathNavigator to the first namespace node of the current element.\r
583         /// Always returns false for the HtmlNavigator implementation.\r
584         /// </summary>\r
585         /// <param name="scope">An XPathNamespaceScope value describing the namespace scope.</param>\r
586         /// <returns>Always returns false for the HtmlNavigator implementation.</returns>\r
587         public override bool MoveToFirstNamespace(XPathNamespaceScope scope)\r
588         {\r
589             InternalTrace(null);\r
590             return false;\r
591         }\r
592 \r
593         /// <summary>\r
594         /// Moves to the node that has an attribute of type ID whose value matches the specified string.\r
595         /// </summary>\r
596         /// <param name="id">A string representing the ID value of the node to which you want to move. This argument does not need to be atomized.</param>\r
597         /// <returns>true if the move was successful, otherwise false. If false, the position of the navigator is unchanged.</returns>\r
598         public override bool MoveToId(string id)\r
599         {\r
600             InternalTrace("id=" + id);\r
601             HtmlNode node = _doc.GetElementbyId(id);\r
602             if (node == null)\r
603             {\r
604                 InternalTrace(">false");\r
605                 return false;\r
606             }\r
607             _currentnode = node;\r
608             InternalTrace(">true");\r
609             return true;\r
610         }\r
611 \r
612         /// <summary>\r
613         /// Moves the XPathNavigator to the namespace node with the specified local name. \r
614         /// Always returns false for the HtmlNavigator implementation.\r
615         /// </summary>\r
616         /// <param name="name">The local name of the namespace node.</param>\r
617         /// <returns>Always returns false for the HtmlNavigator implementation.</returns>\r
618         public override bool MoveToNamespace(string name)\r
619         {\r
620             InternalTrace("name=" + name);\r
621             return false;\r
622         }\r
623 \r
624         /// <summary>\r
625         /// Moves to the next sibling of the current node.\r
626         /// </summary>\r
627         /// <returns>true if the navigator is successful moving to the next sibling node, false if there are no more siblings or if the navigator is currently positioned on an attribute node. If false, the position of the navigator is unchanged.</returns>\r
628         public override bool MoveToNext()\r
629         {\r
630             if (_currentnode.NextSibling == null)\r
631             {\r
632                 InternalTrace(">false");\r
633                 return false;\r
634             }\r
635             InternalTrace("_c=" + _currentnode.CloneNode(false).OuterHtml);\r
636             InternalTrace("_n=" + _currentnode.NextSibling.CloneNode(false).OuterHtml);\r
637             _currentnode = _currentnode.NextSibling;\r
638             InternalTrace(">true");\r
639             return true;\r
640         }\r
641 \r
642         /// <summary>\r
643         /// Moves to the next HTML attribute.\r
644         /// </summary>\r
645         /// <returns></returns>\r
646         public override bool MoveToNextAttribute()\r
647         {\r
648             InternalTrace(null);\r
649             if (_attindex >= (_currentnode.Attributes.Count - 1))\r
650             {\r
651                 InternalTrace(">false");\r
652                 return false;\r
653             }\r
654             _attindex++;\r
655             InternalTrace(">true");\r
656             return true;\r
657         }\r
658 \r
659         /// <summary>\r
660         /// Moves the XPathNavigator to the next namespace node.\r
661         /// Always returns falsefor the HtmlNavigator implementation.\r
662         /// </summary>\r
663         /// <param name="scope">An XPathNamespaceScope value describing the namespace scope.</param>\r
664         /// <returns>Always returns false for the HtmlNavigator implementation.</returns>\r
665         public override bool MoveToNextNamespace(XPathNamespaceScope scope)\r
666         {\r
667             InternalTrace(null);\r
668             return false;\r
669         }\r
670 \r
671         /// <summary>\r
672         /// Moves to the parent of the current node.\r
673         /// </summary>\r
674         /// <returns>true if there is a parent node, otherwise false.</returns>\r
675         public override bool MoveToParent()\r
676         {\r
677             if (_currentnode.ParentNode == null)\r
678             {\r
679                 InternalTrace(">false");\r
680                 return false;\r
681             }\r
682             _currentnode = _currentnode.ParentNode;\r
683             InternalTrace(">true");\r
684             return true;\r
685         }\r
686 \r
687         /// <summary>\r
688         /// Moves to the previous sibling of the current node.\r
689         /// </summary>\r
690         /// <returns>true if the navigator is successful moving to the previous sibling node, false if there is no previous sibling or if the navigator is currently positioned on an attribute node.</returns>\r
691         public override bool MoveToPrevious()\r
692         {\r
693             if (_currentnode.PreviousSibling == null)\r
694             {\r
695                 InternalTrace(">false");\r
696                 return false;\r
697             }\r
698             _currentnode = _currentnode.PreviousSibling;\r
699             InternalTrace(">true");\r
700             return true;\r
701         }\r
702 \r
703         /// <summary>\r
704         /// Moves to the root node to which the current node belongs.\r
705         /// </summary>\r
706         public override void MoveToRoot()\r
707         {\r
708             _currentnode = _doc.DocumentNode;\r
709             InternalTrace(null);\r
710         }\r
711 \r
712         #endregion\r
713 \r
714         #region Internal Methods\r
715 \r
716         [Conditional("TRACE")]\r
717         internal void InternalTrace(object traceValue)\r
718         {\r
719             if (!Trace)\r
720             {\r
721                 return;\r
722             }\r
723             StackFrame sf = new StackFrame(1, true);\r
724             string name = sf.GetMethod().Name;\r
725             string nodename = _currentnode == null ? "(null)" : _currentnode.Name;\r
726             string nodevalue;\r
727             if (_currentnode == null)\r
728             {\r
729                 nodevalue = "(null)";\r
730             }\r
731             else\r
732             {\r
733                 switch (_currentnode.NodeType)\r
734                 {\r
735                     case HtmlNodeType.Comment:\r
736                         nodevalue = ((HtmlCommentNode) _currentnode).Comment;\r
737                         break;\r
738 \r
739                     case HtmlNodeType.Document:\r
740                         nodevalue = "";\r
741                         break;\r
742 \r
743                     case HtmlNodeType.Text:\r
744                         nodevalue = ((HtmlTextNode) _currentnode).Text;\r
745                         break;\r
746 \r
747                     default:\r
748                         nodevalue = _currentnode.CloneNode(false).OuterHtml;\r
749                         break;\r
750                 }\r
751             }\r
752             System.Diagnostics.Trace.WriteLine(string.Format("oid={0},n={1},a={2},v={3},{4}", GetHashCode(), nodename, _attindex, nodevalue, traceValue), "N!" + name);\r
753         }\r
754 \r
755         #endregion\r
756 \r
757         #region Private Methods\r
758 \r
759         private void Reset()\r
760         {\r
761             InternalTrace(null);\r
762             _currentnode = _doc.DocumentNode;\r
763             _attindex = -1;\r
764         }\r
765 \r
766         #endregion\r
767     }\r
768 }