Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C使用linq查找匹配两个元素级别的xml元素_C#_Xml_Linq - Fatal编程技术网

C# C使用linq查找匹配两个元素级别的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

我试图从xml文档中选择一个XElement,并在xml文档的两个级别上进行匹配。我的文件结构是:

<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"));