2013-05-07 2 views
1

XML 파일을 쿼리하는 다음과 같은 방법이 있습니다. 내 시스템에 전달하는 'sys'변수와 일치하는 "System"요소가있는 모든 파일에 대한 정보를 반환해야합니다.C# Linq to XML 쿼리 만 1 결과를 반환합니다.

XML 파일에 일치하는 항목이 2 개 이상있는 경우 1 개의 결과 만 반환합니다.

마치 내 Linq 쿼리가 결과를 찾을 때까지 XML 파일을 trhough로 이동하는 것과 같습니다. 반면에 모든 일치 항목을 수집해야합니다.

<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)의 값에 전달할 수 있습니다
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 파일의 샘플입니다. 위의 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; 
     } 

및 위의 호출 방법의 추출물 당신은 system을 원하는

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

입니다 첫 번째 항목이 아닌 dataModule 각각에 해당하는 항목입니다. 첫 번째 (제거, 내 댓글에서 언급 한 바와 같이

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;