Hello, there is a big XML file, more than 500000 records, often you have to pull correction information from it. not to load the file completely and use linq to filter the records.

<root> <esrs> <rc int_ESR="-1594" str_Name="ПОБОЖИЙ"/> <rc int_ESR="-1593" str_Name="ФЕДОСЕЕВ"/> <rc int_ESR="-1592" str_Name="ГЛУХАРИНЫЙ"/> </esrs> 

Download code for all stations:

  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"), }; } 

And I need to load only the stations specified in stationValid by equality of the ESR code? Tell me how to make such a limitation on Linq request?

    2 answers 2

    With XDocument it will not work not to load the entire document into memory. If you only need to read the information, you need to use an XmlReader , it is streamed.

    For example, to find all the str_Name corresponding to the given int_ESR , the following code is appropriate:

     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; } } 
    • one
      Those. Does Linq already work on document lines in memory? How about XmlReader? - Aldmi
    • @Aldmi: XmlReader does not load the document into memory, but reads and outputs in pieces. Now I will write an example. - VladD
    • @Aldmi: And XDocument , yes, it loads everything into memory: - \ - VladD

    If you had to find one key at a time, you could use XPath, in your case this option might work:

     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"), }; } } } 
    • And if to use one more variable from. var listStationsNameQuery = from train in xmlDoc.Descendants ("rc") from station to stationValid where (string) train.Attribute ("int_ESR") == station.EcpCode.ToString () &&! string.IsNullOrEmpty ((string) train. Attribute ("str_Name")) select new {Esr = (string) train.Attribute ("int_ESR"), Name = (string) train.Attribute ("str_Name"),}; - Aldmi