簡體   English   中英

C#使用linq查找匹配兩個元素級別的xml元素

[英]C# find xml element matching two element levels using 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”,因此我可以將此元素和所有子元素復制到另一個Library節點。

我更喜歡使用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 s的組合可以解決這個問題:

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

你在找這樣的東西嗎?

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

這將從根本上解決你獲得的查詢ReadingList名為Test2和下ReadingList名為Test 1

您可以選擇Where而不是FirstOrDefault但最終會得到所有可能匹配的列表。

        var readingList = table
            .Elements("Library")
            .Where(x => x.Attribute("Name").Value == "Main")
            .Elements("ReadingList")
            .Where(x => x.Attribute("Name").Value == "Test2")
            .ToList(); 

選擇后代變體會導致較少的查找。

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

如果只有一個Main元素,您還可以使用FirstOrDefault擴展方法:

var query=  xdoc.Descendants("Library")
                .FirstOrDefault(e=>e.Attribute("Name").Value=="Main")
                .Descendants("ReadingList").Where(t=>t.Attribute("Name").Value=="Test2"));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM