Как я могу выбрать только некоторые дочерние узлы из XML-файла на С#?

У меня есть файл 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, но я не уверен.

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

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
80
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

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

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

Ответ принят как подходящий

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

/Team/*[self::TeamId or self::TeamName]

Спасибо большое. Все остальные ответы актуальны, но использование вашего заставило меня изменить наименьшее количество кода. Спасибо, парни!

Bogdan Doicin 28.05.2019 18:46

@BogdanDoicin Рад, что это помогло!

Jack Fleeting 28.05.2019 21:06

Вы можете отфильтровать 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();
}

Вот еще один вариант использования 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();

    }

Другие вопросы по теме