How do i get all “properties” from xml via linq to xml

南楼画角 提交于 2020-01-02 04:59:07

问题


XML sample (original link):

<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>

I'm wanting to get an instance of a class per record in the xml.

i found similar examples in here but they only had a root, then one element deep. It works, right up until i put that other element in. i want to be able to do something like

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

回答1:


EDIT: updated code with ToDictionary approach for clarity and efficiency.

You can try the following sample. If you remove Record from the select new Record line it will result in an anonymous type and still work. Your Record class should have a default parameterless constructor to use the object initializer if you have provided other constructors (it will also work if you have no constructors). Otherwise you can use the available constructors instead of the object initializer.

Note that the use of Single() and Value assume the XML is well formed without any missing elements.

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

EDIT: I've updated the code sample above with the ToDictionary approach which is cleaner and quicker. Based on my benchmarking efforts the fastest was ToDictionary, followed by Func, and then the Where approach.

Original Query

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

Query with Func

Redundancy of the original query can be reduced by using the following code:

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


来源:https://stackoverflow.com/questions/2323738/how-do-i-get-all-properties-from-xml-via-linq-to-xml

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!