Получение нескольких элементов XML с помощью LINQ по атрибутам - PullRequest
1 голос
/ 28 марта 2011

Учитывая этот XML:

<?xml version="1.0" encoding="utf-8" ?>
<queryableData>
  <table displayName="Shipments" dbName="Quotes">
    <foreignKey column="CustomerId" references="CustomerRegistration"/>
    <foreignKey column="QuoteStatusId" references="QuoteStatus"/>
    <fields>
      <field displayName="Quote Charge" dbColumn="QuoteCharge" type="Number"/>
      <field displayName="Total Weight" dbColumn="TotalWeight" type="Number"/>
    </fields>
  </table>
  <table displayName="Customers" dbName="CustomerRegistration">
    <fields>
      <field displayName="First Name" dbColumn="FirstName" type="Text" />
      <field displayName="Last Name" dbColumn="LastName" type="Text"/>
    </fields>
  </table>
</queryableData>

Я хочу получить список анонимных типов объектов, содержащих поля DisplayName, DbColumn и Type только для таблицы "Quotes".

IЯ могу получить список обеих таблиц со следующим кодом LINQ to XML:

    var xml = XElement.Load(@"C:\Sandbox\queryable.xml");

    // Tables
    var tables = from el in xml.Elements("table")
                        select new 
                        {
                            Text = el.Attribute("displayName").Value,
                            Value = el.Attribute("dbName").Value
                        };

Но я не уверен, как получить значение поля, где атрибут dbName элемента таблицы равен "Котировки".Самое близкое, что я получил, - это список, содержащий список значений, а не список анонимных объектов с одним элементом, имеющим пару dbColumn / displayName:

var columns = from el in xml.Elements("table")
            where el.Attribute("dbName").Value.Equals("Quotes")
            select new LookupData { 
                Text = el.Elements("fields").Elements("field").Attributes().Where(x => x.Name == "displayName").Select(x => x.Value),
                Value = el.Elements("fields").Elements("field").Attributes().Where(x => x.Name == "dbColumn").Select(x => x.Value)
            };

, поэтому я ожидаю этого в списке:

LookupData # 1

Текст: "Quote Charge"

Значение: "QuoteCharge"

LookupData # 2

Текст: «Общий вес»

Значение: «Общий вес»

, и я получаю это вместо:

LookupData #1

Текст: список, содержащий две строки: [0] = "Стоимость цитаты", [1] = "Общий вес"

Значение: Список, содержащий две строки: [0]= "QuoteCharge", [1] = "TotalWeight"

1 Ответ

1 голос
/ 28 марта 2011

используйте это:

var result = xml.Elements("table").
    Where(el => el.Attribute("dbName").Value.Equals("Quotes")). // 1
    SelectMany(el => el.Elements("fields").Elements("field")).  // 2
    Select(f => new 
                {
                    Text = f.Attributes().Where(x => x.Name == "displayName").
                        Select(x => x.Value).FirstOrDefault(),
                    Value = f.Attributes().Where(x => x.Name == "dbColumn").
                        Select(x => x.Value).FirstOrDefault()
                }
           ) // 3
;

Объяснение:

  1. Мы выбираем элементы, где dbName == "Quotes"
  2. Из каждого из этих элементов мы выбираем все field элементов и сгладить результат с использованием SelectMany.Результатом будет IEnumerable<XElement>.
  3. . Для каждого поля мы выбираем анонимный тип со свойством Text, для которого установлено значение первого атрибута с именем "displayName", а для свойства Value - значениезначение первого атрибута с именем "dbColumn"

Проблема с вашим подходом была в основном в том, что вы поместили шаг 2 в создание анонимного типа.Или другими словами: вы создали один экземпляр анонимного типа для каждого элемента «Quotes», а не для каждого элемента «field».

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