Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

c# - How to serialize TreeView in to xml and deserialize xml back to TreeView?

Tree representation of xml

After loading elements and attributes of the below xml file in to a treeview, the nodes are edited and the treeview is saved back in to the same xml file. All elements and attributes need to be saved. However the attributes of only nested elements disappear during saving. After saving, all attribures of elements d & e are lost! This is because i am unable to retrieve the attribute values stored in to the tag property in addTreeNode function.(please see inline comments) Does anyone know of an easier or cleaner way to achieve this? Providing code snippets would be helpfull.

XML structure:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <a axa="1" axb="2" axc="3">content_of_tag _a</a>
  <b bxa="10" bxb="20" bxc="30">content_of_tag_b</b>
  <c cxa="11" cxb="21" cxc="31">
  content_of_tag_c
      <d dxa="101" dxb="201" dxc="301">
      content_of_tag_d
          <e exa="110" exb="210" exc="310">
          content_of_tag_e
          </e>
      </d>
  </c>
</root>  

C# code:

private void Xml2TreeNode(XElement xNode, TreeNode treeNode)
{
    if (xNode.HasElements) //if node has children
    {
        TreeNode tNode = null;
        int i = 0;
        foreach (XElement subNode in xNode.Elements())
        {
            if (subNode.Descendants().Count() > 0)
            {
                TreeNode tn = treeNode.Nodes.Add(subNode.Name.ToString().Trim());
                tn.Nodes.Add(new TreeNode(subNode.FirstNode.ToString().Trim()));
                treeNode.Nodes[i].Tag = subNode.Attributes().ToList(); //-------->this attribure values are NOT retrievable in saveNodes function!
                tNode = tn; //add child nodes
            }
            else
            {
                TreeNode tn = treeNode.Nodes.Add(subNode.Name.ToString().Trim()); //show name of a leaf node element
                tn.Nodes.Add(new TreeNode(subNode.Value.ToString().Trim())); //show value of above element as a child of its name
                treeNode.Nodes[i].Tag = subNode.Attributes().ToList(); //---->these values are retrivable in saveNodes function
                tNode = treeNode.Nodes[i++]; //add sibling node
            }

            addTreeNode(subNode, tNode); //recursively add child nodes
        }
    }
}




private void TreeNode2Xml(TreeNodeCollection tnc)
{
    foreach (TreeNode node in tnc)
    {
        if (node.Nodes.Count > 0)
        {
            xr.WriteStartElement(node.Text);
            if (node.Tag != null) //attribures retrieved here
            {
                List<XAttribute> attributeList = node.Tag as List<XAttribute>;
                foreach (XAttribute attribute in attributeList)
                {
                    xr.WriteAttributeString(attribute.Name.ToString(), attribute.Value.ToString());
                }
            }
            saveNodes(node.Nodes);
            xr.WriteEndElement();
        }
        else //No child nodes, so we just write the text
        {
            xr.WriteString(node.Text);
        }
    }
}  



xr = new XmlTextWriter(filename, System.Text.Encoding.UTF8); //System.Text.Encoding.UTF8
xr.Formatting = Formatting.Indented;
xr.WriteStartDocument();
//Write our root node
xr.WriteStartElement(treeView1.Nodes[0].Text);
foreach (TreeNode node in tv.Nodes)
{
    **TreeNode2Xml(node.Nodes);**
}
//Close the root node
xr.WriteEndElement();
xr.Close();




xDoc = XDocument.Load(dlg.FileName);
treeView1.Nodes.Clear();
treeView1.Nodes.Add(new TreeNode(xDoc.Document.Root.Name.ToString().Trim()));
TreeNode tNode = new TreeNode();
tNode = (TreeNode)treeView1.Nodes[0];
**Xml2TreeNode(xDoc.Root, tNode);**
treeView1.ExpandAll();  
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Exelent post of load and saving of data of treeview Example Load/Save XML-Treeview

Save Data Code:

//We use this in the export and the saveNode 
//functions, though it's only instantiated once.
private StreamWriter sr;

public void exportToXml(TreeView tv, string filename) 
{
    sr = new StreamWriter(filename, false, System.Text.Encoding.UTF8);
    //Write the header
    sr.WriteLine("<?xml version="1.0" encoding="utf-8" ?>");
    //Write our root node
    sr.WriteLine("<" + treeView1.Nodes[0].Text + ">");
    foreach (TreeNode node in tv.Nodes)
    {
        saveNode(node.Nodes);
    }
    //Close the root node
    sr.WriteLine("</" + treeView1.Nodes[0].Text + ">");
    sr.Close();
}

private void saveNode(TreeNodeCollection tnc)
{
    foreach (TreeNode node in tnc)
    {
        //If we have child nodes, we'll write 
        //a parent node, then iterrate through
        //the children
        if (node.Nodes.Count > 0)
        {
            sr.WriteLine("<" + node.Text + ">");
            saveNode(node.Nodes);
            sr.WriteLine("</" + node.Text + ">");
        } 
        else //No child nodes, so we just write the text
            sr.WriteLine(node.Text);
    }
}

Load Data

//Open the XML file, and start to populate the treeview
private void populateTreeview()
{
    OpenFileDialog dlg = new OpenFileDialog();
    dlg.Title = "Open XML Document";
    dlg.Filter = "XML Files (*.xml)|*.xml";
    dlg.FileName = Application.StartupPath + "\..\..\example.xml";
    if (dlg.ShowDialog() == DialogResult.OK)
    {
        try
        {
            //Just a good practice -- change the cursor to a 
            //wait cursor while the nodes populate
            this.Cursor = Cursors.WaitCursor;
            //First, we'll load the Xml document
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(dlg.FileName);        
            //Now, clear out the treeview, 
            //and add the first (root) node
            treeView1.Nodes.Clear();
            treeView1.Nodes.Add(new 
              TreeNode(xDoc.DocumentElement.Name));
            TreeNode tNode = new TreeNode();
            tNode = (TreeNode)treeView1.Nodes[0];
            //We make a call to addTreeNode, 
            //where we'll add all of our nodes
            addTreeNode(xDoc.DocumentElement, tNode);
            //Expand the treeview to show all nodes
            treeView1.ExpandAll();    
        }
        catch(XmlException xExc) 
          //Exception is thrown is there is an error in the Xml
        {
            MessageBox.Show(xExc.Message);
        }
        catch(Exception ex) //General exception
        {
            MessageBox.Show(ex.Message);
        }
        finally
        {
            this.Cursor = Cursors.Default; //Change the cursor back
        }
    }
}
//This function is called recursively until all nodes are loaded
private void addTreeNode(XmlNode xmlNode, TreeNode treeNode)
{
    XmlNode xNode;
    TreeNode tNode;
    XmlNodeList xNodeList;
    if (xmlNode.HasChildNodes) //The current node has children
    {
        xNodeList = xmlNode.ChildNodes;
        for(int x=0; x<=xNodeList.Count-1; x++) 
          //Loop through the child nodes
        {
            xNode = xmlNode.ChildNodes[x];
            treeNode.Nodes.Add(new TreeNode(xNode.Name));
            tNode = treeNode.Nodes[x];
            addTreeNode(xNode, tNode);
        }
    }
    else //No children, so add the outer xml (trimming off whitespace)
        treeNode.Text = xmlNode.OuterXml.Trim();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...