2013-05-07 3 views
1

У меня есть следующий метод, который запрашивает XML-файл. Мне нужно, чтобы он возвращал информацию обо всех файлах, которые имеют элемент «Система», соответствующий переменной «sys», которую я передаю в свой метод.C# Linq to XML query возвращает только 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 выше содержит два совпадения «Система» 29, но моя программа только перенастраивает 1 из них - первый.

Метод, который вызывает выше и переходит в переменной «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"); 
        } 
+0

Эта строка, вероятно, является проблемой: где dm.Descendants («system»). First() .Value == sys, поскольку вы только запрашиваете элемент First(). – Ric

ответ

2

Как я могу видеть ваши функции возвращает только один элемент по дизайну , Вы пытаетесь выполнить запрос цикла, но оператор 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"); 
       } 
+0

Я думаю, что вы правы, но я не уверен, как реализовать ваше предложение. См. Редактирование на мой пост. Не могли бы вы рассказать мне, как и где я реализую ваше предложение в своем коде. Большое спасибо. – Daedalus

2

Вы хотите system который соответствует каждому из dataModule s, а не только первому.

Попробуйте это:

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

Как уже упоминалось в моем комментарии, удалить первый(), и вы должны быть хорошо:

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