如何解析 XML Blob 并关联来自兄弟节点的数据?

How can I parse an XML Blob and associate data from sibling nodes?

我想解析这个 XML blob:

<NFLTeams>
  <Coaches>
    <HeadCoach>Bill Belichick</HeadCoach>
    <OffensiveCoordinator>Josh McDaniels</OffensiveCoordinator>
    <DefensiveCoordinator>Unknown</DefensiveCoordinator>
  </Coaches>
  <Players>
    <Quarterback>Jarret Stidham</Quarterback>
    <WideReceiver>N'Keal Harry</WideReceiver>
  </Players>
  <TeamInfo>
    <TeamName>Patriots</TeamName>
    <StadiumCapacity>65878</StadiumCapacity>
    <StadiumLocation>Foxboro, MA</StadiumLocation>
  </TeamInfo>
  <Coaches>
    <HeadCoach>Adam Gase</HeadCoach>
    <OffensiveCoordinator>Dowell Loggains</OffensiveCoordinator>
    <DefensiveCoordinator>Gregg Williams</DefensiveCoordinator>
  </Coaches>
  <Players>
    <Quarterback>Sam Darnold</Quarterback>
    <WideReceiver>Breshad Perriman</WideReceiver>
  </Players>
  <TeamInfo>
    <TeamName>Jets</TeamName>
    <StadiumCapacity>82500</StadiumCapacity>
    <StadiumLocation>East Rutherford, NJ</StadiumLocation>
  </TeamInfo>
  <Coaches>
    <HeadCoach>Anthony Lynn</HeadCoach>
    <OffensiveCoordinator>Shane Steichen</OffensiveCoordinator>
    <DefensiveCoordinator>Gus Bradley</DefensiveCoordinator>
  </Coaches>
  <Players>
    <Quarterback>Tyrod Taylor</Quarterback>
    <WideReceiver>Keenan Allen</WideReceiver>
  </Players>
  <TeamInfo>
    <TeamName>Chargers</TeamName>
    <StadiumCapacity>27000</StadiumCapacity>
    <StadiumLocation>Carson, CA</StadiumLocation>
  </TeamInfo>
</NFLTeams>

我想将数据放入 List<NFLTeam> 其中 NFLTeam 是:

public class NFLTeam
{
        public string Quarterback { get; set; }
        public string TeamName { get; set; }
        public int StadiumCapacity { get; set; }
}

这样,如果我解析上面的 blob 并将内容输出到控制台,它将如下所示:

Quarterback: 'Jarret Stidham', TeamName: 'Patriots', StadiumCapacity: '65878'
Quarterback: 'Sam Darnold', TeamName: 'Jets', StadiumCapacity: '82500'
Quarterback: 'Tyrod Taylor', TeamName: 'Chargers', StadiumCapacity: '27000'

如何使用 C# 7.3 和 .NET Framework 4.8 执行此操作?

XML 结构不是最好的。最好有一个 <Team> 标签作为球队信息、教练和球员 XML 片段的容器。

无论如何,请检查一下。

c#

void Main()
{
    XDocument xdoc = XDocument.Parse(@"<NFLTeams>
    <Coaches>
        <HeadCoach>Bill Belichick</HeadCoach>
        <OffensiveCoordinator>Josh McDaniels</OffensiveCoordinator>
        <DefensiveCoordinator>Unknown</DefensiveCoordinator>
    </Coaches>
    <Players>
        <Quarterback>Jarret Stidham</Quarterback>
        <WideReceiver>N'Keal Harry</WideReceiver>
    </Players>
    <TeamInfo>
        <TeamName>Patriots</TeamName>
        <StadiumCapacity>65878</StadiumCapacity>
        <StadiumLocation>Foxboro, MA</StadiumLocation>
    </TeamInfo>
    <Coaches>
        <HeadCoach>Adam Gase</HeadCoach>
        <OffensiveCoordinator>Dowell Loggains</OffensiveCoordinator>
        <DefensiveCoordinator>Gregg Williams</DefensiveCoordinator>
    </Coaches>
    <Players>
        <Quarterback>Sam Darnold</Quarterback>
        <WideReceiver>Breshad Perriman</WideReceiver>
    </Players>
    <TeamInfo>
        <TeamName>Jets</TeamName>
        <StadiumCapacity>82500</StadiumCapacity>
        <StadiumLocation>East Rutherford, NJ</StadiumLocation>
    </TeamInfo>
    <Coaches>
        <HeadCoach>Anthony Lynn</HeadCoach>
        <OffensiveCoordinator>Shane Steichen</OffensiveCoordinator>
        <DefensiveCoordinator>Gus Bradley</DefensiveCoordinator>
    </Coaches>
    <Players>
        <Quarterback>Tyrod Taylor</Quarterback>
        <WideReceiver>Keenan Allen</WideReceiver>
    </Players>
    <TeamInfo>
        <TeamName>Chargers</TeamName>
        <StadiumCapacity>27000</StadiumCapacity>
        <StadiumLocation>Carson, CA</StadiumLocation>
    </TeamInfo>
</NFLTeams>");

    var xelem = xdoc.Root.Elements("Players");

    foreach (var el in xelem)
    {
        Console.WriteLine(string.Format("Quarterback: '{0}', TeamName: '{1}', StadiumCapacity: '{2}'"
            , el.Element("Quarterback")?.Value
            , ToXElement(el.NextNode).Element("TeamName")?.Value
            , ToXElement(el.NextNode).Element("StadiumCapacity")?.Value));
    }
}

// Define other methods and classes here
static XElement ToXElement(XNode node)
{
    return node as XElement; // returns null if node is not an XElement
}

Or even without ToXElement() function:

foreach (var el in xelem)
{
    Console.WriteLine(string.Format("Quarterback: '{0}', TeamName: '{1}', StadiumCapacity: '{2}'"
        , el.Element("Quarterback")?.Value
        , el.ElementsAfterSelf("TeamInfo").First().Element("TeamName")?.Value
        , el.ElementsAfterSelf("TeamInfo").First().Element("StadiumCapacity")?.Value));
}

Output

Quarterback: 'Jarret Stidham', TeamName: 'Patriots', StadiumCapacity: '65878'
Quarterback: 'Sam Darnold', TeamName: 'Jets', StadiumCapacity: '82500'
Quarterback: 'Tyrod Taylor', TeamName: 'Chargers', StadiumCapacity: '27000'

使用 xml 带有连接的 linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            List<NFLTeam> teams = (from p in doc.Descendants("Players").Select((x, i) => new { player = x, index = i })
                                   join t in doc.Descendants("TeamInfo").Select((x, i) => new { team = x, index = i })
                                   on p.index equals t.index
                                   select new  NFLTeam()
                                   { 
                                      Quarterback = (string)p.player.Element("Quarterback"),
                                      TeamName = (string)t.team.Element("TeamName"),
                                      StadiumCapacity = (int)t.team.Element("StadiumCapacity")
                                  }).ToList();
        }
    }
    public class NFLTeam
    {
        public string Quarterback { get; set; }
        public string TeamName { get; set; }
        public int StadiumCapacity { get; set; }
    }
}

https://dotnetfiddle.net/XU4Yqe