[英]C# Linq to XML query only returning 1 result
I have the following method which queries an XML file. 我有以下查询XML文件的方法。 I need it to return the information on ALL files which have the "System" element matching the 'sys' variable which i pass into my method. 我需要它返回所有文件的信息,这些文件具有与“ sys”变量匹配的“ System”元素,该变量已传递给我的方法。
It works OK, but only returns 1 result, when i know that there is more than 1 match in the XML file. 它工作正常,但当我知道XML文件中有多个匹配项时,仅返回1个结果。
It's as if my Linq query just goes trhough the XML file until it finds a result then stops, whereas i need it to get a collection of ALL matches. 好像我的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;
}
This is a sample of the XML file: 这是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>
So as an example, i might pass in the value of 29 to my method. 因此,例如,我可能将29的值传递给我的方法。 And as you can see the XML file above contains two 'System' 29 matches, but my program only retuns 1 of them - the first one. 正如您所看到的,上面的XML文件包含两个“系统” 29个匹配项,但是我的程序仅将它们之一调优-第一个。
The method that calls the above and passes in the 'sys' variable is this: 调用上述方法并传递'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;
}
and an extract of the method which calls the above is 调用上面方法的摘录是
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");
}
As mentioned in my comment, remove the First() and you should be fine: 如我的评论中所述,删除First(),您应该可以:
var dms = from dm in doc.Descendants("dataModule")
where dm.Element("system").Value == sys
select dm;
You want the system
item that corresponds to each of the dataModule
s, not just the first one. 您需要与每个dataModule
相对应的system
项,而不仅仅是第一个。
Try this: 尝试这个:
var dms = from dm in doc.Descendants("dataModule")
where dm.Element("system").Value == sys
select dm;
As I can see your function returns only one element by design. 如我所见,您的函数在设计上仅返回一个元素。 You try to loop trough query but return item;
您尝试循环查询低谷但return item;
statement will always return first element in the query. 语句将始终返回查询中的第一个元素。 Maybe you need to change it's return type to IEnumerable<ListViewItem>
and replace return item;
也许您需要将其返回类型更改为IEnumerable<ListViewItem>
并替换return item;
to yield return item;
yield return item;
for example? 例如?
For your case I would suggest the following change for getDMcollection
function: 对于您的情况,我建议对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;
}
}
when you call to it, you should iterate it's result to add them to list box 调用它时,应迭代将其添加到列表框中的结果
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;
}
}
And finally... 最后...
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");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.