1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright (c) 2003-2012 by AG-Software 											 *
3  * All Rights Reserved.																 *
4  * Contact information for AG-Software is available at http://www.ag-software.de	 *
5  *																					 *
6  * Licence:																			 *
7  * The agsXMPP SDK is released under a dual licence									 *
8  * agsXMPP can be used under either of two licences									 *
9  * 																					 *
10  * A commercial licence which is probably the most appropriate for commercial 		 *
11  * corporate use and closed source projects. 										 *
12  *																					 *
13  * The GNU Public License (GPL) is probably most appropriate for inclusion in		 *
14  * other open source projects.														 *
15  *																					 *
16  * See README.html for details.														 *
17  *																					 *
18  * For general enquiries visit our website at:										 *
19  * http://www.ag-software.de														 *
20  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21 
22 using System;
23 using System.Collections.Generic;
24 using System.Collections.Specialized;
25 using System.Globalization;
26 using System.Text;
27 using System.IO;
28 using System.Xml;
29 
30 namespace agsXMPP.Xml.Dom
31 {
32 
33 	public class Element : Node
34 	{
35 		// Member Variables
36 		private		string			m_TagName;
37 		private		string			m_Prefix;
38         private     ListDictionary  m_Attributes;
39 		private		Text			m_Value				= new Text();
40 
Element()41 		public Element()
42 		{
43 			NodeType = NodeType.Element;
44 			AddChild(m_Value);
45 
46             m_Attributes = new ListDictionary();
47 
48             m_TagName	= "";
49 			Value		= "";
50 		}
51 
Element(string tagName)52 		public Element(string tagName) :this()
53 		{
54             m_TagName = tagName;
55 		}
56 
Element(string tagName, string tagText)57 		public Element(string tagName, string tagText) : this(tagName)
58 		{
59             Value		= tagText;
60 		}
61 
Element(string tagName, bool tagText)62         public Element(string tagName, bool tagText) : this(tagName, tagText ? "true" : "false")
63 		{
64 		}
65 
Element(string tagName, string tagText, string ns)66 		public Element(string tagName, string tagText, string ns) : this(tagName, tagText)
67 		{
68            Namespace		= ns;
69 		}
70 
71 		/// <summary>
72 		/// Is this Element a Rootnode?
73 		/// </summary>
74 		public bool IsRootElement
75 		{
76 			get
77 			{
78 				return (Parent != null ? false : true);
79 			}
80 		}
81 
82 		public override string Value
83 		{
84 			get	{ return m_Value.Value;	}
85 			set	{ m_Value.Value = value; }
86 		}
87 
88 		public string Prefix
89 		{
90 			get { return m_Prefix; }
91 			set { m_Prefix = value; }
92 		}
93 
94 		/// <summary>
95 		/// The Full Qualified Name
96 		/// </summary>
97 		public string TagName
98 		{
99 			get	{ return m_TagName;	}
100 			set { m_TagName = value; }
101 		}
102 
103 		public string TextBase64
104 		{
105 			get
106 			{
107 				byte[] b = Convert.FromBase64String(Value);
108 				return Encoding.ASCII.GetString(b, 0, b.Length);
109 			}
110 			set
111 			{
112                 byte[] b = Encoding.UTF8.GetBytes(value);
113 				//byte[] b = Encoding.Default.GetBytes(value);
114 				Value = Convert.ToBase64String(b, 0, b.Length);
115 			}
116 		}
117 
118         public ListDictionary Attributes
119         {
120             get { return m_Attributes; }
121         }
122 
GetAttributeEnum(string name, Type enumType)123 		public object GetAttributeEnum(string name, Type enumType)
124 		{
125 			string att = GetAttribute(name);
126 			if ((att == null))
127 				return -1;
128 			try
129 			{
130 #if CF
131 				return util.Enum.Parse(enumType, att, true);
132 #else
133 				return Enum.Parse(enumType, att, true);
134 #endif
135 			}
136 			catch (Exception)
137 			{
138 				return -1;
139 			}
140 		}
141 
GetAttribute(string name)142 		public string GetAttribute(string name)
143 		{
144 		    if (HasAttribute(name))
145 				return (string) m_Attributes[name];
146 		    return null;
147 		}
148 
GetAttributeInt(string name)149 	    public int GetAttributeInt(string name)
150 	    {
151 	        if (HasAttribute(name))
152 			{
153 				return int.Parse((string) m_Attributes[name]);
154 			}
155 	        return 0;
156 	    }
157 
GetAttributeLong(string name)158 	    public long GetAttributeLong(string name)
159 	    {
160 	        if (HasAttribute(name))
161 			{
162 				return long.Parse((string) m_Attributes[name]);
163 			}
164 	        return 0;
165 	    }
166 
167 	    /// <summary>
168         /// Reads a boolean Attribute, if the attrib is absent it returns also false.
169         /// </summary>
170         /// <param name="name"></param>
171         /// <returns></returns>
GetAttributeBool(string name)172         public bool GetAttributeBool(string name)
173 	    {
174 	        if (HasAttribute(name))
175             {
176                 string tmp = (string) m_Attributes[name];
177                 if (tmp.ToLower() == "true")
178                     return true;
179                 return false;
180             }
181 	        return false;
182 	    }
183 
GetAttributeJid(string name)184 	    public Jid GetAttributeJid(string name)
185 	    {
186 	        if (HasAttribute(name))
187                 return new Jid(this.GetAttribute(name));
188 	        return null;
189 	    }
190 
191 	    /// <summary>
192         ///
193         /// </summary>
194         /// <param name="name"></param>
195         /// <param name="ifp"></param>
196         /// <returns></returns>
GetAttributeDouble(string name, IFormatProvider ifp)197         public double GetAttributeDouble(string name, IFormatProvider ifp)
198 	    {
199 	        if (HasAttribute(name))
200             {
201                 try
202                 {
203                     return double.Parse((string)m_Attributes[name], ifp);
204                 }
205                 catch
206                 {
207                     return double.NaN;
208                 }
209             }
210 	        return double.NaN;
211 	    }
212 
213 	    /// <summary>
214         /// Get a Attribute of type double (Decimal seperator = ".")
215         /// </summary>
216         /// <param name="name"></param>
217         /// <returns></returns>
GetAttributeDouble(string name)218         public double GetAttributeDouble(string name)
219         {
220             // Parse the double always in english format ==> "." = Decimal seperator
221             NumberFormatInfo nfi = new NumberFormatInfo();
222             nfi.NumberGroupSeparator = ".";
223             return GetAttributeDouble(name, nfi);
224         }
225 
HasAttribute(string name)226 		public bool HasAttribute(string name)
227 		{
228 			return Attributes.Contains(name);
229 		}
230 
231 		/// <summary>
232 		/// Return the Text of the first Tag with a specified Name.
233 		/// It doesnt traverse the while tree and checks only the unerlying childnodes
234 		/// </summary>
235 		/// <param name="TagName">Name of Tag to find as string</param>
236 		/// <returns></returns>
GetTag(string TagName)237 		public string GetTag(string TagName)
238 		{
239 			Element tag = this._SelectElement(this, TagName);
240 			if ( tag != null)
241 				return tag.Value;
242 		    return null;
243 		}
244 
GetTag(string TagName, bool traverseChildren)245 		public string GetTag(string TagName, bool traverseChildren)
246 		{
247 			Element tag = this._SelectElement(this, TagName, traverseChildren);
248 			if ( tag != null)
249 				return tag.Value;
250 		    return null;
251 		}
252 
GetTag(System.Type type)253 		public string GetTag(System.Type type)
254 		{
255 			Element tag = this._SelectElement(this, type);
256 			if ( tag != null)
257 				return tag.Value;
258 		    return null;
259 		}
260 
GetTagBase64(string TagName)261 		public string GetTagBase64(string TagName)
262 		{
263 			byte[] b = Convert.FromBase64String(GetTag(TagName));
264 			return Encoding.ASCII.GetString(b, 0, b.Length);
265 		}
266 
267 		/// <summary>
268 		/// Adds a Tag and encodes the Data to BASE64
269 		/// </summary>
270 		/// <param name="argTagname"></param>
271 		/// <param name="argText"></param>
SetTagBase64(string argTagname, string argText)272 		public void SetTagBase64(string argTagname, string argText)
273 		{
274 			byte[] b = Encoding.Unicode.GetBytes(argText);
275 			SetTag(argTagname, Convert.ToBase64String(b, 0, b.Length));
276 		}
277 
278 		/// <summary>
279 		/// Adds a Tag end decodes the byte buffer to BASE64
280 		/// </summary>
281 		/// <param name="argTagname"></param>
282 		/// <param name="buffer"></param>
SetTagBase64(string argTagname, byte[] buffer)283 		public void SetTagBase64(string argTagname, byte[] buffer)
284 		{
285 			SetTag(argTagname, Convert.ToBase64String(buffer, 0, buffer.Length));
286 		}
287 
SetTag(string argTagname, string argText)288 		public void SetTag(string argTagname, string argText)
289 		{
290 			if (HasTag(argTagname) == false)
291 				AddChild(new Element(argTagname, argText));
292 			else
293 				SelectSingleElement(argTagname).Value = argText;
294 		}
295 
SetTag(Type type, string argText)296 		public void SetTag(Type type, string argText)
297 		{
298 			if (HasTag(type) == false)
299 			{
300 				Element newel;
301 				newel		= (Element) Activator.CreateInstance(type);
302 				newel.Value = argText;
303 				AddChild(newel);
304 			}
305 			else
306 				SelectSingleElement(type).Value = argText;
307 		}
308 
SetTag(Type type)309 		public void SetTag(Type type)
310 		{
311 			if (HasTag(type))
312 				RemoveTag(type);
313 
314 			AddChild( (Element) Activator.CreateInstance(type) );
315 		}
316 
SetTag(string argTagname)317 		public void SetTag(string argTagname)
318 		{
319 			SetTag(argTagname, "");
320 		}
321 
SetTag(string argTagname, string argText, string argNS)322 		public void SetTag(string argTagname, string argText, string argNS)
323 		{
324 			if (HasTag(argTagname) == false)
325 				AddChild(new Element(argTagname, argText, argNS));
326 			else
327 			{
328 				Element e = SelectSingleElement(argTagname);
329 				e.Value		= argText;
330 				e.Namespace = argNS;
331 			}
332 		}
333 
SetTag(string argTagname, double dbl, IFormatProvider ifp)334         public void SetTag(string argTagname, double dbl, IFormatProvider ifp)
335         {
336             SetTag(argTagname, dbl.ToString(ifp));
337         }
338 
SetTag(string argTagname, double dbl)339         public void SetTag(string argTagname, double dbl)
340         {
341             NumberFormatInfo nfi = new NumberFormatInfo();
342             nfi.NumberGroupSeparator = ".";
343             SetTag(argTagname, dbl, nfi);
344         }
345 
SetTag(string argTagname, bool val)346         public void SetTag(string argTagname, bool val)
347         {
348             SetTag(argTagname, val ? "true" : "false");
349         }
350 
SetTag(string argTagname, int val)351         public void SetTag(string argTagname, int val)
352         {
353             SetTag(argTagname, val.ToString());
354         }
355 
SetTag(string argTagname, Jid jid)356         public void SetTag(string argTagname, Jid jid)
357         {
358             SetTag(argTagname, jid.ToString());
359         }
360 
AddTag(string argTagname, string argText)361 		public void AddTag(string argTagname, string argText)
362 		{
363 			AddChild(new Element(argTagname, argText));
364 		}
365 
AddTag(string argTagname)366 		public void AddTag(string argTagname)
367 		{
368 			AddChild(new Element(argTagname));
369 		}
370 
GetTagEnum(string name, System.Type enumType)371 		public object GetTagEnum(string name, System.Type enumType)
372 		{
373 			string tag = this.GetTag(name);
374 			if ( (tag == null) || (tag.Length == 0) )
375 				return -1;
376 			try
377 			{
378 #if CF
379 				return util.Enum.Parse(enumType, tag, true);
380 #else
381 				return Enum.Parse(enumType, tag, true);
382 #endif
383 			}
384 			catch (Exception)
385 			{
386 				return -1;
387 			}
388 		}
389 
390 		/// <summary>
391 		/// Return the Text of the first Tag with a specified Name in all childnodes as boolean
392 		/// </summary>
393 		/// <param name="TagName">name of Tag to findas string</param>
394 		/// <returns></returns>
GetTagBool(string TagName)395 		public bool GetTagBool(string TagName)
396 		{
397 			Element tag = this._SelectElement(this, TagName);
398 			if ( tag != null)
399 			{
400 			    if (tag.Value.ToLower() == "false" || tag.Value.ToLower() == "0")
401 				{
402 					return false;
403 				}
404 			    if(tag.Value.ToLower() == "true" ||	tag.Value.ToLower() == "1")
405 			    {
406 			        return true;
407 			    }
408 			    return false;
409 			}
410 		    return false;
411 		}
412 
GetTagInt(string TagName)413 		public int GetTagInt(string TagName)
414 		{
415 			Element tag = _SelectElement(this, TagName);
416 			if ( tag != null)
417 				return int.Parse(tag.Value);
418 		    return 0;
419 		}
420 
421 
GetTagJid(string TagName)422         public Jid GetTagJid(string TagName)
423         {
424             string jid = GetTag(TagName);
425 
426             if (jid != null)
427                 return new Jid(jid);
428             return null;
429         }
430 
431 
432         /// <summary>
433         /// Get a Tag of type double (Decimal seperator = ".")
434         /// </summary>
435         /// <param name="TagName"></param>
436         /// <returns></returns>
GetTagDouble(string argTagName)437         public double GetTagDouble(string argTagName)
438         {
439             // Parse the double always in english format ==> "." = Decimal seperator
440             NumberFormatInfo nfi = new NumberFormatInfo();
441             nfi.NumberGroupSeparator = ".";
442 
443             return GetTagDouble(argTagName, nfi);
444         }
445 
446         /// <summary>
447         /// Get a Tag of type double with the given iFormatProvider
448         /// </summary>
449         /// <param name="TagName"></param>
450         /// <param name="nfi"></param>
451         /// <returns></returns>
GetTagDouble(string argTagName, IFormatProvider ifp)452         public double GetTagDouble(string argTagName, IFormatProvider ifp)
453         {
454             string val = GetTag(argTagName);
455             if (val != null)
456                 return Double.Parse(val, ifp);
457             return Double.NaN;
458         }
459 
HasTag(string name)460 		public bool HasTag(string name)
461 		{
462 			Element tag = _SelectElement(this, name);
463 			if ( tag != null)
464 				return true;
465 		    return false;
466 		}
467 
HasTag(string name, bool traverseChildren)468 		public bool HasTag(string name, bool traverseChildren)
469 		{
470 			Element tag = _SelectElement(this, name, traverseChildren);
471 			if ( tag != null)
472 				return true;
473 		    return false;
474 		}
475 
HasTag(Type type)476 		public bool HasTag(Type type)
477 		{
478 			Element tag = _SelectElement(this, type);
479 			if ( tag != null)
480 				return true;
481 		    return false;
482 		}
483 
484         public bool HasTag<T>() where T : Element
485         {
486             return SelectSingleElement<T>() != null;
487         }
488 
489         public bool HasTagt<T>(bool traverseChildren) where T : Element
490         {
491             return SelectSingleElement<T>(traverseChildren) != null;
492         }
493 
494 
HasTag(Type type, bool traverseChildren)495 		public bool HasTag(Type type, bool traverseChildren)
496 		{
497 			Element tag = this._SelectElement(this, type, traverseChildren);
498 			if ( tag != null)
499 				return true;
500 		    return false;
501 		}
502 
503 		/// <summary>
504 		///
505 		/// </summary>
506 		/// <param name="enumType"></param>
507 		/// <returns></returns>
HasTagEnum(Type enumType)508         public object HasTagEnum(Type enumType)
509 		{
510 #if CF || CF_2
511 			string[] members = Util.Enum.GetNames(enumType);
512 #else
513 			string[] members = Enum.GetNames(enumType);
514 #endif
515 			foreach (string member in members)
516 			{
517 				if (HasTag(member))
518 #if CF
519 					return util.Enum.Parse(enumType, member, false);
520 #else
521 					return Enum.Parse(enumType, member, false);
522 #endif
523 			}
524 			return -1;
525 		}
526 
527 		/// <summary>
528 		/// Remove a Tag when it exists
529 		/// </summary>
530 		/// <param name="TagName">Tagname to remove</param>
531 		/// <returns>true when existing and removed, false when not existing</returns>
RemoveTag(string TagName)532 		public bool RemoveTag(string TagName)
533 		{
534 			Element tag = _SelectElement(this, TagName);
535 			if ( tag != null)
536 			{
537 				tag.Remove();
538 				return true;
539 			}
540 		    return false;
541 		}
542 
543 		/// <summary>
544 		/// Remove a Tag when it exists
545 		/// </summary>
546 		/// <param name="type">Type of the tag that should be removed</param>
547 		/// <returns>true when existing and removed, false when not existing</returns>
RemoveTag(Type type)548 		public bool RemoveTag(Type type)
549 		{
550 			Element tag = _SelectElement(this, type);
551 			if (tag != null)
552 			{
553 				tag.Remove();
554 				return true;
555 			}
556 
557             return false;
558 		}
559 
560         public bool RemoveTag<T>() where T : Element
561         {
562             Element tag = SelectSingleElement<T>();
563             if (tag != null)
564             {
565                 tag.Remove();
566                 return true;
567             }
568 
569             return false;
570         }
571 
572         /// <summary>
573         /// Removes all Tags of the given type. Doesnt traverse the tree
574         /// </summary>
575         /// <param name="type">Type of the tags that should be removed</param>
576         /// <returns>true when tags were removed, false when no tags were found and removed</returns>
RemoveTags(Type type)577         public bool RemoveTags(Type type)
578         {
579             bool ret = false;
580 
581             ElementList list = SelectElements(type);
582 
583             if (list.Count > 0)
584                 ret = true;
585 
586             foreach (Element e in list)
587                 e.Remove();
588 
589             return ret;
590         }
591 
592         /// <summary>
593         /// Removes all Tags of the given type. Doesnt traverse the tree
594         /// </summary>
595         /// <typeparam name="T">Type of the tags that should be removed</typeparam>
596         /// <returns>true when tags were removed, false when no tags were found and removed</returns>
597         public bool RemoveTags<T>() where T : Element
598         {
599             return RemoveTags(typeof (T));
600         }
601 
602 		/// <summary>
603 		/// Same as AddChild, but Replaces the childelement when it exists
604 		/// </summary>
605 		/// <param name="e"></param>
ReplaceChild(Element e)606 		public void ReplaceChild(Element e)
607 		{
608 			if (HasTag(e.TagName))
609 				RemoveTag(e.TagName);
610 
611 			AddChild(e);
612 		}
613 
Attribute(string name)614 		public string Attribute(string name)
615 		{
616 			return (string) m_Attributes[name];
617 		}
618 
619 		/// <summary>
620 		/// Removes a Attribute
621 		/// </summary>
622 		/// <param name="name">Attribute as string to remove</param>
RemoveAttribute(string name)623 		public void RemoveAttribute(string name)
624 		{
625 			if (HasAttribute(name))
626 			{
627 				Attributes.Remove(name);
628 			}
629 		}
630 
631 		/// <summary>
632 		/// Adds a new Attribue or changes a Attriv when already exists
633 		/// </summary>
634 		/// <param name="name">name of Attribute to add/change</param>
635 		/// <param name="value">value of teh Attribute to add/change</param>
SetAttribute(string name, string val)636 		public void SetAttribute(string name, string val)
637 		{
638 			// When the attrib already exists then we overweite it
639 			// So we must remove it first and add it again then
640 			if (HasAttribute(name))
641 			{
642 				Attributes.Remove(name);
643 			}
644 			m_Attributes.Add(name, val);
645 
646 		}
647 
648         /// <summary>
649         ///
650         /// </summary>
651         /// <param name="name"></param>
652         /// <param name="value"></param>
SetAttribute(string name, int value)653 		public void SetAttribute(string name, int value)
654 		{
655 			SetAttribute(name, value.ToString());
656 		}
657 
658         /// <summary>
659         ///
660         /// </summary>
661         /// <param name="name"></param>
662         /// <param name="value"></param>
SetAttribute(string name, long value)663         public void SetAttribute(string name, long value)
664         {
665             SetAttribute(name, value.ToString());
666         }
667 
668         /// <summary>
669         /// Writes a boolean attribute, the value is either 'true' or 'false'
670         /// </summary>
671         /// <param name="name"></param>
672         /// <param name="val"></param>
SetAttribute(string name, bool val)673         public void SetAttribute(string name, bool val)
674         {
675             // When the attrib already exists then we overweite it
676             // So we must remove it first and add it again then
677             if (HasAttribute(name))
678             {
679                 Attributes.Remove(name);
680             }
681             m_Attributes.Add(name, val ? "true" : "false");
682         }
683 
684         /// <summary>
685         /// Set a attribute of type Jid
686         /// </summary>
687         /// <param name="name"></param>
688         /// <param name="value"></param>
SetAttribute(string name, Jid value)689         public void SetAttribute(string name, Jid value)
690         {
691              if (value != null)
692                     SetAttribute(name, value.ToString());
693                 else
694                     RemoveAttribute(name);
695         }
696 
697         /// <summary>
698         /// Set a attribute from a double in english number format
699         /// </summary>
700         /// <param name="name"></param>
701         /// <param name="value"></param>
SetAttribute(string name, double value)702         public void SetAttribute(string name, double value)
703         {
704             NumberFormatInfo nfi = new NumberFormatInfo();
705             nfi.NumberGroupSeparator = ".";
706             SetAttribute(name, value, nfi);
707         }
708 
709         /// <summary>
710         /// Set a attribute from a double with the given Format provider
711         /// </summary>
712         /// <param name="name"></param>
713         /// <param name="value"></param>
714         /// <param name="ifp"></param>
SetAttribute(string name, double value, IFormatProvider ifp)715         public void SetAttribute(string name, double value, IFormatProvider ifp)
716         {
717             SetAttribute(name, value.ToString(ifp));
718         }
719 
720 
SetNamespace(string value)721 		public void SetNamespace(string value)
722 		{
723 			SetAttribute("xmlns", value);
724 		}
725 
GetFirstCDataNode()726         private CData GetFirstCDataNode()
727         {
728             foreach (Node ch in ChildNodes)
729             {
730                 if (ch.NodeType == NodeType.Cdata)
731                     return ch as CData;
732             }
733             return null;
734         }
735 
736         /// <summary>
737         /// Has this Element some CDATA?
738         /// </summary>
739         /// <returns></returns>
HasData()740         public bool HasData()
741         {
742             return GetFirstCDataNode() != null;
743         }
744 
745         /// <summary>
746         /// Get the CDATA
747         /// </summary>
748         /// <returns></returns>
GetData()749 	    public string GetData()
750 	    {
751 	        var data = GetFirstCDataNode();
752 	        return data == null ? null : data.Value;
753 	    }
754 
755         /// <summary>
756         /// Set the CDATA
757         /// </summary>
758         /// <param name="cdata"></param>
SetData(string cdata)759         public void SetData(string cdata)
760         {
761             var data = GetFirstCDataNode();
762             if (data == null)
763             {
764                 data = new CData();
765                 AddChild(data);
766             }
767             data.Value = cdata;
768         }
769 
770 	    public string InnerXml
771 		{
772 			get
773 			{
774 			    if (ChildNodes.Count > 0)
775 				{
776 					string xml = "";
777 					try
778 					{
779 						for (int i = 0; i < ChildNodes.Count; i++)
780 						{
781 							if (ChildNodes.Item(i).NodeType == NodeType.Element)
782 								xml += ChildNodes.Item(i).ToString();
783 							else if (ChildNodes.Item(i).NodeType == NodeType.Text)
784 								xml += ChildNodes.Item(i).Value;
785 
786 						}
787 					}
788 					catch (Exception)
789 					{
790 					}
791 					return xml;
792 
793 				}
794 			    return null;
795 			}
796 		    set
797             {
798                 Document doc = new Document();
799                 doc.LoadXml(value);
800                 Element root = doc.RootElement;
801                 if (root != null)
802                 {
803                     ChildNodes.Clear();
804                     AddChild(root);
805                 }
806 
807             }
808 		}
809 
810         /// <summary>
811         /// returns whether the current element has child elements or not.
812         /// cares only about element, not text nodes etc...
813         /// </summary>
814         public bool HasChildElements
815         {
816 	        get
817 	        {
818                 foreach (Node e in ChildNodes)
819                 {
820                     if (e.NodeType == NodeType.Element)
821                         return true;
822                 }
823 		        return false;
824 	        }
825         }
826 
827 		/// <summary>
828 		/// returns the first child element (no textNodes)
829 		/// </summary>
830 		public Element FirstChild
831 		{
832 			get
833 			{
834 			    if (ChildNodes.Count > 0)
835                 {
836                     foreach (Node e in ChildNodes)
837                     {
838                         if (e.NodeType == NodeType.Element)
839                             return e as Element;
840                     }
841                     return null;
842 	            }
843 			    return null;
844 			}
845 		}
846 
847 		/// <summary>
848 		/// Returns the first ChildNode, doesnt matter of which type it is
849 		/// </summary>
850 		public Node FirstNode
851 		{
852 			get
853 			{
854 			    if(ChildNodes.Count > 0)
855 					return ChildNodes.Item(0) as Node;
856 			    return null;
857 			}
858 		}
859 
860 		/// <summary>
861 		/// Returns the last ChildNode, doesnt matter of which type it is
862 		/// </summary>
863 		public Node LastNode
864 		{
865 			get
866 			{
867 			    if(ChildNodes.Count > 0)
868 					return ChildNodes.Item(ChildNodes.Count -1) as Node;
869 			    return null;
870 			}
871 		}
872 
StartTag()873         internal string StartTag()
874         {
875             using (StringWriter sw = new StringWriter())
876             {
877                 using (XmlTextWriter tw = new XmlTextWriter(sw))
878                 {
879                     tw.Formatting = Formatting.None;
880 
881                     if (Prefix == null)
882                         tw.WriteStartElement(TagName);
883                     else
884                         tw.WriteStartElement(Prefix + ":" + TagName);
885 
886                     // Write Namespace
887                     if (Namespace != null
888                         && Namespace.Length != 0
889                         )
890                     {
891                         if (Prefix == null)
892                             tw.WriteAttributeString("xmlns", Namespace);
893                         else
894                             tw.WriteAttributeString("xmlns:" + Prefix, Namespace);
895                     }
896 
897                     foreach (string attName in this.Attributes.Keys)
898                     {
899                         tw.WriteAttributeString(attName, Attribute(attName));
900                     }
901 
902                     tw.Flush();
903                     tw.Close();
904 
905                     return sw.ToString().Replace("/>", ">");
906                 }
907             }
908         }
909 
EndTag()910 	    internal string EndTag()
911 	    {
912 	        if (Prefix == null)
913                 return "</" + TagName + ">";
914 	        return "</" + Prefix + ":" + TagName + ">";
915 	    }
916 
917 	    #region << Xml Select Functions >>
918         /// <summary>
919         /// Find a Element by type
920         /// </summary>
921         /// <param name="type"></param>
922         /// <returns></returns>
SelectSingleElement(System.Type type)923 		public Element SelectSingleElement(System.Type type)
924 		{
925 			return _SelectElement(this, type);
926 		}
927 
928         /// <summary>
929         /// find a Element by type and loop thru all children
930         /// </summary>
931         /// <param name="type"></param>
932         /// <param name="loopChildren"></param>
933         /// <returns></returns>
SelectSingleElement(System.Type type, bool loopChildren)934         public Element SelectSingleElement(System.Type type, bool loopChildren)
935         {
936             return _SelectElement(this, type, true);
937         }
938 
SelectSingleElement(string TagName)939 		public Element SelectSingleElement(string TagName)
940 		{
941 			return _SelectElement(this, TagName);
942 		}
943 
SelectSingleElement(string TagName, bool traverseChildren)944         public Element SelectSingleElement(string TagName, bool traverseChildren)
945         {
946             return _SelectElement(this, TagName, true);
947         }
948 
SelectSingleElement(string TagName, string AttribName, string AttribValue)949 		public Element SelectSingleElement(string TagName, string AttribName, string AttribValue)
950 		{
951 			return _SelectElement(this, TagName, AttribName, AttribValue);
952 		}
953 
SelectSingleElement(string TagName, string ns)954 		public Element SelectSingleElement(string TagName, string ns)
955 		{
956             return _SelectElement(this, TagName, ns, true);
957 		}
958 
SelectSingleElement(string TagName, string ns, bool traverseChildren)959         public Element SelectSingleElement(string TagName, string ns, bool traverseChildren)
960         {
961             return _SelectElement(this, TagName, ns, traverseChildren);
962         }
963 
964         public T SelectSingleElement<T>() where T : Element
965         {
966             return (T)_SelectElement(this, typeof(T));
967         }
968 
969         public T SelectSingleElement<T>(bool traverseChildren) where T : Element
970         {
971             return (T)_SelectElement(this, typeof(T), traverseChildren);
972         }
973 
974 		/// <summary>
975 		/// Returns all childNodes with the given Tagname,
976 		/// this function doesn't traverse the whole tree!!!
977 		/// </summary>
978 		/// <param name="TagName"></param>
979 		/// <returns></returns>
SelectElements(string TagName)980 		public ElementList SelectElements(string TagName)
981 		{
982             ElementList es = new ElementList();
983 			//return this._SelectElements(this, TagName, es);
984 			return _SelectElements(this, TagName, es, false);
985 		}
986 
SelectElements(string TagName, bool traverseChildren)987         public ElementList SelectElements(string TagName, bool traverseChildren)
988         {
989             ElementList es = new ElementList();
990             //return this._SelectElements(this, TagName, es);
991             return _SelectElements(this, TagName, es, traverseChildren);
992         }
993 
SelectElements(System.Type type)994         public ElementList SelectElements(System.Type type)
995 		{
996             ElementList es = new ElementList();
997 			return _SelectElements(this, type, es);
998 		}
999 
1000 		/// <summary>
1001 		/// returns a nodelist of all found nodes of the given Type
1002 		/// </summary>
1003 		/// <param name="e"></param>
1004 		/// <param name="type"></param>
1005 		/// <param name="es"></param>
1006 		/// <returns></returns>
_SelectElements(Element e, Type type, ElementList es)1007         private ElementList _SelectElements(Element e, Type type, ElementList es)
1008 		{
1009 			return _SelectElements(e, type, es, false);
1010 		}
1011 
_SelectElements(Element e, Type type, ElementList es, bool traverseChildren)1012         private ElementList _SelectElements(Element e, Type type, ElementList es, bool traverseChildren)
1013 		{
1014 			if (e.ChildNodes.Count > 0)
1015 			{
1016 				foreach(Node n in e.ChildNodes)
1017 				{
1018 					if (n.NodeType == NodeType.Element)
1019 					{
1020                         if (n.GetType() == type)
1021 						{
1022 							es.Add(n);
1023 						}
1024 						if (traverseChildren)
1025 							_SelectElements((Element) n, type, es, true);
1026 					}
1027 				}
1028 			}
1029 			return es;
1030 		}
1031 
1032 		/// <summary>
1033 		/// Select a single element.
1034 		/// This function doesnt traverse the whole tree and checks only the underlying childnodes
1035 		/// </summary>
1036 		/// <param name="se"></param>
1037 		/// <param name="tagname"></param>
1038 		/// <returns></returns>
_SelectElement(Node se, string tagname)1039 		private Element _SelectElement(Node se, string tagname)
1040 		{
1041 			return _SelectElement(se, tagname, false);
1042 		}
1043 
1044 		/// <summary>
1045 		/// Select a single element
1046 		/// </summary>
1047 		/// <param name="se"></param>
1048 		/// <param name="tagname"></param>
1049 		/// <param name="traverseChildren">when set to true then the function traverses the whole tree</param>
1050 		/// <returns></returns>
_SelectElement(Node se, string tagname, bool traverseChildren)1051 		private Element _SelectElement(Node se, string tagname, bool traverseChildren)
1052 		{
1053 			Element rElement = null;
1054 
1055 			if (se.ChildNodes.Count > 0)
1056 			{
1057 				foreach(Node ch in se.ChildNodes)
1058 				{
1059 					if (ch.NodeType == NodeType.Element)
1060 					{
1061 						if ( ((Element) ch).TagName == tagname )
1062 						{
1063 							rElement = (Element) ch;
1064 							return rElement;
1065 						}
1066 						else
1067 						{
1068 							if( traverseChildren)
1069 							{
1070 								rElement = _SelectElement(ch, tagname, true);
1071 								if (rElement != null)
1072 									break;
1073 							}
1074 						}
1075 					}
1076 				}
1077 			}
1078 
1079 			return rElement;
1080 		}
1081 
1082 
_SelectElement(Node se, System.Type type)1083 		private Element _SelectElement(Node se, System.Type type)
1084 		{
1085 			return _SelectElement(se, type, false);
1086 		}
1087 
_SelectElement(Node se, System.Type type, bool traverseChildren)1088 		private Element _SelectElement(Node se, System.Type type, bool traverseChildren)
1089 		{
1090 			Element rElement = null;
1091 
1092 			if (se.ChildNodes.Count > 0)
1093 			{
1094 				foreach(Node ch in se.ChildNodes)
1095 				{
1096 					if (ch.NodeType == NodeType.Element)
1097 					{
1098 						if ( ch.GetType() == type )
1099 						{
1100 							rElement = (Element) ch;
1101 							return rElement;
1102 						}
1103 						else
1104 						{
1105 							if( traverseChildren)
1106 							{
1107 								rElement = _SelectElement(ch, type, true);
1108 								if (rElement != null)
1109 									break;
1110 							}
1111 						}
1112 					}
1113 				}
1114 			}
1115 			return rElement;
1116 		}
1117 
_SelectElement(Node se, string tagname, string AttribName, string AttribValue)1118 		private Element _SelectElement(Node se, string tagname, string AttribName, string AttribValue)
1119 		{
1120 			Element rElement = null;
1121 
1122 			if (se.NodeType == NodeType.Element)
1123 			{
1124 				Element e = se as Element;
1125 				if (e.m_TagName == tagname)
1126 				{
1127 					if (e.HasAttribute(AttribName))
1128 					{
1129 						if (e.GetAttribute(AttribName) == AttribValue)
1130 						{
1131 							rElement = e;
1132 							return rElement;
1133 						}
1134 					}
1135 				}
1136 			}
1137 
1138 			if (se.ChildNodes.Count > 0)
1139 			{
1140 				foreach(Node ch in se.ChildNodes)
1141 				{
1142 					rElement = _SelectElement(ch, tagname, AttribName, AttribValue);
1143 					if (rElement != null)
1144 						break;
1145 				}
1146 			}
1147 
1148 			return rElement;
1149 		}
1150 
1151         /// <summary>
1152         /// Find Element by Namespace
1153         /// </summary>
1154         /// <param name="se">The se.</param>
1155         /// <param name="tagname">The tagname.</param>
1156         /// <param name="nameSpace">The name space.</param>
1157         /// <param name="traverseChildren">if set to <c>true</c> [traverse children].</param>
1158         /// <returns></returns>
_SelectElement(Node se, string tagname, string nameSpace, bool traverseChildren)1159         private Element _SelectElement(Node se, string tagname, string nameSpace, bool traverseChildren)
1160         {
1161             Element rElement = null;
1162 
1163             if (se.ChildNodes.Count > 0)
1164             {
1165                 foreach (Node ch in se.ChildNodes)
1166                 {
1167                     if (ch.NodeType == NodeType.Element)
1168                     {
1169                         Element e = ch as Element;
1170                         if (e.TagName == tagname && e.Namespace == nameSpace)
1171                         {
1172                             rElement = (Element)ch;
1173                             return rElement;
1174                         }
1175                         else
1176                         {
1177                             if (traverseChildren)
1178                             {
1179                                 rElement = _SelectElement(ch, tagname, nameSpace, traverseChildren);
1180                                 if (rElement != null)
1181                                     break;
1182                             }
1183                         }
1184                     }
1185                 }
1186             }
1187             return rElement;
1188         }
1189 
_SelectElements(Element e, string tagname, ElementList es, bool traverseChildren)1190         private ElementList _SelectElements(Element e, string tagname, ElementList es, bool traverseChildren)
1191 		{
1192 			if (e.ChildNodes.Count > 0)
1193 			{
1194 				foreach(Node n in e.ChildNodes)
1195 				{
1196 					if (n.NodeType == NodeType.Element)
1197 					{
1198 						if ( ((Element) n).m_TagName == tagname)
1199 						{
1200 							es.Add(n);
1201 						}
1202 						if (traverseChildren)
1203 							_SelectElements((Element) n, tagname, es, true);
1204 					}
1205 
1206 				}
1207 			}
1208 			return es;
1209         }
1210 
1211 
1212         public List<T> SelectElements<T>() where T : Element
1213         {
1214             return SelectElements<T>(false);
1215         }
1216 
1217         public List<T> SelectElements<T>(bool traverseChildren) where T : Element
1218         {
1219             List<T> list = new List<T>();
1220             return this._SelectElements<T>(this, list, traverseChildren);
1221         }
1222 
1223         private List<T> _SelectElements<T>(Element e, List<T> list, bool traverseChildren) where T : Element
1224         {
1225             if (e.ChildNodes.Count > 0)
1226             {
1227                 foreach (Node n in e.ChildNodes)
1228                 {
1229                     if (n.NodeType == NodeType.Element)
1230                     {
1231                         if (n.GetType() == typeof(T))
1232                         {
1233                             list.Add(n as T);
1234                         }
1235                         if (traverseChildren)
1236                             _SelectElements((Element)n, list, true);
1237                     }
1238                 }
1239             }
1240             return list;
1241         }
1242         #endregion
1243     }
1244 }