【问题标题】:How to use a LINQ query to get XElement values when XElements have same name当 XElement 具有相同名称时如何使用 LINQ 查询获取 XElement 值
【发布时间】:2009-05-20 21:19:36
【问题描述】:

我有一段xml如下:

<Table>
  <Record>
    <Field>Value1_1</Field>
    <Field>Value1_2</Field>
  </Record>
  <Record>
    <Field>Value2_1</Field>
    <Field>Value2_2</Field>
  </Record>
</Table>

我想要的是生成一个 IEnumerable 的 LINQ 查询,我可以将它指定为 DataGrid 的数据源。我目前的情况如下:

var temp = from record in table.Elements("Record")
            select record.Element("Field").Value

我可以有多个字段元素的事实是我的绊脚石。

在上面的例子中,我需要的是IEnumerable&lt;string,string&gt;。 数据网格看起来像这样:

Value1_1, Value1_2
Value2_1, Value2_2

【问题讨论】:

  • XML 有点奇怪,我们可以假设记录内的每个字段元素实际上都是唯一的名称。他们肯定不都被称为“场”吧?
  • 您的预期行为是什么? IE。鉴于有多个 Field 元素,你想要哪一个?
  • xml 很奇怪,但不幸的是我被它困住了。
  • DSO 我已经用预期的行为更新了问题。
  • 也许用有效的类型再次更新问题——IEnumerable&lt;string,string&gt; 不是。我在回答中使用了IEnumerable&lt;IEnumerable&lt;string&gt;&gt;,但也许您想要string[,]string[][]MyRows&lt;MyColumns&gt; 等。

标签: c# linq-to-xml


【解决方案1】:

这样的东西会有帮助吗?

var a = from record in table.Elements("Record")
    select new
    {
        one = (string)record.Elements().ElementAt(0),
        two = (string)record.Elements().ElementAt(1)
    };

【讨论】:

  • 同意 - 我认为这是他唯一的选择,因为它们的顺序很重要。通过将“Field”放在空的 Elements() 调用中,可以做得更好(更准确)。
  • 当这个问题出现在我的搜索中时,正是我正在寻找的东西,我为此创建了赏金来奖励你,因为它看起来不像提问者会接受......跨度>
【解决方案2】:

听起来您想对该字段进行非规范化处理,以使其适合数据网格中的 1 列。

以下有帮助吗?

var table = XElement.Parse(@"<Table>
                                <Record><Field>Value1_1</Field><Field>Value1_2</Field></Record>
                                <Record><Field>Value2_1</Field><Field>Value2_2</Field></Record>
                             </Table>");


var temp = from record in table.Elements("Record")
           from field in record.Elements("Field")
           group field.Value by record into groupedFields
           select groupedFields.Aggregate((l, r) => l + ", " + r);

foreach (var row in temp)
    Console.WriteLine(row);

Console.ReadKey();

免责声明:我不再做太多 SQL 或 LINQ,所以这可能会变得更好。随意更改它。

【讨论】:

    【解决方案3】:

    我不明白问题出在哪里以及为什么其中一些答案看起来如此复杂:-/ 这是我的提议:

    var r = (from record in table.Elements("Record")
             select (from element in record.Elements("Field")
                     select element.Value));
    
    // => IEnumerable<IEnumerable<string>>
    

    内部 IEnumerable 用于列,外部用于行。 (这个问题有点混乱,因为没有IEnumerable&lt;T,T'&gt;,以上是我改编的意图。)

    你可以把内部的 IEnumerable 变成一个字符串(例如加入 ", "),但是如果你的意思是将值作为列,那么放入网格并不是很有趣!

    var r = (from record in table.Elements("Record")
             select String.Join(", ",
                 record.Elements("Field").Select(f => f.Value).ToArray());
    
    // => IEnumerable<string>
    

    如果我真的了解 LINQ 表达式,上述内容可能会变得更好。但是,它可以工作并涵盖“其他”情况——“ToArray”适用于 .NET 3.5 及更低版本。

    【讨论】:

      【解决方案4】:

      也许是这个?

      using System.Linq;
      using System.Xml.Linq;
      using System.Collections.Generic;
      using System.Diagnostics;
      
      [TestMethod]
          public void Linq_XElement_Test()
          {
      
      
          string xml = @"<Table>
        <Record>
          <Field>Value1_1</Field>
          <Field>Value1_2</Field>
        </Record>
        <Record>
          <Field>Value2_1</Field>
          <Field>Value2_2</Field>
        </Record>
      </Table>";
      
          XElement elements = XElement.Parse(xml);
      
          var qryRecords = from record in elements.Elements("Record")
                        select record;
      
          foreach (var rec in qryRecords)
          {
              Debug.WriteLine(rec.Value);
          }
      
          var qryFields = from record in elements.Elements("Record")
                       from fields in record.Elements("Field")
                       select fields;
      
          foreach (var fil in qryFields)
          {
              Debug.WriteLine(fil.Value);
          }
      
          IEnumerable<string> list = qryFields.Select(x => x.Value);
      
          foreach (string item in list)
          {
              Debug.WriteLine(item);
          }
      
      
      }
      

      【讨论】:

      • 请说明您发布的代码如何解决问题。您的代码可能会有所帮助,但说明它的作用可能有助于其他人理解并从中学习。
      【解决方案5】:

      您可以将调用链接到Elements()

      var temp = from field in table.Elements("Record").Elements("Field")
                 select field.Value;
      

      你也可以使用Descendants():

       var temp = from field in table.Descendants("Field")
                  select field.Value;
      

      但是,这将返回

      下的所有 元素,即使它们不在 元素内。

      【讨论】:

        【解决方案6】:

        您需要一个两步流程:

        注释记录(代替属性),然后 枚举字段并将值传递给匿名类进行绑定,如下所示:

        string xml = [string-goes-here];
        
          XElement elem = XElement.Parse(xml);
        
          int count= 0;
          foreach(XElement recordElems in elem.Elements("Record")){
            recordElems.SetAttributeValue("id", count);
            count++;
          }
          var temp = from record in elem.Elements("Record")
                     from field in record.Elements("Field")
                     select new { Record = "Record " + record.Attribute("id").Value, Field = field.Value };
        
          foreach (var item in temp)
          {
            Console.WriteLine("{0}: {1}", item.Record, item.Field);
          }
        }
        

        【讨论】:

          【解决方案7】:

          我可能与您正在寻找的东西相去甚远,但您是否正在寻找这样的东西?

                  DataSet ds = new DataSet("Records DS");
                  ds.Tables.Add("Records");
                  foreach (XElement record in table.Descendants("Record"))
                  {
                      var temp = from r in record.Descendants("Field")
                                 select r.Value;
          
                      string[] datum = temp.ToArray();
                      if (datum != null
                          && datum.Length > 0)
                      {
                          foreach (string s in datum)
                              ds.Tables[0].Columns.Add();
                          DataRow row = ds.Tables[0].NewRow();
                          row.ItemArray = datum;
                          ds.Tables[0].Rows.Add(row);
                      }
                  }
          

          然后返回ds并将DataMember设置为"Records"

          【讨论】:

            【解决方案8】:

            呃...我认为您为这个问题使用了错误的 LINQ 范式。您应该使用 LINQ to XML,这可能与您的预期略有不同。

            查看此链接:

            http://msdn.microsoft.com/en-us/library/bb308960.aspx

            它使用与您提供的结构相似的示例来解释它。

            【讨论】:

              【解决方案9】:

              IEnumerable<List<string>>
              

              工作? (不知道如何让它内联显示)

              var recordList = from record in data.Elements("record") select record;
              List<List<string>> x = new List<List<string>>(recordList.Count());
              foreach (var record in recordList)
              {
                var z = from field in record.Elements("field") select field.Value;
                x.Add(z.ToList());
              }
              return x.AsEnumerable();
              

              不知道这是否适用于您的特定场景。

              【讨论】:

                【解决方案10】:

                var detail1 = 来自 ds.tbl_Looking_Fors 中的 d 其中 d.Profile_ID == id 选择 d.Looking_For ;

                            string[] datum = detail1.ToArray();
                            if (datum != null && datum.Length > 0)
                            {
                                foreach (var row in datum)
                                {
                                    Label6.Text = datum[0]+" , "+datum[1];
                                }
                
                            }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2012-06-14
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多