繁体   English   中英

通过属性使用LINQ检索多个XML元素

[英]Retrieving multiple XML elements with LINQ by attributes

鉴于此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>

我想获取一个仅包含“ Quotes”表的DisplayName,DbColumn和Type字段的匿名对象类型的列表。

我可以使用下面的LINQ to XML代码获得两个表的列表:

    var xml = XElement.Load(@"C:\Sandbox\queryable.xml");

    // Tables
    var tables = from el in xml.Elements("table")
                        select new 
                        {
                            Text = el.Attribute("displayName").Value,
                            Value = el.Attribute("dbName").Value
                        };

但是我不确定如何获取表格元素的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)
            };

所以我希望在列表中这样:

LookupData#1

文字:“报价单”

值:“ QuoteCharge”

LookupData#2

文字:“总重量”

值:“总重量”

而我得到这个代替:

查找数据#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
;

说明:

  1. 我们选择dbName == "Quotes"的元素
  2. 在所有这些元素中,我们选择所有field元素,并使用SelectMany将结果展平。 结果将是IEnumerable<XElement>
  3. 对于每个字段,我们选择一个匿名类型,其Text属性设置为名为“ displayName”的第一个属性的值,而Value属性设置为名为“ dbColumn”的第一个属性的值

基本上,您的方法存在问题,即您将步骤2放入了匿名类型的创建中。 换句话说:您为“ Quotes”元素而不是“ field”元素创建了一个匿名类型实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM