我如何获得所有“属性”?从 xml 通过 linq 到 xml

发布于 2024-08-23 06:16:12 字数 1113 浏览 6 评论 0原文

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暮光沉寂 2024-08-30 06:16:12

编辑:使用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
            };

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

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")
            };
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文