1. Tech

Your suggestion is on its way!

An email with a link to:

http://delphi.about.com/library/weekly/aa101904a.htm

was emailed to:

Thanks for sharing About.com with others!

Exporting a TreeView to XML. Populating a TreeView from XML
Here's how to store TTreeView component items to XML (preserving the Text and other properties of a tree node) and how to populate a TreeView from an XML file.
 Win prizes by sharing code!
Do you have some Delphi code you want to share? Are you interested in winning a prize for your work?
Delphi Programming Quickies Contest
 More of this Feature
• FULL SOURCE CODE
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• TTreeView to the Max (TreeView related tutorials, articles and tips)
• Working with XML files
• Using VCL components

The TTreeView Delphi component (located on the "Win32" component palette tab) represents a window that displays a hierarchical list of items. Each item (tree node) consists of a label and an optional bitmapped image (two to be precise).
XML gives developers the power to deliver structured data. A structure of an XML document is very similar to the structure of a tree view. In Delphi, the TXMLDocument (located on the "Internet" component palette tab) can be used to represent an XML document.

This article will show you techniques you can use to export tree view items to an XML file, and how to construct a tree view from an XML document.

If you need a powerful and transferable format for some kind of application configuration storage, which comes from a tree view, XML is a great choice, as you will see...

Saving TTreeView items to XML
First, we build a sample application hosting a TTreeView component, two ImageList components and one TXMLDocument component. One image list is associated with the Images property of a TreeView, another attached to the StateImages property (see: how to add check boxes and radio buttons to a tree view).

From XML to a TTreeView This is a screen shot of the application at run time (with "dummy" images for tree items). The Tree2XML procedure is used to save the tree view items to an XML document. Its only parameter is the reference to a TTreeView component we are saving to XML. The XML document has the same name as the application (of course, with the '.XML' as extension)

The procedure basically iterates through all TreeView items and for each item calls the ProcessTreeItem sub-procedure. The ProcessTreeItem is then recursively called for each tree node at the same level as the calling node. This recursive algorithm ensures all TreeView nodes are processed.
For each tree view item, an XML node (IXMLNode) is created with its attributes holding the values of Text, ImageIndex and StateIndex properties. Note that you could actually store any kind of tree node related value.
Once all the tree view items were processed the XML file is saved.
Note that the ProcessTreeItem procedure dynamically creates and manipulates a TXMLDocument (XMLDoc) component.

procedure Tree2XML(tree: TTreeView);
var
  tn : TTreeNode;
  XMLDoc : TXMLDocument;
  iNode : IXMLNode;

  procedure ProcessTreeItem(
        tn    : TTreeNode; 
        iNode : IXMLNode);
  var
    cNode : IXMLNode;
  begin
    if (tn = nil) then Exit;
    cNode := iNode.AddChild('item');
    cNode.Attributes['text'] := tn.Text;
    cNode.Attributes['imageIndex'] := tn.ImageIndex;
    cNode.Attributes['stateIndex'] := tn.StateIndex;

    //child nodes
    tn := tn.getFirstChild;
    while tn <> nil do
    begin
      ProcessTreeItem(tn, cNode);
      tn := tn.getNextSibling;
    end;
  end; (*ProcessTreeItem*)
begin
  XMLDoc := TXMLDocument.Create(nil);
  XMLDoc.Active := True;
  iNode := XMLDoc.AddChild('tree2xml');
  iNode.Attributes['app'] := ParamStr(0);

  tn := tree.TopItem;
  while tn <> nil do
  begin
    ProcessTreeItem (tn, iNode);

    tn := tn.getNextSibling;
  end;

  XMLDoc.SaveToFile(ChangeFileExt(ParamStr(0),'.XML'));

  XMLDoc := nil;
end; (* Tree2XML *)

In real world scenarios, you would export your tree view to XML when the application gets closed. The sample application provided for download, uses the OnCloseQuery event of a form to ask the user whether the TreeView should be saved to an XML:

// tree is the name of the TTreeView component
procedure TForm1.FormCloseQuery(
    Sender: TObject; 
    var CanClose: Boolean);
begin
  case MessageDlg('Save tree items to XML?', 
                   mtConfirmation, 
                   [mbYes, mbNo, mbCancel], 0) of
    mrYes:
      Tree2XML(tree); 
    mrNo:
      CanClose := True;
    mrCancel:
      CanClose := False;
  end;
end;

Here's the resulting XML document.

XML view of a TreeView
Loading TTreeView items from XML
Once we have the XML representation of the tree view items, we can use it to populate the tree view. When the application starts, the XML2Tree procedure is called to construct the tree. The tree parameter is a reference to a TTreeView component we are populating; the XMLDoc parameter points to a TXMLDocument component. In this case we are using the TXMLDocument component dropped on a form.

procedure XML2Tree(
          tree   : TTreeView; 
          XMLDoc : TXMLDocument);
var
  iNode : IXMLNode;

  procedure ProcessNode(
        Node : IXMLNode; 
        tn   : TTreeNode);
  var
    cNode : IXMLNode;
  begin
    if Node = nil then Exit;
    with Node do
    begin
      tn := tree.Items.AddChild(tn, Attributes['text']);
      tn.ImageIndex := Integer(Attributes['imageIndex']);
      tn.StateIndex := Integer(Attributes['stateIndex']);
    end;


    cNode := Node.ChildNodes.First;
    while cNode <> nil do
    begin
      ProcessNode(cNode, tn);
      cNode := cNode.NextSibling;
    end;
  end; (*ProcessNode*)
begin
  tree.Items.Clear;
  XMLDoc.FileName := ChangeFileExt(ParamStr(0),'.XML');
  XMLDoc.Active := True;

  iNode := XMLDoc.DocumentElement.ChildNodes.First;

  while iNode <> nil do
  begin
    ProcessNode(iNode,nil);
    iNode := iNode.NextSibling;
  end;

  XMLDoc.Active := False;
end;

The XML2Tree procedure basically operates on the same principles as the Tree2XML does. The code walks through the nodes of the XML, creates TTreeNode objects and adds them to the TreeView component.

That's it
To be honest, in the last couple of projects I've stopped using the Registry or INI files for storing a few pieces of application configuration data. XML seems much friendlier.
The full source code is available for download.

If you need any help with the code, do post your questions and/or comments to the Delphi Programming Forum.

©2014 About.com. All rights reserved.