/// <summary>
        /// Replace tree node anywhere in the node hierarchy
        /// </summary>
        /// <param name="treeNodeToReplace"></param>
        /// <param name="replacementElement"></param>
        /// <returns>Tuple containing 2 tree nodes: Item1 = root node (to repopulate treDataNodes) and Item2 = replacement node (to make it selected node)</returns>
        private Tuple <TreeNode, TreeNode> ReplaceTreeNode(TreeNode treeNodeToReplace, XElement replacementElement)
        {
            var oldNodeData = (XmlNodeData)treeNodeToReplace.Tag;
            var index       = oldNodeData.SeqNo; //index to replace node in the parent node
            var newNodeData = new XmlNodeData(replacementElement, oldNodeData.Level, index);

            var      replacementTreeNode = CreateTreeNodeHierarchy(newNodeData);
            var      parentNode          = treeNodeToReplace.Parent;
            TreeNode rootNode;

            if (parentNode == null)
            { //end of recursion, mark the new root node (to be kept as Item1 in return value)
                rootNode = replacementTreeNode;
            }
            else
            { //update parent node (recursively)
                parentNode.Nodes.RemoveAt(index);
                parentNode.Nodes.Insert(index, replacementTreeNode);

                //newParentElement is the same as current, except for the current element
                var parentNodeData            = (XmlNodeData)parentNode.Tag;
                var replacemeentParentElement = new XElement(parentNodeData.Name);
                replacemeentParentElement.Add(parentNodeData.Attributes);
                replacemeentParentElement.Add(parentNodeData.Element.Elements().Select((e, i) => i == newNodeData.SeqNo ? replacementElement : e));
                var newNodes = ReplaceTreeNode(parentNode, replacemeentParentElement);
                rootNode = newNodes.Item1;
            }
            return(Tuple.Create(rootNode, replacementTreeNode));
        }
        /// <summary>
        /// Creates a hierarchy of tree nodes for a given XmlNodeData object
        /// </summary>
        /// <param name="hierarchyRoot"></param>
        /// <returns></returns>
        private TreeNode CreateTreeNodeHierarchy(XmlNodeData hierarchyRoot)
        {
            var newTreeNode = new TreeNode(hierarchyRoot.FullName)
            {
                Tag = hierarchyRoot // //Tag property of each tree node contains a XmlNodeData object that describes node contents
            };

            foreach (var child in hierarchyRoot.Children)
            {
                newTreeNode.Nodes.Add(CreateTreeNodeHierarchy(child));
            }
            return(newTreeNode);
        }
        /// <summary>
        /// Accept an XML string, parse it and populate the form with it.
        /// </summary>
        /// <param name="xmlData">The XML string to parse and display.</param>
        /// <returns>true if data sucessfully assigned, false if submitted XML is invalid.</returns>
        public bool AssignFacetsData(string xmlData)
        {
            XmlNodeData xmlNodeData;

            try { xmlNodeData = new XmlNodeData(xmlData); }
            catch (System.Xml.XmlException)
            {
                MessageBox.Show("Submitted text is not a valid XML.", "FacetsDataExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return(false);
            }
            var rootNode = CreateTreeNodeHierarchy(xmlNodeData);

            PopulateTreeView(rootNode);
            ////         this.treDataNodes.SelectedNode = rootNode;
            this.txtNodeContents.Clear();
            return(true);
        }