2013-12-17 126 views
2

我想用XDocument来解析xml文档,但是我对XML很陌生,以前只使用过JSON。到目前为止,我可以解析每个报告名称,但我试图解析参数列表。当没有节点区分不同参数时,如何解析参数列表?使用XDocument和LINQ解析XML和元素对

var reports = xml.Descendants("Report").Select(reportElement => new 
{ 
    Name = reportElement.Attribute("Name").Value, 
    Parameters = reportElement.Descendants("ParameterList").Select(parameter => new 
    { 
    }) 
}); 

XML:

<ReportList> 
    <Report Name="JobNotClose"> 
     <ParameterList> 
      <Name>@StationCode</Name><Value>LAX</Value> 
      <Name>@ShipmentType</Name><Value>SE|SI</Value> 
     </ParameterList> 
    </Report> 
    <Report Name="JobWithoutSales"> 
     <ParameterList> 
      <Name>@StationCode</Name><Value>PA</Value> 
      <Name>@JobDateFrom</Name><Value>2013-10-1</Value> 
      <Name>@JobDateTo</Name><Value>2013-10-31</Value> 
     </ParameterList> 
    </Report> 
</ReportList> 
+1

那xml看起来有点小狗给我。参数条目是不是应该是? – Alex

+0

看到这就是我问的,但没有这将如何被格式化。如果这是一个节点,我只是使用'.Descendants()'我真的不知道如何处理它像这样构造 – ChaoticLoki

回答

2

您可以使用Enumerable.Zip合并与参数的参数名称序列值序列:

var reports = from r in xml.Root.Elements("Report") 
       let parameters = r.Element("ParameterList") 
       select new { 
        Name = (string)r.Attribute("Name"), 
        Parameters = parameters.Elements("Name") 
             .Zip(parameters.Elements("Value"), 
               (n,v) => new { 
                Name = (string)n, 
                Value = (string)v 
               }) 
       }; 

这给了以下报告集合:

[ 
    { 
    "Name": "JobNotClose", 
    "Parameters": [ 
     { 
     "Name": "@StationCode", 
     "Value": "LAX" 
     }, 
     { 
     "Name": "@ShipmentType", 
     "Value": "SE|SI" 
     } 
    ] 
    }, 
    { 
    "Name": "JobWithoutSales", 
    "Parameters": [ 
     { 
     "Name": "@StationCode", 
     "Value": "PA" 
     }, 
     { 
     "Name": "@JobDateFrom", 
     "Value": "2013-10-1" 
     }, 
     { 
     "Name": "@JobDateTo", 
     "Value": "2013-10-31" 
     } 
    ] 
    } 
] 
0

也许这会工作。

您可以使用XNode.ElementsAfterSelf将ParameterList元素作为IEnumerable。 然后遍历结果集并假定元素是成对的。

这实际上会给你一种方法来解析出现在ParameterList中的元素的顺序,而不用担心.Descendants搞乱了顺序。

当然,这里的一个重要假设是元素总是成对的。

1

试试这个(和尝试我的意思是使用):

var reports = xml.Descendants("Report").Select(reportElement => new 
{ 
    Name = reportElement.Attribute("Name").Value, 
    Parameters = reportElement.Descendants("ParameterList").Select(parameter => 
    { 
     List<string> names = parameter.Elements("Name").Select(x=>x.Value).ToList(); 
     List<string> values = parameter.Elements("Value").Select(x=>x.Value).ToList(); 

     List<object> pairs=new List<object>(); 

     for (int i = 0; i < names.Count; i++) 
     { 
      pairs.Add(new { Name = names[i], Value = values[i] }); 
     } 

     return pairs;      
    }).ToList() 
}).ToList(); 

您可以删除这两个ToList()电话。它只是使测试更容易。当然,在您的XML中,可能存在<Name> <Value>标签并不总是完整的(即Name而没有Value)。您可以在执行for循环之前检查。

编辑:另一种:

Dictionary<string, List<Tuple<string, string>>> rep = new Dictionary<string, List<Tuple<string, string>>>(); 

foreach (XElement report in xml.Elements("Report")) 
{ 
    rep.Add(report.Attribute("Name").Value, new List<Tuple<string, string>>()); 

    List<string> names = report.Elements("ParameterList").FirstOrDefault().Elements("Name").Select(x => x.Value).ToList(); 
    List<string> values = report.Elements("ParameterList").FirstOrDefault().Elements("Value").Select(x => x.Value).ToList(); 

    for (int i = 0; i < names.Count; i++) 
    { 
     rep[report.Attribute("Name").Value].Add(new Tuple<string, string>(names[i], values[i])); 
    } 
} 
+0

这不会使参数成为一个列表清单吗?我可能从参数的开头写错了。据我的理解,每个报告将只包含一个ParameterList节点,并在其中多个对 – ChaoticLoki

+0

@ChaoticLoki,是的,它确实使它成为一个列表清单。这是这种方法的缺点。还有其他的方法。这个建立在你的逻辑之上。 –