0

(第一次发帖,请温柔!)

我只是在学习 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 处理似乎都是按文档顺序完成的——到目前为止,我所有的测试用例都已经完成。

我会提供赏金和/或赞成的答案,但没有足够的代表点数。我今天会决定一个答案,所以让他们进来!谢谢。

4

2 回答 2

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();

根据需要添加空检查。

于 2010-04-07T16:35:50.990 回答
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>元素,并与这些元素组成一个键值对。然后它按键对键值对进行分组,并且每个键只取第一个键值对

于 2010-04-07T16:38:16.667 回答