(第一次发帖,请温柔!)
我只是在学习 LINQ to XML 的所有荣耀和脆弱,试图破解它来做我想做的事:
给定这样的 XML 文件 -
<list>
<!-- random data, keys, values, etc.-->
<key>FIRST_WANTED_KEY</key>
<value>FIRST_WANTED_VALUE</value>
<key>SECOND_WANTED_KEY</key>
<value>SECOND_WANTED_VALUE</value> <!-- wanted because it's first -->
<key>SECOND_WANTED_KEY</key>
<value>UNWANTED_VALUE</value> <!-- not wanted because it's second -->
<!-- nonexistent <key>THIRD_WANTED_KEY</key> -->
<!-- nonexistent <value>THIRD_WANTED_VALUE</value> -->
<!-- more stuff-->
</list>
我想以稳健的方式提取一组已知“想要的键”的值,即如果SECOND_WANTED_KEY
出现两次,我只想要SECOND_WANTED_VALUE
,而不是UNWANTED_VALUE
。此外,THIRD_WANTED_KEY
可能会出现也可能不会出现,因此查询也应该能够处理它。我可以假设它FIRST_WANTED_KEY
会出现在其他键之前,但不能假设其他键的顺序 - 如果一个键出现两次,它的值并不重要,我只想要第一个。由字符串组成的匿名数据类型很好。
我的尝试集中在以下方面:
var z = from y in x.Descendants()
where y.Value == "FIRST_WANTED_KEY"
select new
{
first_wanted_value = ((XElement)y.NextNode).Value,
//...
}
我的问题是那应该是什么...
?例如,我尝试过(丑陋,我知道)
second_wanted_value = ((XElement)y.ElementsAfterSelf()
.Where(w => w.Value=="SECOND_WANTED_KEY")
.FirstOrDefault().NextNode).Value
这应该希望允许密钥在任何地方,或者不存在,但这还没有成功,因为.NextNode
在 nullXElement
上似乎不起作用。
我也尝试添加一个
.Select(t => {
if (t==null)
return new XElement("SECOND_WANTED_KEY","");
else return t;
})
在 where 之后的子句,但这也没有奏效。
我愿意接受建议、(建设性的)批评、链接、参考或向谷歌提供的短语建议等。我已经做了相当多的谷歌搜索和检查,所以任何帮助都将不胜感激。
谢谢!
编辑: 让我为此添加一层复杂性-我应该首先将其包括在内。假设 XML 文档如下所示:
<lists>
<list>
<!-- as above -->
</list>
<list>
<!-- as above -->
</list>
</lists>
我想提取多组这些键值对。问题/警告:如果SECOND_WANTED_KEY
没有出现在第一个<list>
元素中但出现在第二个元素中,我不想意外拾取第二个列表元素的SECOND_WANTED_KEY
.
编辑#2:
作为另一个想法,我尝试创建一个HashSet
我正在寻找的密钥并执行此操作:
HashSet<string> wantedKeys = new HashSet<string>();
wantedKeys.Add("FIRST_WANTED_KEY");
//...add more keys here
var kvp = from a in x.Descendants().Where(a => wantedKeys.Contains(a.Value))
select new KeyValuePair<string,string>(a.value,
((XElement)a.NextNode).Value);
这让我得到了所有的键值对,但我不确定它是否能保证我会正确地将这些对“关联”到它们的父 `' 元素。这两种方法之间的任何想法或比较都会有所帮助。
状态更新 2010 年 4 月 9 日
截至目前,我仍然主要认为哈希集方法是最优选的。.NET 完成的大部分 XML 处理似乎都是按文档顺序完成的——到目前为止,我所有的测试用例都已经完成。
我会提供赏金和/或赞成的答案,但没有足够的代表点数。我今天会决定一个答案,所以让他们进来!谢谢。