1 // HtmlAgilityPack V1.0 - Simon Mourier <simon underscore mourier at hotmail dot com>
3 using System
.Collections
;
4 using System
.Collections
.Generic
;
6 namespace HtmlAgilityPack
9 /// Represents a combined list and collection of HTML nodes.
11 public class HtmlNodeCollection
: IList
<HtmlNode
>
15 private readonly HtmlNode _parentnode
;
16 private readonly List
<HtmlNode
> _items
= new List
<HtmlNode
>();
23 /// Initialize the HtmlNodeCollection with the base parent node
25 /// <param name="parentnode">The base node of the collection</param>
26 public HtmlNodeCollection(HtmlNode parentnode
)
28 _parentnode
= parentnode
; // may be null
36 /// Gets a given node from the list.
38 public int this[HtmlNode node
]
42 int index
= GetNodeIndex(node
);
45 throw new ArgumentOutOfRangeException("node",
46 "Node \"" + node
.CloneNode(false).OuterHtml
+
47 "\" was not found in the collection");
54 /// Get node with tag name
56 /// <param name="nodeName"></param>
57 /// <returns></returns>
58 public HtmlNode
this[string nodeName
]
62 nodeName
= nodeName
.ToLower();
63 for (int i
= 0; i
< _items
.Count
; i
++)
64 if (_items
[i
].Equals(nodeName
))
73 #region IList<HtmlNode> Members
76 /// Gets the number of elements actually contained in the list.
80 get { return _items.Count; }
84 /// Is collection read only
86 public bool IsReadOnly
92 /// Gets the node at the specified index.
94 public HtmlNode
this[int index
]
96 get { return _items[index]; }
97 set { _items[index] = value; }
101 /// Add node to the collection
103 /// <param name="node"></param>
104 public void Add(HtmlNode node
)
110 /// Clears out the collection of HtmlNodes. Removes each nodes reference to parentnode, nextnode and prevnode
114 foreach (HtmlNode node
in _items
)
116 node
.ParentNode
= null;
117 node
.NextSibling
= null;
118 node
.PreviousSibling
= null;
124 /// Gets existence of node in collection
126 /// <param name="item"></param>
127 /// <returns></returns>
128 public bool Contains(HtmlNode item
)
130 return _items
.Contains(item
);
134 /// Copy collection to array
136 /// <param name="array"></param>
137 /// <param name="arrayIndex"></param>
138 public void CopyTo(HtmlNode
[] array
, int arrayIndex
)
140 _items
.CopyTo(array
, arrayIndex
);
146 /// <returns></returns>
147 IEnumerator
<HtmlNode
> IEnumerable
<HtmlNode
>.GetEnumerator()
149 return _items
.GetEnumerator();
153 /// Get Explicit Enumerator
155 /// <returns></returns>
156 IEnumerator IEnumerable
.GetEnumerator()
158 return _items
.GetEnumerator();
162 /// Get index of node
164 /// <param name="item"></param>
165 /// <returns></returns>
166 public int IndexOf(HtmlNode item
)
168 return _items
.IndexOf(item
);
172 /// Insert node at index
174 /// <param name="index"></param>
175 /// <param name="node"></param>
176 public void Insert(int index
, HtmlNode node
)
178 HtmlNode next
= null;
179 HtmlNode prev
= null;
183 prev
= _items
[index
- 1];
186 if (index
< _items
.Count
)
188 next
= _items
[index
];
191 _items
.Insert(index
, node
);
197 throw new InvalidProgramException("Unexpected error.");
199 prev
._nextnode
= node
;
204 next
._prevnode
= node
;
207 node
._prevnode
= prev
;
210 throw new InvalidProgramException("Unexpected error.");
212 node
._nextnode
= next
;
213 node
._parentnode
= _parentnode
;
219 /// <param name="item"></param>
220 /// <returns></returns>
221 public bool Remove(HtmlNode item
)
223 int i
= _items
.IndexOf(item
);
229 /// Remove <see cref="HtmlNode"/> at index
231 /// <param name="index"></param>
232 public void RemoveAt(int index
)
234 HtmlNode next
= null;
235 HtmlNode prev
= null;
236 HtmlNode oldnode
= _items
[index
];
240 prev
= _items
[index
- 1];
243 if (index
< (_items
.Count
- 1))
245 next
= _items
[index
+ 1];
248 _items
.RemoveAt(index
);
254 throw new InvalidProgramException("Unexpected error.");
256 prev
._nextnode
= next
;
261 next
._prevnode
= prev
;
264 oldnode
._prevnode
= null;
265 oldnode
._nextnode
= null;
266 oldnode
._parentnode
= null;
271 #region Public Methods
274 /// Get first instance of node in supplied collection
276 /// <param name="items"></param>
277 /// <param name="name"></param>
278 /// <returns></returns>
279 public static HtmlNode
FindFirst(HtmlNodeCollection items
, string name
)
281 foreach (HtmlNode node
in items
)
283 if (node
.Name
.ToLower().Contains(name
))
285 if (node
.HasChildNodes
)
287 HtmlNode returnNode
= FindFirst(node
.ChildNodes
, name
);
288 if (returnNode
!= null)
296 /// Add node to the end of the collection
298 /// <param name="node"></param>
299 public void Append(HtmlNode node
)
301 HtmlNode last
= null;
302 if (_items
.Count
> 0)
304 last
= _items
[_items
.Count
- 1];
308 node
._prevnode
= last
;
309 node
._nextnode
= null;
310 node
._parentnode
= _parentnode
;
315 throw new InvalidProgramException("Unexpected error.");
317 last
._nextnode
= node
;
322 /// Get first instance of node with name
324 /// <param name="name"></param>
325 /// <returns></returns>
326 public HtmlNode
FindFirst(string name
)
328 return FindFirst(this, name
);
332 /// Get index of node
334 /// <param name="node"></param>
335 /// <returns></returns>
336 public int GetNodeIndex(HtmlNode node
)
338 // TODO: should we rewrite this? what would be the key of a node?
339 for (int i
= 0; i
< _items
.Count
; i
++)
341 if (node
== (_items
[i
]))
350 /// Add node to the beginning of the collection
352 /// <param name="node"></param>
353 public void Prepend(HtmlNode node
)
355 HtmlNode first
= null;
356 if (_items
.Count
> 0)
361 _items
.Insert(0, node
);
365 throw new InvalidProgramException("Unexpected error.");
367 node
._nextnode
= first
;
368 node
._prevnode
= null;
369 node
._parentnode
= _parentnode
;
372 first
._prevnode
= node
;
377 /// Remove node at index
379 /// <param name="index"></param>
380 /// <returns></returns>
381 public bool Remove(int index
)
388 /// Replace node at index
390 /// <param name="index"></param>
391 /// <param name="node"></param>
392 public void Replace(int index
, HtmlNode node
)
394 HtmlNode next
= null;
395 HtmlNode prev
= null;
396 HtmlNode oldnode
= _items
[index
];
400 prev
= _items
[index
- 1];
403 if (index
< (_items
.Count
- 1))
405 next
= _items
[index
+ 1];
408 _items
[index
] = node
;
414 throw new InvalidProgramException("Unexpected error.");
416 prev
._nextnode
= node
;
421 next
._prevnode
= node
;
424 node
._prevnode
= prev
;
428 throw new InvalidProgramException("Unexpected error.");
431 node
._nextnode
= next
;
432 node
._parentnode
= _parentnode
;
434 oldnode
._prevnode
= null;
435 oldnode
._nextnode
= null;
436 oldnode
._parentnode
= null;
444 /// Get all node descended from this collection
446 /// <returns></returns>
447 public IEnumerable
<HtmlNode
> DescendantNodes()
449 foreach (HtmlNode item
in _items
)
450 foreach (HtmlNode n
in item
.DescendantNodes())
455 /// Get all node descended from this collection
457 /// <returns></returns>
458 public IEnumerable
<HtmlNode
> Descendants()
460 foreach (HtmlNode item
in _items
)
461 foreach (HtmlNode n
in item
.Descendants())
466 /// Get all node descended from this collection with matching name
468 /// <returns></returns>
469 public IEnumerable
<HtmlNode
> Descendants(string name
)
471 foreach (HtmlNode item
in _items
)
472 foreach (HtmlNode n
in item
.Descendants(name
))
477 /// Gets all first generation elements in collection
479 /// <returns></returns>
480 public IEnumerable
<HtmlNode
> Elements()
482 foreach (HtmlNode item
in _items
)
483 foreach (HtmlNode n
in item
.ChildNodes
)
488 /// Gets all first generation elements matching name
490 /// <param name="name"></param>
491 /// <returns></returns>
492 public IEnumerable
<HtmlNode
> Elements(string name
)
494 foreach (HtmlNode item
in _items
)
495 foreach (HtmlNode n
in item
.Elements(name
))
500 /// All first generation nodes in collection
502 /// <returns></returns>
503 public IEnumerable
<HtmlNode
> Nodes()
505 foreach (HtmlNode item
in _items
)
506 foreach (HtmlNode n
in item
.ChildNodes
)