英文:
DescendantsUntil() in case of nested elements
问题
在我的上一个问题中:链接,
我学会了如何使用名为"DescendantsUntil()"的扩展方法来查找最顶层的< Member >元素(父级)及其最顶层的后代(子级)。
现在假设我们有更多的后代(父级、子级、侄子等等):
<?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>
使用DescendantsUntil()扩展方法,我可以轻松筛选< Member >父级和< Member >子级:
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();
现在,如何使用DescendantsUntil()来提取< Member >父级、子级、侄子等等元素,以及通常如何提取所有后代,只要还有另一个嵌套的元素存在?
英文:
In my previous question: link,
I learnt how to use extension method called "DescendantsUntil()" to find the topmost <Member> 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="&quot;3bool&quot;" 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="&quot;3bool&quot;" 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 <Member> parent and <Member> 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 <Member> elements, and in general, how to extract all descendants as long as there's another nested one?
答案1
得分: 0
这是你提供的代码的中文翻译:
尝试类似这样的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication52
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement xSections = doc.Descendants().Where(x => x.Name.LocalName == "Sections").FirstOrDefault();
XNamespace ns = xSections.GetDefaultNamespace();
Sections root = new Sections();
root.ParseSections(xSections, ns);
}
}
public class Sections
{
public List<Section> sections { get; set; }
public void ParseSections(XElement xSections, XNamespace ns)
{
List<XElement> sections = xSections.Elements(ns + "Section").ToList();
foreach (XElement section in sections)
{
if (this.sections == null) this.sections = new List<Section>();
Section childSection = new Section();
this.sections.Add(childSection);
childSection.ParseSection(section, ns);
}
}
}
public class Section
{
public string name { get; set; }
public List<Member> members { get; set; }
public void ParseSection(XElement xSection, XNamespace ns)
{
this.name = (string)xSection.Attribute("Name");
foreach (XElement xMember in xSection.Elements(ns + "Member"))
{
if (this.members == null) this.members = new List<Member>();
Member member = new Member();
this.members.Add(member);
member.ParseMember(xMember, ns);
}
}
}
public class Member
{
public string name { get; set; }
public string remanence { get; set; }
public string accessibility { get; set; }
public Dictionary<string, Boolean> attributes { get; set; }
public Sections sections { get; set; }
public void ParseMember(XElement member, XNamespace ns)
{
this.name = (string)member.Attribute("Name");
this.remanence = (string)member.Attribute("Remanence");
this.accessibility = (string)member.Attribute("Accessibility");
XElement attributeList = member.Element(ns + "AttributeList");
if (attributeList != null)
{
foreach (XElement attribute in attributeList.Descendants(ns + "BooleanAttribute"))
{
if (attributes == null) attributes = new Dictionary<string, bool>();
string attributeName = (string)attribute.Attribute("Name");
Boolean attributeValue = (Boolean)attribute;
attributes.Add(attributeName, attributeValue);
}
}
XElement xSections = member.Element(ns + "Sections");
if (xSections != null)
{
Sections childSections = new Sections();
this.sections = childSections;
childSections.ParseSections(xSections, ns);
}
}
}
}
请注意,代码中包含一些HTML实体编码,例如<
和"
,这些需要根据需要解码成正常的HTML字符。
英文:
Try code like this :
<!-- begin snippet: js hide: false console: true babel: false -->
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication52
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement xSections = doc.Descendants().Where(x => x.Name.LocalName == "Sections").FirstOrDefault();
XNamespace ns = xSections.GetDefaultNamespace();
Sections root = new Sections();
root.ParseSections(xSections, ns);
}
}
public class Sections
{
public List<Section> sections { get; set; }
public void ParseSections(XElement xSections, XNamespace ns)
{
List<XElement> sections = xSections.Elements(ns + "Section").ToList();
foreach (XElement section in sections)
{
if (this.sections == null) this.sections = new List<Section>();
Section childSection = new Section();
this.sections.Add(childSection);
childSection.ParseSection(section, ns);
}
}
}
public class Section
{
public string name { get; set; }
public List<Member> members { get; set; }
public void ParseSection(XElement xSection, XNamespace ns)
{
this.name = (string)xSection.Attribute("Name");
foreach (XElement xMember in xSection.Elements(ns + "Member"))
{
if (this.members == null) this.members = new List<Member>();
Member member = new Member();
this.members.Add(member);
member.ParseMember(xMember, ns);
}
}
}
public class Member
{
public string name { get; set; }
public string remanence { get; set; }
public string accessibility { get; set; }
public Dictionary<string, Boolean> attributes { get; set; }
public Sections sections { get; set; }
public void ParseMember(XElement member, XNamespace ns)
{
this.name = (string)member.Attribute("Name");
this.remanence = (string)member.Attribute("Remanence");
this.accessibility = (string)member.Attribute("Accessibility");
XElement attributeList = member.Element(ns + "AttributeList");
if (attributeList != null)
{
foreach (XElement attribute in attributeList.Descendants(ns + "BooleanAttribute"))
{
if (attributes == null) attributes = new Dictionary<string, bool>();
string attributeName = (string)attribute.Attribute("Name");
Boolean attributeValue = (Boolean)attribute;
attributes.Add(attributeName, attributeValue);
}
}
XElement xSections = member.Element(ns + "Sections");
if (xSections != null)
{
Sections childSections = new Sections();
this.sections = childSections;
childSections.ParseSections(xSections, ns);
}
}
}
}
<!-- end snippet -->
答案2
得分: 0
我自己找到了解决方法(也许对你有用)。
如果你想要使用扩展方法 "DescendantsUntil" 来查找更多的嵌套级别,只需要在 foreach 语句内部再次调用它,就像下面的工作代码一样:
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}\", {1}", 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"
如果有任何其他需要,请告诉我。
英文:
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"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论