Search code examples
c#algorithmtraversal

Reverse traverse xml node to root node based on dependencies defined in subelement


I have an XML structure with nodes. Each node may, or may not, have one or several dependencies on another node(s). I want to do a traverse reverse from one node to root based on the starting nodes dependency or dependencies. The result of the below code, starting from node w/ id=6, would be: 6, 2, 1, 5, 4

using System;
using System.Xml;

namespace ReverseTraverseXML
{
    class Program
    {
        static void Main()
        {
            string xmlData = @"<?xml version=""1.0"" encoding=""UTF-8""?>
                <nodes>
                    <node>
                        <id>1</id>
                    </node>
                    <node>
                        <id>2</id>
                        <dependency>1</dependency>
                    </node>
                    <node>
                        <id>3</id>
                        <dependency>2</dependency>
                    </node>
                    <node>
                        <id>4</id>
                    </node>
                    <node>
                        <id>5</id>
                        <dependency>4</dependency>
                    </node>
                    <node>
                        <id>6</id>
                        <dependency>2</dependency>
                        <dependency>5</dependency>
                    </node>
                </nodes>";

            // Notice how node 4 does not have any dependencies. So it is an independent node.

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlData);

            // Let's say we want to do a reverse traverse iteration of dependencies of node 6, so:
            // 6 -> 2 -> 1 and 5 -> 4. Output should be: 6, 2, 1, 5, 4

            Console.ReadKey();
        }
    }
}

Thanks!


Solution

  • You could deserialize the structure and then parse the object based on the Dependency Id number. For example, consider the following

    [XmlRoot(ElementName="node")]
    public class Node 
    {
            [XmlElement(ElementName="id")]
            public int Id { get; set; }
            [XmlElement(ElementName="dependency")]
            public List<int> Dependency { get; set; }
    }
    
    [XmlRoot(ElementName="nodes")]
    public class Nodes 
    {
            [XmlElement(ElementName="node")]
            public List<Node> Node { get; set; }
    }
    

    You could now deserilize your xml as

    var serializer = new XmlSerializer(typeof(Nodes));
    Nodes result;
    
    using (TextReader reader = new StringReader(xmlData))
    {
        result = (Nodes)serializer.Deserialize(reader);
    }
    

    With the parsed result, you could create a recursive method which would iterate over the Dependency list of the node.

    public IEnumerable<int> Parse(Nodes source,int Id)
    {
        var node = source.Node.First(x=>x.Id == Id);
        yield return node.Id;
        foreach(var d in node.Dependency)
        {
            foreach(var item in Parse(source,d))
                yield return item;
        }
        
    }
    

    You could now retrieve the desired result as

    var parseOrder = Parse(result,6);
    

    Demo Code