如何通过LINQ to XML从XML中获取所有“属性”

5

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

编辑:为了更加清晰和高效,更新了代码并采用ToDictionary方法。

您可以尝试以下示例。如果从select new Record行中移除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<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")
            };

太完美了!我已经试了2-3天了,一直在琢磨这个问题。我的额头都红肿了。你有什么关于LINQ(和C#)的书推荐吗? - Sunzaru Sven
@Sunzaru 我喜欢《LINQ in Action》(http://www.amazon.com/dp/1933988169/),或者你可以考虑购买一本C# 4.0 / .NET 4.0的书籍来了解一些新材料。《C# 4.0 in a Nutshell》不错,但它涵盖了很多内容。我还建议下载LINQPad(http://www.linqpad.net/)并浏览其中附带的Nutshell示例(由该书作者制作)。你也可以通过它下载《LINQ in Action》的示例。也许在购买书籍之前先这样做 :) - Ahmad Mageed
我今天测试了一下,平均处理时间为120毫秒。但在这120毫秒内,我还查找了一些未提及的其他指标。速度快、流畅,比“编辑->查找”好太多了。再次感谢! - Sunzaru Sven
@Sunzaru,很高兴你发现它有用。顺便再看一下主代码块。我添加了一个“ToDictionary”的方法,它比原来的Func方法更快。而且我觉得这种方式更易读。 - Ahmad Mageed

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