c# Linq到XML查询只返回1个结果

本文关键字:返回 1个 结果 查询 Linq XML | 更新日期: 2023-09-27 18:12:29

我有以下查询XML文件的方法。我需要它来返回所有文件的信息,这些文件的"System"元素与我传递给我的方法的"sys"变量相匹配。

它工作正常,但只返回1个结果,当我知道有超过1个匹配在XML文件。

这就好像我的Linq查询只是通过XML文件,直到它找到一个结果,然后停止,而我需要它来获得所有匹配的集合。

public ListViewItem getDMcollection(string sys)
        {
            XDocument doc = XDocument.Load(Form1.CSDBpath + Form1.projectName + "''Data.xml");
            var dms = from dm in doc.Descendants("dataModule")
                      where dm.Descendants("system").First().Value == sys
                      select dm;
            foreach (var module in dms)
            {
                    ListViewItem item = new ListViewItem(new string[]
                {
                         module.Element("DMC").Value,
                         module.Element("techName").Value,
                         module.Element("infoName").Value,
                         module.Element("status").Value,
                         module.Element("currentUser").Value,
                         module.Element("validator").Value,
                         module.Element("notes").Value,
                         //dm.Element("size").Value + " kb",
                         //dm.Element("dateMod").Value
                 });
                    return item;
                }
                return null;
        }

这是一个XML文件的示例:

<DMs>
  <dataModule>
    <DMC>DMC-AJ-A-29-13-54-00ZZZ-254Z-B_001-00.XML</DMC>
    <techName>Pressure switch</techName>
    <infoName>Clean mechanically</infoName>
    <system>72</system>
    <subsystem>13</subsystem>
    <subsubsystem>60</subsubsystem>
    <status>Checked Out</status>
    <notes>-</notes>
    <currentUser>JakeMemery</currentUser>
    <validator>-</validator>
    <dateMod>-</dateMod>
    <size>-</size>
  </dataModule>
  <dataModule>
    <DMC>DMC-AJ-A-30-15-62-00AAA-066A-D_001-00.XML</DMC>
    <techName>Pressure switch</techName>
    <infoName>Support equipment and tools data</infoName>
    <system>29</system>
    <subsystem>13</subsystem>
    <subsubsystem>54</subsubsystem>
    <status>Checked In</status>
    <notes>-</notes>
    <currentUser>-</currentUser>
    <validator>-</validator>
    <dateMod>-</dateMod>
    <size>-</size>
  </dataModule>
  <dataModule>
    <DMC>DMC-AJ-A-45-60-12-00AAA-420A-B_001-00.XML</DMC>
    <techName>Pressure switch</techName>
    <infoName>General fault isolation procedure</infoName>
    <system>29</system>
    <subsystem>20</subsystem>
    <subsubsystem>10</subsubsystem>
    <status>Checked In</status>
    <notes>-</notes>
    <currentUser>-</currentUser>
    <validator>-</validator>
    <dateMod>-</dateMod>
    <size>-</size>
  </dataModule>
</DMs>

作为一个例子,我可以将值29传递给我的方法。正如您所看到的,上面的XML文件包含两个'System' 29匹配,但是我的程序只返回其中的一个——第一个。

调用上述方法并传入'sys'变量的方法如下:

public ListViewItem splitSNS(string fullSNSpath)
        {
            string sns = new String(fullSNSpath.ToCharArray().Where(c => Char.IsDigit(c)).ToArray());
            if (sns.Length.ToString() == "6")
            {
                string sys = sns.Substring(4, 2);
                string subsys = sns.Substring(2, 2);
                string unit = sns.Substring(0, 2);
               ListViewItem dms = getDMcollection(sys, subsys, unit);
               return dms;
            }
            else if (sns.Length.ToString() == "4")
            {
                string sys = sns.Substring(2, 2);
                string subsys = sns.Substring(0, 2);
                ListViewItem dms = getDMcollection(sys, subsys);
                return dms;
            }
            else if (sns.Length.ToString() == "2")
            {
                string sys = sns.Substring(0, 2);
                ListViewItem dms = getDMcollection(sys);
                return dms;
            }
            return null;  
        }

和调用上述方法的一个提取是

 ListViewItem dms = newFilter.splitSNS(fullSNSpath);
                    if (dms != null)
                    {
                       // showfilteredList(dms);
                        listView1.Items.Add(dms);
                        showStatus(dms);
                    }
                    else
                    {
                        MessageBox.Show("There are no DMs to be displayed");
                    }

c# Linq到XML查询只返回1个结果

正如我在评论中提到的,删除First(),你应该没事:

var dms = from dm in doc.Descendants("dataModule")
                  where dm.Element("system").Value == sys
                  select dm;

我可以看到你的函数只返回一个元素的设计。您尝试遍历查询,但return item;语句将始终返回查询中的第一个元素。也许你需要改变它的返回类型为IEnumerable<ListViewItem>,并将return item;替换为yield return item; ?

对于您的情况,我建议对getDMcollection功能进行以下更改:

public IEnumerable<ListViewItem> getDMcollection(string sys)
{    
    XDocument doc = XDocument.Load(Form1.CSDBpath + Form1.projectName + "''Data.xml");
    var dms = from dm in doc.Descendants("dataModule")
              where dm.Descendants("system").First().Value == sys
              select dm;
    foreach (var module in dms)
    {
        ListViewItem item = new ListViewItem(new string[]
        {
            module.Element("DMC").Value,
            module.Element("techName").Value,
            module.Element("infoName").Value,
            module.Element("status").Value,
            module.Element("currentUser").Value,
            module.Element("validator").Value,
            module.Element("notes").Value,
            //dm.Element("size").Value + " kb",
            //dm.Element("dateMod").Value
        });
        yield return item;    
    }
}

当你调用它时,你应该迭代它的结果,将它们添加到列表框

public IEnumerable<ListViewItem> splitSNS(string fullSNSpath)
    {
        string sns = new String(fullSNSpath.ToCharArray().Where(c => Char.IsDigit(c)).ToArray());
        if (sns.Length.ToString() == "6")
        {
            string sys = sns.Substring(4, 2);
            string subsys = sns.Substring(2, 2);
            string unit = sns.Substring(0, 2);
           IEnumerable<ListViewItem> dms = getDMcollection(sys, subsys, unit);
           foreach(var d in dms)
               yield return d;
        }
        else if (sns.Length.ToString() == "4")
        {
            string sys = sns.Substring(2, 2);
            string subsys = sns.Substring(0, 2);
           IEnumerable<ListViewItem> dms = getDMcollection(sys, subsys);
           foreach(var d in dms)
               yield return d;
        }
        else if (sns.Length.ToString() == "2")
        {
            string sys = sns.Substring(0, 2);
           IEnumerable<ListViewItem> dms = getDMcollection(sys);
           foreach(var d in dms)
               yield return d;
        }
    }

最后……

IEnumerable<ListViewItem> dms = newFilter.splitSNS(fullSNSpath);
                if (dms.Any())
                {
                   // showfilteredList(dms);
                   foreach(var d in dms)
                        listView1.Items.Add(d);
                    showStatus(dms);
                }
                else
                {
                    MessageBox.Show("There are no DMs to be displayed");
                }

您希望system项对应于每个dataModule项,而不仅仅是第一个。

试试这个:

var dms = from dm in doc.Descendants("dataModule")
                  where dm.Element("system").Value == sys
                  select dm;