C# 使用 linq 查找匹配两个元素级别的 xml 元素

标签 c# xml linq

我正在尝试从 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">

我想在图书馆“Main”中找到名为“test2”的阅读列表,这样我就可以将这个元素和所有子元素复制到另一个图书馆节点。

我更喜欢使用 linq 的解决方案,因为我正在尝试学习它。

在此先感谢您的帮助

当我添加一个新的“阅读列表”时,我是这样做的:

public void AddReadingList(string fullyQualifiedPath, Library lib, string name)
{
    XDocument xdoc = XDocument.Load(fullyQualifiedPath);

    XElement library = xdoc.Element("eStack").Elements("Library")
                .Single(x => x.Attribute("Name").Value == lib.Name);

    library.Add(new XElement("ReadingList", new XAttribute("Name", name)));

    xdoc.Save(fullyQualifiedPath);                        
}

但是我要执行的操作是复制这个元素和子元素。问题是,可能有多个同名的“图书馆”元素,所以我需要检查图书馆名称和阅读列表名称。那有意义吗?

最佳答案

结合使用 .DescendantsWhere 可以解决问题:

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 而不是 Descendants 我只是更喜欢使用它,所以不指定 app 的级别或任何其他沿途。


对于之前的 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();

关于C# 使用 linq 查找匹配两个元素级别的 xml 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39855965/

相关文章:

javascript - 从 Excel 导出 XML 并保持日期格式

java - 如何从applicationContext.xml中的bean读取值?

c# - LINQ 查询 - 根据具有与字符串匹配的属性的值选择键?

asp.net-mvc-3 - Linq 查询中的字符串扩展方法

c# - 配置系统在尝试连接到 Web 服务时初始化失败

c# - 显式布局类型中 bool 字段的语义 (ECMA-334)

c# - 使用 Linq 将数据分区到数组中

c# - c# vs2015 中的 c++ dll xml 文档注释

c# - 分页错误 :The method 'Skip' is only supported for sorted input in LINQ to Entities. 方法 'OrderBy' 必须在方法 'Skip' 之前调用

c# - 使用 Entity Framework 获取特定类型的实体返回错误 - LINQ to Entities 无法识别方法 'System.Type GetType()'