У меня есть файл 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, но я не уверен.
Как я могу прочитать данные из Только упомянутых узлов, без каких-либо бесполезных операций?
Вы можете использовать метод XmlDocument.GetElementsByTagName. Для вашего примера я сделаю что-то вроде этого:
XmlNodeList elemList = doc.GetElementsByTagName("TeamName");
XmlNodeList elemList = doc.GetElementsByTagName("TeamId");
Результатом является XmlNodeList, содержащий список всех соответствующих узлов. Если ни один узел не соответствует имени, возвращаемая коллекция будет пустой.
Строго с точки зрения xpath, следующее выражение должно выбирать ваши узлы:
/Team/*[self::TeamId or self::TeamName]
@BogdanDoicin Рад, что это помогло!
Вы можете отфильтровать 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();
}
Спасибо большое. Все остальные ответы актуальны, но использование вашего заставило меня изменить наименьшее количество кода. Спасибо, парни!