In my previous question: link,
I learnt how to use extension method called "DescendantsUntil()" to find the topmost elements (Parent) and their topmost descendants (Children).
Let's suppose now to have more descendants (Parent, Children, Nephews and so on..):
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Interface>
<Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v4">
<Section Name="Static">
<Member Name="3bool1" Datatype=""3bool"" Remanence="NonRetain" Accessibility="Public">
<AttributeList>
<BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute>
<BooleanAttribute Name="ExternalVisible" SystemDefined="true">true</BooleanAttribute>
<BooleanAttribute Name="ExternalWritable" SystemDefined="true">true</BooleanAttribute>
<BooleanAttribute Name="SetPoint" SystemDefined="true">false</BooleanAttribute>
</AttributeList>
<Sections>
<Section Name="None">
<Member Name="bool1" Datatype="Bool" />
<Member Name="bool2" Datatype="Bool" />
<Member Name="bool3" Datatype="Bool" />
<Member Name="3bool1" Datatype=""3bool"" Remanence="NonRetain" Accessibility="Public">
<AttributeList>
<BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute>
<BooleanAttribute Name="ExternalVisible" SystemDefined="true">true</BooleanAttribute>
<BooleanAttribute Name="ExternalWritable" SystemDefined="true">true</BooleanAttribute>
<BooleanAttribute Name="SetPoint" SystemDefined="true">false</BooleanAttribute>
</AttributeList>
<Sections>
<Section Name="None">
<Member Name="bool1" Datatype="Bool" />
<Member Name="bool2" Datatype="Bool" />
<Member Name="bool3" Datatype="Bool" />
</Section>
</Sections>
</Member>
</Section>
</Sections>
</Member>
<Member Name="int7" Datatype="Int" Remanence="NonRetain" Accessibility="Public">
<AttributeList>
<BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute>
<BooleanAttribute Name="ExternalVisible" SystemDefined="true">true</BooleanAttribute>
<BooleanAttribute Name="ExternalWritable" SystemDefined="true">true</BooleanAttribute>
<BooleanAttribute Name="SetPoint" SystemDefined="true">true</BooleanAttribute>
</AttributeList>
</Member>
</Section>
</Sections>
</Interface>
</Document>
By using DescendantsUntil() extension method, I can easily filter parent and children
string path = ("C:\\Users\\");
XDocument doc = XDocument.Load(path + "File.xml");
XNamespace ns = "http://www.siemens.com/automation/Openness/SW/Interface/v4";
XName name = ns + "Member";
var memb = doc
.Root.DescendantsUntil(e => e.Name == name)
.Select(e => (Parent: e, Children: e.DescendantsUntil(c => c.Name == name).ToList()))
//.Where(i => i.Children.Count > 0); // Uncomment to filter out <Member> elements with no child members.
.ToList();
Now, how can I use DescendantsUntil() to extract Parent, Children, Nephews elements, and in general, how to extract all descendants as long as there's another nested one?
I found the solution by myself (maybe it might be useful for you).
If you want to use the extension method "DescendantsUntil" to find more nested levels, you just have to call it again inside the foreach statement, like the following working code:
var memb_L0 = doc
.Root.DescendantsUntil(e => e.Name == name)
.Select(e => (Parent: e, Children: e.DescendantsUntil(c => c.Name == name).ToList()))
//.Where(i => i.Children.Count > 0); // Uncomment to filter out <Member> elements with no child members.
.ToList();
foreach (var ele in memb_L0)
{
Console.WriteLine("Parent: \"{0}\", ", ele.Parent.Attribute("Name")?.Value);
var memb_L1 = ele.Parent.DescendantsUntil(e => e.Name == name).Select(e => (Children: e, Nephew: e.DescendantsUntil(c => c.Name == name).ToList())).ToList();
memb_L1.ForEach(i => Console.WriteLine("Children: \"{0}\", Nephews: {1}",
i.Children.Attribute("Name")?.Value,
i.Nephew.Count == 0
? "None" :
string.Join(",",
i.Nephew.Select(c => $"\"{c.Attribute("Name")?.Value}\""))));
}
Here's the output:
Parent: "3bool1",
Children: "bool1", Nephews: None
Children: "bool2", Nephews: None
Children: "bool3", Nephews: None
Children: "3bool1", Nephews: "bool1","bool2","bool3"
Parent: "int7"