4

I need to display a large XML file (>21MB) in a tree view control in a C# Windows Form application. I have written the code which is working for small XML files but when i am trying to open a BIG XML file (>1 MB), its taking too much of time. Can anyone suggest how i can optimise this and suggest me any changes or alternatives to achieve this.

Below is the code snippet:

private void CreateTreeViewFromATXML(string strSrcFileName)
        {
            XmlDataDocument xmldoc = new XmlDataDocument();
            XmlNode xmlnode ;
            FileStream fs = new FileStream(strSrcFileName, FileMode.Open, FileAccess.Read);
            xmldoc.Load(fs);
            xmlnode = xmldoc.ChildNodes[1];
            XMLTreeView.Nodes.Clear();
            XMLTreeView.Nodes.Add(new TreeNode(xmldoc.DocumentElement.Name));
            TreeNode tNode ;
            tNode = XMLTreeView.Nodes[0];
            AddNode(xmlnode, tNode);
        }


    private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
    {
        //XmlNode xNode ;
        TreeNode tNode ;
        XmlNodeList nodeList ;
        int i = 0;
        if (inXmlNode.HasChildNodes)
        {
            nodeList = inXmlNode.ChildNodes;

            foreach (XmlNode XNode in inXmlNode.ChildNodes)
            {
                tNode = new TreeNode(XNode.Name);
                inTreeNode.Nodes.Add(tNode);
                AddNode(XNode, tNode);
            }
        }
        else
        {
            inTreeNode.Text = inXmlNode.InnerText.ToString();
        }
    }
Pradnya Bolli
  • 1,915
  • 1
  • 19
  • 37
  • 2
    Instead of building the entire treeview up-front, build it lazily. When the user clicks a node, build its children. – Tomalak May 15 '15 at 04:54
  • 1
    I would also consider using a worker/background thread for parsing and generating tree nodes, as it isn't desirable to lockup the UI thread processing considerable chunks of data like this. – pnm Jan 14 '16 at 16:43

3 Answers3

4

I would wrap your code like this:

XMLTreeView.BeginUpdate();
try
{
    CreateTreeViewFromATXML(strSrcFileName);
}
catch (Exception e)
{
    //Handle any error
}
finally
{
    XMLTreeView.EndUpdate();
}

If you're not in an update block it's repainting the GUI on every node add and that's expensive. You also have recursion in AddNode but if the XML isn't too deeply nested it shouldn't be an issue.

Zer0
  • 7,191
  • 1
  • 20
  • 34
1

I would suggest using XDocument and XML to Linq for a faster parsing. You can use the following code to parse the XML:

using System.Xml;
using System.Xml.Linq;
using System.Data;

            XDocument xdoc = XDocument.Load(XMLFile);

var item = from items in xdoc.Element("EPICORTLOG").Descendants("POS")
                       where (string)items.Element("Id") == strSelectedPOSID
                       select items.Elements("TRADE").Elements("ITEM").ToList().ToList();

You can then follow the explanation in the following link to parse the XML: http://www.dotnetcurry.com/showarticle.aspx?ID=564 The article above will explain the XML to LINQ programming. Using the above method you can load XML files as big as 10MB in a short time.

Sormita Chakraborty
  • 1,015
  • 2
  • 19
  • 36
0

Recently, I used TreeView component to implement my HTML editor in C#, I used serialized data structure to impove the performance to open and save a XML file. From my experience , using this structure and serialize read and write file can open file up to 20M byes within 2 seconds in my computer. This solution can open a XML file over 2G bytes in my C# application. Hope this solution can help you better.

Example to define Serializable Structure for TreeView and TreeNode

[Serializable]
public class TreeViewData
{
    public TreeNodeData[] Nodes;
    public TreeViewData(){ }  
    public TreeViewData(TreeView treeview)
    {
       //your code
    }
    public TreeViewData(TreeNode treenode)
    {
       //your code 
    }
    public void PopulateTree(TreeView treeview)
    {
        //your code 
    }
    public void PopulateSubTree(TreeNode treenode)
    {
         //your code 
    }
}
[Serializable]
public class TreeNodeData
{
    public string Text;
    public int ImageIndex;
    public int SelectedImageIndex;
    public string Tag;
    public TreeNodeData[] Nodes;
    public TreeNodeData() {}  
    public TreeNodeData(TreeNode node)
    {
          // your code 
    }
    public TreeNode ToTreeNode()
    {
     // your code 
    }
}

Example to serialize read XML file

System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(TreeViewData));
System.IO.FileStream file = new System.IO.FileStream(strFilename, FileMode.Open);
System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(file);
TreeViewData treeData = (TreeViewData)ser.Deserialize(reader);
treeData.PopulateTree(TreeView1);

Example to serialize write XML file

System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(TreeViewData));
System.IO.FileStream file = new System.IO.FileStream(strFilename,   System.IO.FileMode.Create);
System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(file, null);
ser.Serialize(writer, new TreeViewData(TreeView1));
McMillan Cheng
  • 382
  • 1
  • 6
  • 20
  • Actually, I want to ask the same question as you did. but my question is how to display a large xml file over 1G bytes in treeview. that is the reason I found your post. – McMillan Cheng Oct 21 '17 at 02:08