(首先,请温柔!)
我正在学习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
上的XElement
似乎不起作用。
我也尝试添加
.Select(t => {
if (t==null)
return new XElement("SECOND_WANTED_KEY","");
else return t;
})
子句在where之后,但是也没有用。
我愿意接受建议,(建设性的)批评,链接,参考或谷歌的短语建议等等。我已经公平分享了谷歌搜索和检查SO,所以任何帮助将不胜感激。
谢谢!
修改 让我为此添加一层复杂性 - 我应该首先将其包括在内。假设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);
这让我获得了所有的键值对,但我不确定它是否能保证我将这些对与其父元素“正确”关联起来。这两种方法之间的任何想法或比较都会有所帮助。
状态更新4/9/10
截至目前,我仍然主要认为散列集方法是最受欢迎的。似乎.NET完成的大多数XML处理都是按文档顺序完成的 - 到目前为止,我的所有测试用例都已经完成了。
我会提供赏金和/或upvote答案,但没有足够的代表点。今天我会给你答案,所以请他们进去!感谢。
答案 0 :(得分:0)
这会获得包含<value>
的第一个<key>
元素后的第一个"SECOND_WANTED_KEY"
元素的值:
XDocument doc;
string result = (string)doc.Root
.Elements("key")
.First(node => (string)node == "SECOND_WANTED_KEY")
.ElementsAfterSelf("value")
.First();
根据需要添加空检查。
答案 1 :(得分:0)
XDocument doc = ...
var wantedKeyValuePairs =
from keyElement in doc.Root.Elements("key")
let valueElement = keyElement.ElementsAfterSelf("value").First()
select new { Key = keyElement.Value, Value = valueElement.Value } into kvp
group kvp by kvp.Key into g
select g.First();
说明:此查询获取每个<key>
元素及其后续<value>
元素,并使用这些元素创建键值对。然后,它按键对键值对进行分组,并仅为每个键