Как использовать запрос LINQ для получения значений XElement, когда XElements имеют одинаковое имя - PullRequest
8 голосов
/ 21 мая 2009

У меня есть кусок 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

Ответы [ 10 ]

10 голосов
/ 22 мая 2009

Хотелось бы что-нибудь подобное?

var a = from record in table.Elements("Record")
    select new
    {
        one = (string)record.Elements().ElementAt(0),
        two = (string)record.Elements().ElementAt(1)
    };
3 голосов
/ 22 мая 2009

Звучит так, будто вы хотите денормализовать поле, чтобы оно поместилось в 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 голос
/ 12 ноября 2013

Может быть, это?

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


}
1 голос
/ 10 ноября 2010

Я не понимаю, в чем проблема и почему некоторые из этих ответов выглядят такими сложными: - / Вот мое предложение:

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

// => IEnumerable<IEnumerable<string>>

Внутренний IEnumerable предназначен для столбцов, а внешний - для строк. (Вопрос несколько сбивает с толку, потому что нет IEnumerable<T,T'>, выше - моя адаптация намерения.)

Вы можете сделать внутренний IEnumerable в строку (например, Join on ","), но не очень интересно помещать в сетку, если вы подразумеваете значения в виде столбцов!

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 и ниже.

0 голосов
/ 13 апреля 2010

var detail1 = из d в 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 голосов
/ 22 мая 2009

Будет

IEnumerable<List<string>>

работа? (не уверен, как заставить это отображать inline)

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 голосов
/ 22 мая 2009

Э-э ... Я думаю, что вы используете неправильную парадигму LINQ для этой проблемы. Вы должны использовать LINQ to XML, который может немного отличаться от ожидаемого.

Проверьте эту ссылку:

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

Это объясняется на примере структуры, аналогичном приведенному вами.

0 голосов
/ 22 мая 2009

Вам нужны 2-х шаговые процессы:

Аннотируйте записи (вместо атрибутов), а затем Перечислите поля и передайте значения в анонимный класс для привязки, например:

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 голосов
/ 22 мая 2009

Я могу быть далеко в том, что вы ищете, но вы ищете что-то вроде этого?

        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 голосов
/ 21 мая 2009

Вы можете связывать звонки с 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;

Однако это вернет все элементы в

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...