Как я могу получить все "свойства" из XML через LINQ для XML - PullRequest
5 голосов
/ 24 февраля 2010

Пример XML ( исходная ссылка ):

<records>
  <record index="1">
    <property name="Username">Sven</property>
    <property name="Domain">infinity2</property>
    <property name="LastLogon">12/15/2009</property>
  </record>
  <record index="2">
    <property name="Username">Josephine</property>
    <property name="Domain">infinity3</property>
    <property name="LastLogon">01/02/2010</property>
  </record>
  <record index="3">
    <property name="Username">Frankie</property>
    <property name="Domain">wk-infinity9</property>
    <property name="LastLogon">10/02/2009</property>
  </record>
</records>

Я хочу получить экземпляр класса для каждой записи в XML.

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

foreach(Record rec in myVar)
{
Console.WriteLine("ID: {0} User:{1} Domain:{2} LastLogon:{3}",rec.Index, rec.Username, rec.Domain, rec.LastLogon);
}

1 Ответ

3 голосов
/ 24 февраля 2010

РЕДАКТИРОВАТЬ: обновленный код с ToDictionary подход для ясности и эффективности.

Вы можете попробовать следующий пример.Если вы удалите Record из строки select new Record, это приведет к анонимному типу и будет работать.Ваш класс Record должен иметь конструктор по умолчанию без параметров, чтобы использовать инициализатор объекта, если вы предоставили другие конструкторы (он также будет работать, если у вас нет конструкторов).В противном случае вы можете использовать доступные конструкторы вместо инициализатора объекта.

Обратите внимание, что использование Single() и Value предполагает, что XML правильно сформирован без каких-либо пропущенных элементов.

var xml = XElement.Parse(@"<records>
 <record index=""1"">
   <property name=""Username"">Sven</property>
   <property name=""Domain"">infinity2</property>
   <property name=""LastLogon"">12/15/2009</property>
 </record>
 <record index=""2"">
   <property name=""Username"">Josephine</property>
   <property name=""Domain"">infinity3</property>
   <property name=""LastLogon"">01/02/2010</property>
 </record>
 <record index=""3"">
   <property name=""Username"">Frankie</property>
   <property name=""Domain"">wk-infinity9</property>
   <property name=""LastLogon"">10/02/2009</property>
 </record>
</records>");

var query = from record in xml.Elements("record")
        let properties = record.Elements("property")
                               .ToDictionary(p => p.Attribute("name").Value, p => p.Value)
        select new Record
        {
            Index = record.Attribute("index").Value,
            Username = properties["Username"],
            Domain = properties["Domain"],
            LastLogon = properties["LastLogon"]
        };

foreach(var rec in query)
{
    Console.WriteLine("ID: {0} User:{1} Domain:{2} LastLogon:{3}", rec.Index, rec.Username, rec.Domain, rec.LastLogon);
}

РЕДАКТИРОВАТЬ: Я обновил пример кода выше с подходом ToDictionary, который чище и быстрее.Исходя из моих усилий по сравнительному анализу, самым быстрым был ToDictionary, затем Func, а затем Where.

Оригинальный запрос

var query = from record in xml.Elements("record")
            let properties = record.Elements("property")
            select new Record
            {
                Index = record.Attribute("index").Value,
                Username = properties.Where(p => p.Attribute("name").Value == "Username").Single().Value,
                Domain = properties.Where(p => p.Attribute("name").Value == "Domain").Single().Value,
                LastLogon = properties.Where(p => p.Attribute("name").Value == "LastLogon").Single().Value
            };

Запрос с помощью Func

Избыточность исходного запроса можно уменьшить с помощью следующего кода:

Func<XElement, string, string> GetAttribute =
          (e, property) => e.Elements("property")
                            .Where(p => p.Attribute("name").Value == property)
                            .Single().Value;

var query = from record in xml.Elements("record")
            select new Record
            {
                Index = record.Attribute("index").Value,
                Username = GetAttribute(record, "Username"),
                Domain = GetAttribute(record, "Domain"),
                LastLogon = GetAttribute(record, "LastLogon")
            };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...