public static KmlNode[] SelectNodes(KmlNode ParentNode, string Path)
        {
            //check that the path is not blank
            if (Path != "")
            {
                List<KmlNode> SelectedNodes = new List<KmlNode>();
                string[] nodeNames = Path.Split('/');
                foreach (KmlNode kNode in ParentNode.ChildNodes)
                {
                    if (String.Compare(kNode.FirstValue.Value, nodeNames[0], true) == 0 && nodeNames.Length == 1)
                    {
                        SelectedNodes.Add(kNode);
                        //MessageBox.Show("Ad1");

                    }
                    if (nodeNames.Length > 1)
                    {
                        //MessageBox.Show(GetNextPath(nodeNames));
                        SelectedNodes.AddRange(SelectNodes(kNode, GetNextPath(nodeNames)));
                    }
                }
                return SelectedNodes.ToArray();
            }
            else
            {
                throw new InvalidKmlPathException(Path);
            }
        }
 /// <summary>
 /// Adds an item to the collection.
 /// </summary>
 /// <param name="item">The item to add to the collection.</param>
 /// <returns></returns>
 public KmlNode Add(KmlNode item)
 {
     List.Add(item);
     item.Parent = Parent;
     return item;
 }
 /// <summary>
 /// Sets the item at the specified index in the collection.
 /// </summary>
 /// <param name="index">The index to set.</param>
 /// <param name="item">The item to set.</param>
 public void Set(int index, KmlNode item)
 {
     List[index] = item;
     item.Parent = Parent;
 }
 /// <summary>
 /// Creates a new collection with the specified parent.
 /// </summary>
 /// <param name="parent">The parent.</param>
 public KmlNodeCollection(KmlNode parent)
 {
     this.Parent = parent;
 }
 /// <summary>
 /// Gets the index of the specified item.
 /// </summary>
 /// <param name="item">The item to get the index of.</param>
 /// <returns></returns>
 public int IndexOf(KmlNode item)
 {
     return List.IndexOf(item);
 }
 /// <summary>
 /// Removes the item from the collection.
 /// </summary>
 /// <param name="item"></param>
 public void Remove(KmlNode item)
 {
     if (List.Contains(item))
     {
         List.Remove(item);
         item.Parent = null;
     }
 }
 /// <summary>
 /// Checks if the collection contains the specified item.
 /// </summary>
 /// <param name="item">The item to check for.</param>
 /// <returns></returns>
 public bool Contains(KmlNode item)
 {
     return List.Contains(item);
 }
 /// <summary>
 /// Copies the collection to an array starting at a specified index.
 /// </summary>
 /// <param name="array">The array to copy the collection to.</param>
 /// <param name="index">The index to start copying from.</param>
 public void CopyTo(KmlNode[] array, int index)
 {
     List.CopyTo(array, index);
 }
 /// <summary>
 /// Adds a range of items to the collection
 /// </summary>
 /// <param name="range">The range of values to add to the collection.</param>
 public void AddRange(KmlNode[] range)
 {
     foreach (KmlNode value in range)
     {
         List.Add(value);
         value.Parent = Parent;
     }
 }
        /// <summary>
        /// Returns a deep-copy of the collection.
        /// </summary>
        /// <returns></returns>
        public KmlNodeCollection Clone(KmlNode parent)
        {
            KmlNodeCollection newCollection = new KmlNodeCollection(parent);
            foreach (KmlNode item in List)
            {
                newCollection.Add(item.Clone());
            }

            return newCollection;
        }
        /// <summary>
        /// Merges the node with the target node.
        /// </summary>
        /// <param name="target">The target to merge with.</param>
        public void Merge(KmlNode target)
        {
            if (target == null || target == this)
            {
                return;
            }

            //merge values
            for(int i = this.Values.Count; i < target.Values.Count; i++)
            {
                this.Values.Add(target.Values[i]);
               // MessageBox.Show(target.Values[i].Value);
            }

            List<KmlNode> subNodesToAdd = new List<KmlNode>();
            //match first values that are not numeric

            foreach (KmlNode targetSubNode in target.ChildNodes)
            {
                //merge current subnodes
                foreach (KmlNode subNode in this.ChildNodes)
                {
                    //if it is numeric then it is probably an array.
                    if (targetSubNode.FirstValue.IsNumeric)
                    {
                        if (subNode.FirstValue.IsNumeric)
                        {
                            //they are both numeric so we can merge the values
                            subNode.Merge(targetSubNode);
                        }
                    }
                    else
                    {
                        //check if the subnodes have the same key
                        if (targetSubNode.FirstValue.Value == subNode.FirstValue.Value)
                        {
                            //merge them
                            //MessageBox.Show(targetSubNode.FirstValue.Value);
                            subNode.Merge(targetSubNode);
                        }
                    }
                }

                //for subnodes that don't exist
                if (!this.ChildNodes.ContainsKey(targetSubNode.FirstValue.Value))
                {
                    subNodesToAdd.Add(targetSubNode);
                }
            }

            foreach (KmlNode kNode in subNodesToAdd)
            {
                this.ChildNodes.Add(kNode);
            }

            //we have stolen any nodes needed from target, now we kill the target.
            target.ChildNodes.Clear();
        }
        public KmlNode Clone()
        {
            KmlNode newNode = new KmlNode(StartPosition.Clone(), EndPosition.Clone());

            newNode.ChildNodes = ChildNodes.Clone(newNode);
            newNode.Values = Values.Clone(newNode);
            newNode.Values.Parent = newNode;

            if (StartPosition != null)
            {
                newNode.StartPosition = StartPosition.Clone();
            }
            if (EndPosition != null)
            {
                newNode.EndPosition = EndPosition.Clone();
            }

            //comments
            foreach (KmlComment comment in Comments)
            {
                newNode.Comments.Add(comment.Clone());
            }

            return newNode;
        }
        /// <summary>
        /// Returns a deep-copy of the collection.
        /// </summary>
        /// <returns></returns>
        public KmlValueCollection Clone(KmlNode parent)
        {
            KmlValueCollection newCollection = new KmlValueCollection(parent);

            foreach (KmlValue value in List)
            {
                newCollection.Add(value.Clone());
            }

            return newCollection;
        }
        /// <summary>
        /// Reads a comment from the stream
        /// </summary>
        /// <returns></returns>
        public void ReadComment(KmlNode Node)
        {
            StringBuilder buffer = new StringBuilder();
            bool end = false;

            //record start position for errors
            CharPosition startPosition = GetCurrentPosition();

            while (!end)
            {
                //check if we are at end of stream
                if (reader.Peek() < 0)
                {
                    break;
                }

                char c = (char)reader.Read();

                //keep track of characters read
                TrackPosition(c);

                if (c == END_COMMENT_CHAR)
                {
                    end = true;
                }
                else
                {
                    buffer.Append(c);
                }
            }

               CommentBuffer.Add(new KmlComment(buffer.ToString(), startPosition, GetCurrentPosition()));
        }
        public KmlNode ReadNode(KmlNode Parent)
        {
            StringBuilder buffer = new StringBuilder();
            bool end = false;
            bool readingValue = false;

            //record start position
            CharPosition nodeStartPosition = GetCurrentPosition();
            CharPosition valueStartPosition = GetCurrentPosition();

            //node to store values in
            KmlNode node = new KmlNode(nodeStartPosition);

            //unload comments
            node.Comments.AddRange(CommentBuffer);
            CommentBuffer.Clear();
            while (!end)
            {
                //check if we are at end of stream
                if (reader.Peek() < 0)
                {
                    throw new InvalidKmlSyntaxException(GetCurrentPosition(), new UnclosedNodeException(nodeStartPosition));
                }
                char c = (char)reader.Read();
                //keep track of characters read
                TrackPosition(c);
                //check for comment
                if (c == COMMENT_CHAR)
                {
                    ReadComment(node);
                    continue;
                }
                //check if we are reading whitespace
                if (Char.IsWhiteSpace(c) || Char.IsSeparator(c) || c== CLOSE_NODE_CHAR)
                {
                    //check if we have finished reading the node
                    if (c == CLOSE_NODE_CHAR)
                    {
                        //end reading
                        end = true;
                    }
                    //check if we have been reading a value
                    if (readingValue)
                    {
                        //create new value
                        KmlValue val = new KmlValue(buffer.ToString(), false, valueStartPosition, GetCurrentPosition());
                        //give it out comments
                        val.Comments.AddRange(CommentBuffer);
                        //clear out our comments
                        CommentBuffer.Clear();
                        //put the buffer into a value
                        node.Values.Add(val);
                        //finished reading value
                        readingValue = false;
                        //clear buffer
                        buffer = new StringBuilder();
                    }
                    //if not ignore
                }
                else
                {

                    //check if theres another node to read
                    if (c == OPEN_NODE_CHAR)
                    {
                        //read the node and add to child nodes
                        KmlNode rn = ReadNode(null);
                        node.ChildNodes.Add(rn);
                    }
                    //check if theres a string to read
                    else if (c == QUOTE_CHAR)
                    {
                        //end pos
                        CharPosition valueEndPosition = GetCurrentPosition();
                        //create our value
                        KmlValue val = new KmlValue(ReadString(), true, valueStartPosition, valueEndPosition);

                        //give it out comments
                        val.Comments.AddRange(CommentBuffer);
                        //clear out our comments
                        CommentBuffer.Clear();
                        //read the string and add it to values
                        node.Values.Add(val);
                    }
                    else
                    {
                        //check if we are reading a value
                        if (!readingValue)
                        {
                            //we arnt reading a value - but we are now
                            readingValue = true;
                            //set value start post
                            valueStartPosition = GetCurrentPosition();
                        }
                        //add the character to the buffer
                        buffer.Append(c);
                        //MessageBox.Show(c.ToString());
                    }
                }
            }

            node.EndPosition = new CharPosition(Position.Row, Position.Column + 1, Position.Offset + 1);

            return node;
        }