如果c#中有多个<data>元素来自xml

时间:2016-11-16 04:54:42

标签: c# xml linq

如果有多个数据元素,我想要多个记录,因此每个数据记录的id和log元素将保持相同。

注意:xml中会有多个元素,下面的示例,下面仅针对单个

xml代码:

<pay>
  <id>1</id>
  <data>
    <startDate>2016-03-03</startDate>
    <adjustedDueDate>2016-03-31</adjustedDueDate>
    <Rate>50</Rate>
</data>
<data>
    <startDate>2016-04-04</startDate>
    <adjustedDueDate>2016-04-04</adjustedDueDate>
    <Rate>12</Rate>
</data>
<log>IMP</log>
</pay>

C#代码

string path = @"E:\XMLFile1.xml";
XDocument xmlExeDoc = XDocument.Load(path);
var recordsFac = xmlExeDoc.Descendants("pay").Select(x => new
{
    id = (string)x.Element("id"),
    cycle = x.Elements("data").Select(y => new
    {
        startDate = (y.Elements("startDate").Any() == true) ? (string)y.Element("startDate") : string.Empty,
        adjustedDueDate = (DateTime)y.Element("adjustedDueDate"),
        Rate = (decimal)y.Element("Rate")
    }).Where(y => y.Rate > 0 && y.adjustedDueDate < DateTime.Now)
                           .Select
                           (
                               c => new
                               {
                                   startDate = c.startDate,
                                   adjustedDueDate = c.adjustedDueDate,
                                   Rate = c.Rate
                               }
                           ).FirstOrDefault(),

    log = x.Element("log")
}).ToList();

必需的输出:

输出:

[0] {1,2016-03-03,2016-03-31,50,IMP}

[1] {1,2016-04-04,2016-04-04,12,IMP}

需要与此处相同的输出,但添加的另一个元素我已编码,如下所示是正确的方法,需要2行和2行元素。

<pay>
  <id>1</id>
  <data>
    <startDate>2016-03-03</startDate>
    <adjustedDueDate>2016-03-31</adjustedDueDate>
    <Rate>50</Rate>
</data>
<data>
    <startDate>2016-04-04</startDate>
    <adjustedDueDate>2016-04-04</adjustedDueDate>
    <Rate>12</Rate>
</data>
<log>IMP</log>
</pay>
<ClientData>
    <startDate>2016-07-04</startDate>
    <adjustedDueDate>2016-08-04</adjustedDueDate>
    <Rate>100</Rate>
</ClientData>
<ClientData>
    <startDate>2016-09-04</startDate>
    <adjustedDueDate>2016-09-04</adjustedDueDate>
    <Rate>555</Rate>
</ClientData>
</pay>



var recordsFac = xmlExeDoc.Descendants("pay").Select(x => new
{

    cycle = x.Elements("data").Select(y => new
    {
        id = (string)x.Element("id"),
        startDate = (y.Elements("startDate").Any() == true) ? (string)y.Element("startDate") : string.Empty,
        adjustedDueDate = (DateTime)y.Element("adjustedDueDate"),
        Rate = (decimal)y.Element("Rate"),
        log = x.Element("log")
    }).Where(y => y.Rate > 0 && y.adjustedDueDate < DateTime.Now),
    ClientData = x.Elements("data").Select(y => new
    {
        id = (string)x.Element("id"),
        startDate = (y.Elements("startDate").Any() == true) ? (string)y.Element("startDate") : string.Empty,
        adjustedDueDate = (DateTime)y.Element("adjustedDueDate"),
        Rate = (decimal)y.Element("Rate"),
        log = x.Element("log")
    }).Where(y => y.Rate > 0 && y.adjustedDueDate < DateTime.Now)

}).ToList();

以上代码是实现此目的的正确方法:

输出:

[0] {1,2016-03-03,2016-03-31,50,IMP}

[1] {1,2016-04-04,2016-04-04,12,IMP}

[2] {1,2016-07-04,2016-08-04,100,IMP}

[3] {1,2016-09-04,2016-09-04,555,IMP}

1 个答案:

答案 0 :(得分:0)

您的查询已经产生了您所要求的内容,但您将周期查询限制为FirstOrDefault,因此它只会产生1条记录。如果删除它,则循环包含两个记录。

要获取ID并记录与日期相同的记录,只需将它们包含在您正在创建的最终匿名类中:

var recordsFac = xmlExeDoc.Descendants("pay").Select(x => new
{

    cycle = x.Elements("data").Select(y => new
    {
        startDate = (y.Elements("startDate").Any() == true) ? (string)y.Element("startDate") : string.Empty,
        adjustedDueDate = (DateTime)y.Element("adjustedDueDate"),
        Rate = (decimal)y.Element("Rate"),
    }).Where(y => y.Rate > 0 && y.adjustedDueDate < DateTime.Now)
                           .Select
                           (
                               c => new
                               {
                                   id = (string)x.Element("id"),
                                   startDate = c.startDate,
                                   adjustedDueDate = c.adjustedDueDate,
                                   Rate = c.Rate,
                                   log = x.Element("log")
                               }
                           ),

}).ToList();

recordsFac将包含xml文件中每个pay元素的记录。每条记录的循环属性将包含您概述的数据。一个简单的嵌套foreach循环将访问数据:

foreach(var record in recordsFac)
{
    foreach(var record2 in record.cycle)
    {
        Console.WriteLine($"{record2.id},{record2.startDate},{record2.adjustedDueDate},{record2.log}");
    }
}

再看看你的代码并注意到最后一个选择是多余的,可以删除:

var recordsFac = xmlExeDoc.Descendants("pay").Select(x => new
{

    cycle = x.Elements("data").Select(y => new
    {
        id = (string)x.Element("id"),
        startDate = (y.Elements("startDate").Any() == true) ? (string)y.Element("startDate") : string.Empty,
        adjustedDueDate = (DateTime)y.Element("adjustedDueDate"),
        Rate = (decimal)y.Element("Rate"),
        log = x.Element("log")
    }).Where(y => y.Rate > 0 && y.adjustedDueDate < DateTime.Now)               
}).ToList();

foreach(var record in recordsFac)
{
    foreach(var record2 in record.cycle)
    {
        Console.WriteLine($"{record2.id},{record2.startDate},{record2.adjustedDueDate},{record2.log}");
    }
}