C# 使用LINQ by属性检索多个XML元素

C# 使用LINQ by属性检索多个XML元素,c#,linq-to-xml,C#,Linq To Xml,鉴于此XML: <?xml version="1.0" encoding="utf-8" ?> <queryableData> <table displayName="Shipments" dbName="Quotes"> <foreignKey column="CustomerId" references="CustomerRegistration"/> <foreignKey column="QuoteStatusId

鉴于此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>
但我不知道如何获取表元素的dbName属性为“Quotes”的字段值。我得到的最接近的是一个包含值列表的列表,而不是一个匿名对象列表,其中一个项具有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)
            };
因此,我希望在列表中列出:

lookUpdatea#1

正文:“报价费用”

值:“QuoteCharge”

lookUpdatea#2

正文:“总重量”

值:“总重量”

我得到的是这个:

lookUpdatea#1

文本:包含两个字符串的列表:[0]=“报价费用”,[1]=“总重量”

值:包含两个字符串的列表:[0]=“QuoteCharge”,[1]=“TotalWeight”

使用以下命令:

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
;
说明:

  • 我们选择
    dbName==“Quotes”
  • 在所有这些元素中,我们选择所有
    field
    元素,并使用
    SelectMany
    将结果展平。结果将是一个
    IEnumerable
  • 对于每个字段,我们选择一个匿名类型,
    Text
    属性设置为第一个名为“displayName”的属性值,
    value
    属性设置为第一个名为“dbColumn”的属性值
  • 您的方法的问题基本上是,您将步骤2放在匿名类型的创建中。或者换句话说:您为每个“Quotes”元素创建了一个匿名类型实例,而不是为每个“field”元素创建了一个匿名类型实例。

    使用以下方法:

    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
    ;
    
    说明:

  • 我们选择
    dbName==“Quotes”
  • 在所有这些元素中,我们选择所有
    field
    元素,并使用
    SelectMany
    将结果展平。结果将是一个
    IEnumerable
  • 对于每个字段,我们选择一个匿名类型,
    Text
    属性设置为第一个名为“displayName”的属性值,
    value
    属性设置为第一个名为“dbColumn”的属性值
  • 您的方法的问题基本上是,您将步骤2放在匿名类型的创建中。或者换句话说:您为每个“Quotes”元素而不是每个“field”元素创建了一个匿名类型实例