Здравствуйте есть большой XML файл, более 500000 записей, из него часто приходится дергать корректировочную информацию. чтобы не грузить файл полностью а с помощью linq выполнить фильтрацию записей.
<root>
<esrs>
<rc int_ESR="-1594" str_Name="ПОБОЖИЙ"/>
<rc int_ESR="-1593" str_Name="ФЕДОСЕЕВ"/>
<rc int_ESR="-1592" str_Name="ГЛУХАРИНЫЙ"/>
</esrs>
код загрузки всех станций:
public IEnumerable<Station> SetResponse(XDocument xmlDoc, IEnumerable<Station> stationValid)
{
var listStationsNameQuery =
from train in xmlDoc.Descendants("rc")
select new
{
Esr = (string)train.Attribute("int_ESR"),
Name = (string)train.Attribute("str_Name"),
};
}
А мне нужно грузить только станции указанные в stationValid по равенству ESR кода? Подскажите как сделать такое ограничение на Linq запрос?
С XDocument не выйдет не грузить весь документ в память. Если вам нужно только читать информацию, нужно использовать XmlReader, он потоковый.
Например, чтобы найти все str_Name, соответствующие данному int_ESR, подойдёт вот такой код:
var goodEsrValues = new HashSet<string>(
stationValid.Select(station => station.ESR.ToString()));
using (TextReader tr = ...)
using (var reader = XmlReader.Create(tr))
{
while (reader.Read())
{
if (reader.NodeType != XmlNodeType.Element || reader.Name != "rc")
continue;
var attr = reader.GetAttribute("int_ESR");
if (!goodEsrValues.Contains(attr))
continue;
var name = reader.GetAttribute("str_Name");
if (name != null)
yield return name;
}
}
Если бы надо было найти по одному ключу, можно было бы XPath использовать, в вашем случае может подойдёт такой вариант:
public IEnumerable<Station> SetResponse(XDocument xmlDoc, IEnumerable<Station> stationValid)
{
var validEsr = new HashSet<string>(stationValid.Select(s => s.Esr));
foreach(var elem in xmlDoc.Descendants("rc"))
{
var esr = (string)train.Attribute("int_ESR");
if (validEsr.Contain(esr))
{
yield return new
{
Esr = esr,
Name = (string)train.Attribute("str_Name"),
};
}
}
}
Продвижение своими сайтами как стратегия роста и независимости