C# C使用linq查找匹配两个元素级别的xml元素
我试图从xml文档中选择一个XElement,并在xml文档的两个级别上进行匹配。我的文件结构是:C# C使用linq查找匹配两个元素级别的xml元素,c#,xml,linq,C#,Xml,Linq,我试图从xml文档中选择一个XElement,并在xml文档的两个级别上进行匹配。我的文件结构是: <app> <Library Name="Main" Path="C:\somefile.Xml"> <ReadingList Name="Test1"> <Book>... <ReadingList Name="Test2"> <Book>... <Library Nam
<app>
<Library Name="Main" Path="C:\somefile.Xml">
<ReadingList Name="Test1">
<Book>...
<ReadingList Name="Test2">
<Book>...
<Library Name="Backup" Path="C:\somefile.Xml">
但是我要执行的操作是这个元素和子元素的副本。问题是,可能有多个库元素具有相同的名称,因此我需要检查库名称和阅读列表名称。这有意义吗 使用.substands和where的组合将实现以下功能:
var result = XDocument.Load(fullyQualifiedPath)
.Descendants("Library")
//Can replace with `FirstOrDefault` if you know there is only one
.Where(element => element.Attribute("Name")?.Value == "Main")
.Descendants("ReadingList")
.Where(element => element.Attribute("Name")?.Value == "Test2").ToList();
你也可以使用.Elements而不是后代,我只是更喜欢使用它,这样就不会同时指定应用程序的级别或任何其他级别
对于先前的c 6.0,您可以执行以下操作:
var result = XDocument.Load("data.xml")
.Descendants("Library")
.Where(element =>
{
var att = element.Attribute("Name");
return att != null ? (att.Value == "Main" ? true : false) : false;
})
.Descendants("ReadingList")
//Make sure to do above change here too
.Where(element => element.Attribute("Name")?.Value == "Test2").ToList();
或者如果创建一个方法来帮助它,而不是重复代码:
Func<XElement, string, string> tryGetAttributeValue = (element, attributeName) =>
{
var attribute = element.Attribute(attributeName);
return attribute == null ? string.Empty : attribute.Value;
};
var result = XDocument.Load("data.xml")
.Descendants("Library")
.Where(element => tryGetAttributeValue(element,"Name") == "Main")
.Descendants("ReadingList")
.Where(element => tryGetAttributeValue(element, "Name") == "Test2").ToList();
你在找这样的东西吗
var table = XElement.Parse(@"<app>
<Library Name=""Main"" Path=""C:\somefile.Xml"">
<ReadingList Name=""Test1"">
<Book>Book1</Book>
</ReadingList>
<ReadingList Name=""Test2"">
<Book>Book2</Book>
</ReadingList>
</Library>
<Library Name=""Backup"" Path=""C:\somefile.Xml""></Library>
</app>");
var readingList = table
.Elements("Library")
.FirstOrDefault(x => x.Attribute("Name")?.Value == "Main")
.Elements("ReadingList")
.FirstOrDefault(x => x.Attribute("Name")?.Value == "Test2");
当然,选择一个后代变体将导致更少的查找
var readingList = table
.Descendants("Library")
.Where(x => x.Attribute("Name").Value == "Main")
.Descendants("ReadingList")
.Where(x => x.Attribute("Name").Value == "Test2")
.ToList();
您还可以执行以下查询:
var query= xdoc.Descendants("Library")
.Where(e=>e.Attribute("Name").Value=="Main")
.SelectMany(e=>e.Elements("ReadingList").Where(t=>t.Attribute("Name").Value=="Test2"));
如果只有一个主元素,也可以使用FirstOrDefault扩展方法:
var query= xdoc.Descendants("Library")
.FirstOrDefault(e=>e.Attribute("Name").Value=="Main")
.Descendants("ReadingList").Where(t=>t.Attribute("Name").Value=="Test2"));
你能和我们分享一下你的尝试吗?。不需要第二个子体/元素之前的运算符-它永远不会为null。如果没有找到,它将是一个可枚举的.EmptyTrue,我没有注意到。已修复。where语句中的值似乎不起作用。您确定这是正确的吗?我在两个.Where部分的.Value上都得到了一个无效的表达式项“.”。知道为什么吗?@cbutler-知道。你用的是什么c?我假设您在c 6.0之前,因此?。不起作用。是的,这就是问题所在。太棒了,谢谢!我真的很感谢你的帮助。您针对C 6.0之前版本的解决方案适合我。
var query= xdoc.Descendants("Library")
.Where(e=>e.Attribute("Name").Value=="Main")
.SelectMany(e=>e.Elements("ReadingList").Where(t=>t.Attribute("Name").Value=="Test2"));
var query= xdoc.Descendants("Library")
.FirstOrDefault(e=>e.Attribute("Name").Value=="Main")
.Descendants("ReadingList").Where(t=>t.Attribute("Name").Value=="Test2"));