using System.IO; using System.IO.Compression; using System.Xml; using System.Xml.Linq; public static TextReader OpenFile(string path) { Stream s = File.OpenRead(path); // otevření souboru na čtení // odzipovací stream, když to vypadá jako zkomprimovaný soubor if (path.EndsWith(".gz")) s = new GZipStream(s, CompressionMode.Decompress); return new StreamReader(s); } public static IEnumerable LoadElements(TextReader text) { // XmlReader je streamové parsovadlo XML v .NETu using (var reader = XmlReader.Create(text, new XmlReaderSettings { IgnoreComments = true, IgnoreWhitespace = true })) { reader.MoveToContent(); reader.Read(); while (!reader.EOF) { if (reader.NodeType == XmlNodeType.Element) { // před načtením celého elementu si můžu přečíst jenom název elementu a atributy a zkontrolovat si, že ho fakt chci načítat celý // zajímají cesty a vrcholy if (reader.Name == "way" || reader.Name == "node") { // ještě před načtením celého elementu můžete také filtrovat podle XML atributů // ale podle vnitřních elementů (například tagů) to nejde // takto se načte id: `long.Parse(reader.GetAttribute("id"))` // načteme element, protože nás zajímá // funkce ReadFrom načte element celý do stromu v paměti a není zrovna rychlá var el = (XElement)XNode.ReadFrom(reader); // a pak ho vrátíme jako částečný výsledek // tato metoda je trochu speciální, protože vrací libovolné množství XElementů // a spočítá je až když je to potřeba, takže nám nebudou zabírat paměť všechny najednou yield return el; } else { // když nás nezajímá, přeskočíme // volání Skip je vlastně stejné jako XNode.ReadFrom, ale nevyrobí nám žádný strom, jenom projede ten kus XML // a je tak o poznání rychlejší reader.Skip(); } } else { // když to není element, tak ho přeskočíme reader.Read(); } } } } // teď třeba můžeme projít všechny cesty a vypsat je foreach (var element in LoadElements(OpenFile("brno.osm.gz"))) { if (element.Elements("tag").Any(t => t.Attribute("k").Value == "amenity" && t.Attribute("v").Value == "library")) { if (element.Name == "node") Console.WriteLine($"Library: {element}"); else Console.WriteLine($"Library area: {element}"); } }