簡體   English   中英

使用XDocument和LINQ使用成對的元素解析XML

[英]Parsing XML with pairs of elements using XDocument and LINQ

我正在嘗試使用XDocument來解析xml文檔,但是我對XML還是很陌生,過去僅主要使用JSON。 到目前為止,我可以解析每個報表名稱,但仍然嘗試解析參數列表。 沒有節點區分不同參數時,如何解析參數列表?

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>

您可以使用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"
      }
    ]
  }
]

試試這個(通過嘗試我的意思是使用 ):

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]));
    }
}

也許這會起作用。

您可以使用XNode.ElementsAfterSelf將ParameterList元素作為IEnumerable。 然后循環遍歷結果集並假定元素成對。

從本質上講,這將為您提供一種按元素在ParameterList中出現的順序解析元素的方法,而不必擔心.Descendants會弄亂順序。

當然,這里的主要假設是元素總是成對存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM