Как я могу выбрать только некоторые дочерние узлы из файла XML в C #? - PullRequest
1 голос
/ 28 мая 2019

У меня есть файл XML, который я хочу проанализировать.Это дольше, чем то, что я опубликую здесь, но только эта часть меня интересует в этом вопросе:

       <Team>
        <TeamId>1187457</TeamId>
        <TeamName>Zanardi Redwings</TeamName>
        <Arena>
          <ArenaId>1184019</ArenaId>
          <ArenaName>Evolution</ArenaName>
        </Arena>
        <League>
          <LeagueId>37</LeagueId>
          <LeagueName>România</LeagueName>
        </League>
        <Country>
          <CountryId>36</CountryId>
          <CountryName>România</CountryName>
        </Country>
        <LeagueLevelUnit>
          <LeagueLevelUnitId>4109</LeagueLevelUnitId>
          <LeagueLevelUnitName>V.171</LeagueLevelUnitName>
        </LeagueLevelUnit>
        <Region>
          <RegionId>799</RegionId>
          <RegionName>Prahova</RegionName>
        </Region>
        <YouthTeam>
          <YouthTeamId>2337461</YouthTeamId>
          <YouthTeamName>Little Redwings</YouthTeamName>
          <YouthLeague>
            <YouthLeagueId>436902</YouthLeagueId>
            <YouthLeagueName>Normandie Ligue des jeunes</YouthLeagueName>
          </YouthLeague>
        </YouthTeam>
      </Team>

Из приведенной выше части мне нужно только прочитать данные из TeamId и TeamNameдочерние узлы.Чтобы добиться этого, я написал следующий код:

Nodes = Node.SelectNodes("Team");
foreach (XmlNode j in Nodes)
  {
    XmlNodeList TeamDetails = j.SelectNodes("*");
    foreach (XmlNode k in TeamDetails)
      {
         switch (k.Name)
           {
             case "TeamName":
               {
                  UserTeamNames[counter] = k.InnerXml;
                  break;
               }
             case "TeamId":
               {
                  if (!int.TryParse(k.InnerXml, out UserTeamIDs[counter]))
                   {
                      ShowErrorMessageBox("Parsing TeamID from XML file failed!"); //A function which sets some parameters for MessageBox.Show() then calls it
                   }
                  break;
                }
            }
       }
   }

В приведенном выше коде counter - это переменная int, которая мне нужна в другой части кода.

Код работает отлично, но я хочу устранить бесполезные циклы и тестирование, когда узел, над которым я работаю, не является либо TeamName, либо TeamID.

Я подозреваю, что искомый ответ как-то связан с выражениями XPath, но я не уверен.

Как я могу прочитать данные только из * упомянутогоузлы, без каких-либо бесполезных операций?

Ответы [ 4 ]

1 голос
/ 28 мая 2019

Вот еще один вариант, использующий LINQ to XML. Сначала создайте свой собственный класс, который будет содержать данные, которые вы ищете, вот так:

public class TeamInfo
{
    public string TeamName { get; set; }
    public int TeamId { get; set; }
}

Затем вы бы проанализировали xml в список объектов, таких какэто:

var data =
            "<Team><TeamId>1187457</TeamId><TeamName>Zanardi Redwings</TeamName><Arena><ArenaId>1184019</ArenaId><ArenaName>Evolution</ArenaName></Arena><League><LeagueId>37</LeagueId><LeagueName>România</LeagueName></League><Country><CountryId>36</CountryId><CountryName>România</CountryName></Country><LeagueLevelUnit><LeagueLevelUnitId>4109</LeagueLevelUnitId><LeagueLevelUnitName>V.171</LeagueLevelUnitName></LeagueLevelUnit><Region><RegionId>799</RegionId><RegionName>Prahova</RegionName></Region><YouthTeam><YouthTeamId>2337461</YouthTeamId><YouthTeamName>Little Redwings</YouthTeamName><YouthLeague><YouthLeagueId>436902</YouthLeagueId><YouthLeagueName>Normandie Ligue des jeunes</YouthLeagueName></YouthLeague></YouthTeam></Team>";
        var elm = new XElement("Base",data);
        var decoded = System.Web.HttpUtility.HtmlDecode(elm.ToString());//this is to remove any formatting issues when we call .ToString()

        var doc = XDocument.Parse(decoded);

        var result = doc.Root.Descendants("Team")
            .Select(y => new TeamInfo
            {
                TeamId = Convert.ToInt32(y.Element("TeamId").Value),
                TeamName = y.Element("TeamName").Value
            }).ToList();

    }
1 голос
/ 28 мая 2019

Строго говоря, с точки зрения xpath, следующие выражения должны выбирать ваши узлы:

/Team/*[self::TeamId or self::TeamName]
1 голос
/ 28 мая 2019

Вы можете отфильтровать XML-документ с помощью linq, а затем работать с отфильтрованными данными.

using System;
using System.Linq;
using System.Xml.Linq;
using System.IO;
using System.Xml;

static void Main(string[] args)
{
    var document = new XDocument();

    // use path to your xml file
    using (FileStream fs = File.OpenRead("examp.xml"))
    {
        using (XmlTextReader reader = new XmlTextReader(fs))
        {
            document = XDocument.Load(reader);
        }
    }

    int value;
    var query = (from element in document.Element("Base").Elements("Team")
                 where int.TryParse(element.Element("TeamId").Value.ToString(), out value)
                 select new
                 {
                     TeamName = element.Element("TeamName").Value,
                     TeamId = element.Element("TeamId").Value
                 }).ToList();

    // do further processing with filtered data
    foreach (var item in query)
    {
        Console.WriteLine($"{item.TeamName}: {item.TeamId}");
    }

    Console.ReadKey();
}
1 голос
/ 28 мая 2019

Вы можете использовать метод XmlDocument.GetElementsByTagName. Для вашего примера я сделаю что-то вроде этого:

XmlNodeList elemList = doc.GetElementsByTagName("TeamName");
XmlNodeList elemList = doc.GetElementsByTagName("TeamId");

Результатом является XmlNodeList, содержащий список всех соответствующих узлов. Если ни одно из узлов не соответствует имени, возвращаемая коллекция будет пустой.

...