I just adapted code from this answer to be a generic tree builder, and what I came up with works, however, I ended up introducing a Tuple to make it work. I am pretty sure it can be written more straight forwardly, but I am having trouble seeing it..
The fundamental reason I introduced the Tuple was because at the time I'm iterating the children, I have not yet converted those children into Tree Nodes yet.. did I create this issue with my approach or is it intrinsic to the problem I'm solving with the code?
Here's the usage followed by the tree builder:
// USAGE
var document = DocumentModel.Load(@"Part CareAlerts Page 1 Part 1.docx", LoadOptions.DocxDefault);
var tree = BuildTree<Element, Node>(
document,
elt => elt.GetChildElements(false),
elt => new Node(elt.ElementType.ToString()) {Content = elt.Content.ToString().Trim()},
(parent, child) => parent.Children.Add(child));
// TREE BUILDER FUNCTION
public static TNode BuildTree<TIn, TNode>(TIn root, Func<TIn, IEnumerable<TIn>> childSelector,
Func<TIn, TNode> createNode, Action<TNode, TNode> connectNodes)
where TIn : class
where TNode : class
{
var stack = new Stack<Tuple<TNode, TIn>>(new[] {Tuple.Create(default(TNode), root)});
TNode tree = null;
while (stack.Any())
{
var next = stack.Pop();
var result = createNode(next.Item2);
if (tree == null)
{
tree = result;
}
if (next.Item1 != null)
{
connectNodes(next.Item1, result);
}
foreach (var child in childSelector(next.Item2).Reverse())
{
stack.Push(Tuple.Create(result, child));
}
}
return tree;
}