Каков наилучший способ анализа (большого) XML в коде C #?

Я пишу инструмент GIS-клиента на C # для извлечения «функций» в XML-схеме на основе GML (образец ниже) с сервера. Экстракты ограничены 100 000 функциями.

Я хочу, чтобы самый большой файл extract.xml мог получить около 150 мегабайт, поэтому очевидно, что DOM-парсеры отсутствуют. Я пытаюсь решить между XmlSerializer и XSD.EXE сгенерированными привязками -OR– XmlReader и графом объектов вручную.

Или, может быть, есть лучший способ, который я еще не рассмотрел? Как XLINQ, или ????

Пожалуйста, кто-нибудь может мне помочь? Особенно в отношении эффективности памяти любого данного подхода. Если нет, мне придется «прототипировать» оба решения и проецировать их бок о бок.

Я немного креветка в .NET. Любое руководство будет высоко оценено.

Благодарю вас. Кит.


Пример XML – до 100 000 из них, до 234 600 коордов на каждую функцию.

      153.505004,-27.42196 153.505044,-27.422015 153.503992 .... 172 coordinates omitted to save space ... 153.505004,-27.42196       

    Используйте XmlReader для анализа больших XML-документов. XmlReader обеспечивает быстрый, прямой доступ, не кэшированный доступ к данным XML. (Только для пересылки означает, что вы можете читать XML-файл от начала до конца, но не можете перемещаться назад в файл.) XmlReader использует небольшие объемы памяти и эквивалентен использованию простого считывателя SAX.

      using (XmlReader myReader = XmlReader.Create(@"c:\data\coords.xml")) { while (myReader.Read()) { // Process each node (myReader.Value) here // ... } } 

    Вы можете использовать XmlReader для обработки файлов размером до 2 гигабайт (ГБ).

    Ссылка: Как читать XML из файла с помощью Visual C #

    Асат 14 мая 2009 года: я перешел на использование гибридного подхода … см. Код ниже.

    Эта версия имеет большинство преимуществ обоих:
    * XmlReader / XmlTextReader (эффективность памяти -> скорость); а также
    * XmlSerializer (code-gen -> ускорение разработки и гибкость).

    Он использует XmlTextReader для итерации по документу и создает «doclets», которые он десериализует, используя classы XmlSerializer и «XML binding», созданные с помощью XSD.EXE.

    Я думаю, этот рецепт универсально применим, и он быстро … Я разбираю XML-документ 201 МБ, содержащий 56 000 функций GML, примерно за 7 секунд … для старой реализации этого приложения VB6 потребовалось несколько минут (или даже часов) для синтаксического анализа большие выдержки … так что я выгляжу хорошо.

    Еще раз, БОЛЬШОЕ Спасибо, форумчикам за то, что вы пожертвовали свое драгоценное время. Я очень ценю это.

    Приветствует всех. Кит.

     using System; using System.Reflection; using System.Xml; using System.Xml.Serialization; using System.IO; using System.Collections.Generic; using nrw_rime_extract.utils; using nrw_rime_extract.xml.generated_bindings; namespace nrw_rime_extract.xml { internal interface ExtractXmlReader { rimeType read(string xmlFilename); } ///  /// RimeExtractXml provides bindings to the RIME Extract XML as defined by /// $/Release 2.7/Documentation/Technical/SCHEMA and DTDs/nrw-rime-extract.xsd ///  internal class ExtractXmlReader_XmlSerializerImpl : ExtractXmlReader { private Log log = Log.getInstance(); public rimeType read(string xmlFilename) { log.write( string.Format( "DEBUG: ExtractXmlReader_XmlSerializerImpl.read({0})", xmlFilename)); using (Stream stream = new FileStream(xmlFilename, FileMode.Open)) { return read(stream); } } internal rimeType read(Stream xmlInputStream) { // create an instance of the XmlSerializer class, // specifying the type of object to be deserialized. XmlSerializer serializer = new XmlSerializer(typeof(rimeType)); serializer.UnknownNode += new XmlNodeEventHandler(handleUnknownNode); serializer.UnknownAttribute += new XmlAttributeEventHandler(handleUnknownAttribute); // use the Deserialize method to restore the object's state // with data from the XML document. return (rimeType)serializer.Deserialize(xmlInputStream); } protected void handleUnknownNode(object sender, XmlNodeEventArgs e) { log.write( string.Format( "XML_ERROR: Unknown Node at line {0} position {1} : {2}\t{3}", e.LineNumber, e.LinePosition, e.Name, e.Text)); } protected void handleUnknownAttribute(object sender, XmlAttributeEventArgs e) { log.write( string.Format( "XML_ERROR: Unknown Attribute at line {0} position {1} : {2}='{3}'", e.LineNumber, e.LinePosition, e.Attr.Name, e.Attr.Value)); } } ///  /// xtractXmlReader provides bindings to the extract.xml /// returned by the RIME server; as defined by: /// $/Release X/Documentation/Technical/SCHEMA and /// DTDs/nrw-rime-extract.xsd ///  internal class ExtractXmlReader_XmlTextReaderXmlSerializerHybridImpl : ExtractXmlReader { private Log log = Log.getInstance(); public rimeType read(string xmlFilename) { log.write( string.Format( "DEBUG: ExtractXmlReader_XmlTextReaderXmlSerializerHybridImpl." + "read({0})", xmlFilename)); using (XmlReader reader = XmlReader.Create(xmlFilename)) { return read(reader); } } public rimeType read(XmlReader reader) { rimeType result = new rimeType(); // a deserializer for featureClass, feature, etc, "doclets" Dictionary serializers = new Dictionary(); serializers.Add(typeof(featureClassType), newSerializer(typeof(featureClassType))); serializers.Add(typeof(featureType), newSerializer(typeof(featureType))); List featureClasses = new List(); List features = new List(); while (!reader.EOF) { if (reader.MoveToContent() != XmlNodeType.Element) { reader.Read(); // skip non-element-nodes and unknown-elements. continue; } // skip junk nodes. if (reader.Name.Equals("featureClass")) { using ( StringReader elementReader = new StringReader(reader.ReadOuterXml())) { XmlSerializer deserializer = serializers[typeof (featureClassType)]; featureClasses.Add( (featureClassType) deserializer.Deserialize(elementReader)); } continue; // ReadOuterXml advances the reader, so don't read again. } if (reader.Name.Equals("feature")) { using ( StringReader elementReader = new StringReader(reader.ReadOuterXml())) { XmlSerializer deserializer = serializers[typeof (featureType)]; features.Add( (featureType) deserializer.Deserialize(elementReader)); } continue; // ReadOuterXml advances the reader, so don't read again. } log.write( "WARNING: unknown element '" + reader.Name + "' was skipped during parsing."); reader.Read(); // skip non-element-nodes and unknown-elements. } result.featureClasses = featureClasses.ToArray(); result.features = features.ToArray(); return result; } private XmlSerializer newSerializer(Type elementType) { XmlSerializer serializer = new XmlSerializer(elementType); serializer.UnknownNode += new XmlNodeEventHandler(handleUnknownNode); serializer.UnknownAttribute += new XmlAttributeEventHandler(handleUnknownAttribute); return serializer; } protected void handleUnknownNode(object sender, XmlNodeEventArgs e) { log.write( string.Format( "XML_ERROR: Unknown Node at line {0} position {1} : {2}\t{3}", e.LineNumber, e.LinePosition, e.Name, e.Text)); } protected void handleUnknownAttribute(object sender, XmlAttributeEventArgs e) { log.write( string.Format( "XML_ERROR: Unknown Attribute at line {0} position {1} : {2}='{3}'", e.LineNumber, e.LinePosition, e.Attr.Name, e.Attr.Value)); } } } 

    Просто подведем итоги и сделаем ответ более очевидным для тех, кто находит этот stream в google.

    До .NET 2 XmlTextReader был наиболее эффективным с точки зрения памяти XML-парсером, доступным в стандартном API (thanx Mitch 😉

    .NET 2 представил class XmlReader, который лучше снова. Это iterator с прямым доступом (немного похожий на парсер StAX). (thanx Cerebrus 😉

    И помните, что детишки любого экземпляра XML могут быть больше, чем около 500 тыс., НЕ ИСПОЛЬЗУЙТЕ ДОМ!

    Приветствует всех. Кит.

    Парсер SAX может быть тем, что вы ищете. SAX не требует, чтобы вы прочитали весь документ в памяти – он постепенно анализирует его и позволяет обрабатывать элементы по мере их поступления. Я не знаю, есть ли SAX-анализатор, предоставленный в .NET, но есть несколько вариантов с открытым исходным кодом, на которые вы могли бы обратить внимание:

    Вот связанный пост:

    • SAX vs XmlTextReader – SAX в C #

    Просто хотел добавить этот простой метод расширения в качестве примера использования XmlReader (как ответил Митч):

     public static bool SkipToElement (this XmlReader xmlReader, string elementName) { if (!xmlReader.Read ()) return false; while (!xmlReader.EOF) { if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == elementName) return true; xmlReader.Skip (); } return false; } 

    И использование:

     using (var xml_reader = XmlReader.Create (this.source.Url)) { if (!SkipToElement (xml_reader, "Root")) throw new InvalidOperationException ("XML element \"Root\" was not found."); if (!SkipToElement (xml_reader, "Users")) throw new InvalidOperationException ("XML element \"Root/Users\" was not found."); ... } 
    Interesting Posts

    Есть ли какая-либо библиотека C / C ++ для подключения к удаленному NTP-серверу?

    Строковый график в GnuPlot, где цвет линии является третьим столбцом в моем файле данных?

    Размер подсказки для Android EditText

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

    Что мне делать при запуске приложения триггеров, повторяющих бесконечный самозапуск установщика Windows?

    Android: Как включить / отключить пункт меню выбора при нажатии кнопки?

    Проводник Windows. Как большой файл может иметь значение «Размер на диске»? Что это значит

    Android Studio отмечает R красным цветом с сообщением об ошибке «не удается разрешить символ R», но assembly завершается успешно

    Как найти новейшие файлы в каталоге, включая подкаталоги?

    MySQL: Сортировка значений GROUP_CONCAT

    Зачем использовать Async / Await Over Normal Threading или Tasks?

    Почему люди так боятся использовать clone () (на коллекции и classы JDK)?

    Лучший способ передачи файлов через локальную сеть между двумя компьютерами Linux

    Использование IsAssignableFrom с открытыми типами

    Bitmap, Bitmap.recycle (), WeakReferences и garbage collection

    Давайте будем гением компьютера.