0

I am attempting to implement the following tree structure class as per Tree data structure in C#

delegate void TreeVisitor<T>(T nodeData);

class NTree<T>
{
    T data;
    LinkedList<NTree<T>> children;

    public NTree(T data)
    {
        this.data = data;
        children = new LinkedList<NTree<T>>();
    }

    public void addChild(T data)
    {
        children.AddFirst(new NTree<T>(data));
    }

    public NTree<T> getChild(int i)
    {
        foreach (NTree<T> n in children)
            if (--i == 0) return n;
        return null;
    }

    public NTree<T> getChild( T data )
{
    foreach (NTree<T> n in children)
        {
         if (n.data.Equals(data))
     {
         return n;
     }
    }
    return null;
    }

    public void traverse(NTree<T> node, TreeVisitor<T> visitor)
    {
        visitor(node.data);
        foreach (NTree<T> kid in node.children)
            traverse(kid, visitor);
    }        
}

I want to then output an instance of the object as XML, however I'm struggling to keep the child / parent hierarchy in place

So far I have

NTree<string> root = new NTree<string>( "Electronic" );
root.addChild( "Techno" );
root.getChild( "Techno" ).addChild( "Detroit" );
root.getChild( "Techno" ).addChild( "Gabba" );
root.addChild( "House" );
root.getChild( "House" ).addChild( "Deep" );
root.getChild( "House" ).addChild( "Ambient" );
root.getChild( "House" ).addChild( "Chicago" );

XElement treeAsXml = new XElement("Root");
root.traverse( root, new TreeVisitor<string>( this.ConvertNodeToXml ) );

private void ConvertNodeToXml( string nodeData )
{
 XElement node = new XElement( "Node" );
 node.Value = nodeData;
 this.treeAsXml.Add( node );
}

Which just gives me:

<Root><Node>Electronic</Node><Node>House</Node><Node>Chicago</Node><Node>Ambient</Node><Node>Deep</Node><Node>Techno</Node><Node>Gabba</Node><Node>Detroit</Node></Root>

How can I output this correctly, ideally as below

<Node value="Electronic">
<Node value="Techno">
    <Node value="Detroit" />
    <Node value="Gabba" />
</Node> 
<Node value="House">
    <Node value="Deep" />
    <Node value="Ambient" />
    <Node value="Chicago" />
</Node>     
</Node>
Community
  • 1
  • 1
Stewart Alan
  • 1,521
  • 5
  • 23
  • 45

1 Answers1

1

The problem is that your delegate has no context, it does not know it's parent and it does not know it's children since it only gets the data of the node. You would either have to change the delegate to include some type of context or you could do it as an extension method:

public static class NTreeXmlHelper
{
    public static XElement TreeAsXml<T>(this NTree<T> node)
    {
        XElement element = new XElement("Node",
                                  new XAttribute("value", node.data));

        foreach (var child in node.children)
        {
            element.Add(TreeAsXml(child));
        }

        return element;
    }
}

For this to work you would have to make the children and data properties public.

To use it just do :

        NTree<string> root = new NTree<string>("Electronic");
        root.addChild("Techno");
        root.getChild("Techno").addChild("Detroit");
        root.getChild("Techno").addChild("Gabba");
        root.addChild("House");
        root.getChild("House").addChild("Deep");
        root.getChild("House").addChild("Ambient");
        root.getChild("House").addChild("Chicago");

        treeAsXml = root.TreeAsXml();
        Console.WriteLine(treeAsXml.Tostring());
Tommy Grovnes
  • 4,126
  • 2
  • 25
  • 40