如何使用LINQ查询在XElements具有相同名称时获取XElement值

9

我有一个以下格式的xml片段:

<Table>
  <Record>
    <Field>Value1_1</Field>
    <Field>Value1_2</Field>
  </Record>
  <Record>
    <Field>Value2_1</Field>
    <Field>Value2_2</Field>
  </Record>
</Table>

我希望能够得到一个LINQ查询,生成一个IEnumerable对象,以便我可以将其分配为DataGrid的数据源。目前我的代码如下:

var temp = from record in table.Elements("Record")
            select record.Element("Field").Value

我遇到的难题是可以创建多个字段元素。

在上面的例子中,我需要的是类似于 IEnumerable<string,string> 的东西。 数据表格应该长这样:

Value1_1, Value1_2
Value2_1, Value2_2

XML有点奇怪,我们能否假设记录中的每个字段元素实际上都有一个唯一的名称。它们肯定不都叫做“Field”,对吧? - AnthonyWJones
你期望的行为是什么?即假设有多个Field元素,你想要哪一个? - dso
XML确实很奇怪,但不幸的是我被卡在里面了。 - JohnC
DSO,我已经更新了问题并提供了预期行为。 - JohnC
也许您需要使用有效的类型更新问题 -- IEnumerable<string,string> 不是它。我在我的答案中使用了 IEnumerable<IEnumerable<string>>,但也许您想要 string[,]string[][]MyRows<MyColumns> 等等。 - user166390
10个回答

11

这样的做法有帮助吗?

var a = from record in table.Elements("Record")
    select new
    {
        one = (string)record.Elements().ElementAt(0),
        two = (string)record.Elements().ElementAt(1)
    };

同意 - 我认为这是他唯一的选择,因为它们的顺序很重要。通过在空的Elements()调用中加入“Field”,可能会使其更好(更精确)。 - TheSoftwareJedi
当我在搜索中遇到这个问题时,您提供的正是我所需要的。由于看起来提问者不打算接受,所以我创建了悬赏以奖励您。 - Jason Goemaat

4

看起来你想将该字段去规范化,以便在数据网格中适应1个列。

下面的内容是否有帮助?

var table = XElement.Parse(@"<Table>
                                <Record><Field>Value1_1</Field><Field>Value1_2</Field></Record>
                                <Record><Field>Value2_1</Field><Field>Value2_2</Field></Record>
                             </Table>");


var temp = from record in table.Elements("Record")
           from field in record.Elements("Field")
           group field.Value by record into groupedFields
           select groupedFields.Aggregate((l, r) => l + ", " + r);

foreach (var row in temp)
    Console.WriteLine(row);

Console.ReadKey();

免责声明:我现在不怎么使用SQL或LINQ,所以这个可能可以做得更好。随意更改。


1

我不明白问题在哪里,也不知道为什么这些答案看起来那么复杂 :-/ 这是我的建议:

var r = (from record in table.Elements("Record")
         select (from element in record.Elements("Field")
                 select element.Value));

// => IEnumerable<IEnumerable<string>>

内部的IEnumerable用于列,外部的IEnumerable用于行。(问题有点混乱,因为没有,上面是我对意图的适应。)

你可以将内部的IEnumerable转换为字符串(例如,在“,”上连接),但如果你想将值作为列放入网格中,那就不太好玩了!

var r = (from record in table.Elements("Record")
         select String.Join(", ",
             record.Elements("Field").Select(f => f.Value).ToArray());

// => IEnumerable<string>

如果我真的了解LINQ表达式,上面的代码可能会更好。但是它能够工作并覆盖了“其他”情况——“ToArray”适用于.NET 3.5及以下版本。


1
也许是这个吗?
using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Diagnostics;

[TestMethod]
    public void Linq_XElement_Test()
    {


    string xml = @"<Table>
  <Record>
    <Field>Value1_1</Field>
    <Field>Value1_2</Field>
  </Record>
  <Record>
    <Field>Value2_1</Field>
    <Field>Value2_2</Field>
  </Record>
</Table>";

    XElement elements = XElement.Parse(xml);

    var qryRecords = from record in elements.Elements("Record")
                  select record;

    foreach (var rec in qryRecords)
    {
        Debug.WriteLine(rec.Value);
    }

    var qryFields = from record in elements.Elements("Record")
                 from fields in record.Elements("Field")
                 select fields;

    foreach (var fil in qryFields)
    {
        Debug.WriteLine(fil.Value);
    }

    IEnumerable<string> list = qryFields.Select(x => x.Value);

    foreach (string item in list)
    {
        Debug.WriteLine(item);
    }


}

请说明您发布的代码解决问题的方法。您的代码可能有所帮助,但是说明它的作用可以帮助其他人理解和学习。 - Joel

0

var detail1 = from d in ds.tbl_Looking_Fors where d.Profile_ID == id select d.Looking_For ;

变量detail1 = 来自ds.tbl_Looking_Fors的查询结果,其中d.Profile_ID等于id,选择d.Looking_For;

            string[] datum = detail1.ToArray();
            if (datum != null && datum.Length > 0)
            {
                foreach (var row in datum)
                {
                    Label6.Text = datum[0]+" , "+datum[1];
                }

            }

0
您可以链接调用Elements():
var temp = from field in table.Elements("Record").Elements("Field")
           select field.Value;

你也可以使用Descendants()

 var temp = from field in table.Descendants("Field")
            select field.Value;

然而,这将返回<Table>下的所有<Field>元素,即使它们不在<Record>元素内。


0

我可能完全不了解你所寻找的内容,但是你是否在寻找类似于这样的东西?

        DataSet ds = new DataSet("Records DS");
        ds.Tables.Add("Records");
        foreach (XElement record in table.Descendants("Record"))
        {
            var temp = from r in record.Descendants("Field")
                       select r.Value;

            string[] datum = temp.ToArray();
            if (datum != null
                && datum.Length > 0)
            {
                foreach (string s in datum)
                    ds.Tables[0].Columns.Add();
                DataRow row = ds.Tables[0].NewRow();
                row.ItemArray = datum;
                ds.Tables[0].Rows.Add(row);
            }
        }

然后返回ds并将DataMember设置为"Records"


0

你需要一个两步骤的过程:

注释记录(而不是属性),然后枚举字段并将值传递到匿名类中进行绑定,如下所示:

string xml = [string-goes-here];

  XElement elem = XElement.Parse(xml);

  int count= 0;
  foreach(XElement recordElems in elem.Elements("Record")){
    recordElems.SetAttributeValue("id", count);
    count++;
  }
  var temp = from record in elem.Elements("Record")
             from field in record.Elements("Field")
             select new { Record = "Record " + record.Attribute("id").Value, Field = field.Value };

  foreach (var item in temp)
  {
    Console.WriteLine("{0}: {1}", item.Record, item.Field);
  }
}

0

一个

IEnumerable<List<string>>

工作?(不确定如何将其显示为内联)

var recordList = from record in data.Elements("record") select record;
List<List<string>> x = new List<List<string>>(recordList.Count());
foreach (var record in recordList)
{
  var z = from field in record.Elements("field") select field.Value;
  x.Add(z.ToList());
}
return x.AsEnumerable();

不知道那是否适用于你的特定情况。


0

嗯...我认为你在这个问题上使用了错误的LINQ范例。你应该使用LINQ to XML,它可能与你预期的略有不同。

查看此链接:

http://msdn.microsoft.com/en-us/library/bb308960.aspx

它使用一个结构相似的例子来解释你提出的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接