Какой XML-парсер следует использовать в С++?

У меня есть документы XML, которые мне нужны для синтаксического анализа и/или мне нужно создавать документы XML и записывать их в текст (файлы или память). Поскольку у стандартной библиотеки С++ нет библиотеки для этого, что я должен использовать?

Примечание.. Этот вопрос должен быть окончательным, С++ - часто задаваемым вопросом. Так что да, это дубликат других. Я не просто задавал эти другие вопросы, потому что они, как правило, просили что-то более конкретное. Этот вопрос более общий.

Ответ 1

Точно так же, как со стандартными библиотечными контейнерами, какая библиотека вы должны использовать, зависит от ваших потребностей. Здесь удобная блок-схема:

enter image description here

Итак, первый вопрос: что вам нужно?

Мне нужно полное соответствие XML

ОК, поэтому вам нужно обработать XML. Не игрушка XML, реального XML. Вы должны иметь возможность читать и писать всю спецификацию XML, а не только низколежащие, простые в анализе биты. Вам нужны пространства имен, DocTypes, подстановка объектов, работы. Спецификация XML W3C, в целом.

Следующий вопрос: должен ли ваш API соответствовать DOM или SAX?

Мне нужна точная DOM и/или SAX Conformance

Хорошо, так что вам действительно нужен API для DOM и/или SAX. Это не может быть просто синтаксический синтаксический анализатор SAX или сохраняемый парсер в стиле DOM. Это должен быть фактический DOM или фактический SAX, насколько это разрешено C++.

Ты выбрал:

Xerces

Это ваш выбор. Это в значительной степени единственный C++ XML-синтаксический анализатор/писатель, который имеет полный (или почти как C++), совместимый с DOM и SAX. Он также поддерживает XInclude, поддержку XML Schema и множество других функций.

Он не имеет реальных зависимостей. Он использует лицензию Apache.

Я не забочусь о DOM и/или SAX Conformance

Ты выбрал:

LibXML2

LibXML2 предлагает интерфейс C-стиля (если это вас действительно беспокоит, используйте Xerces), хотя интерфейс, по крайней мере, основан на объектах и легко обернут. Он предоставляет множество функций, таких как поддержка XInclude (с обратными вызовами, чтобы вы могли указать, откуда он получает файл), распознаватель XPath 1.0, RelaxNG и Schematron (хотя сообщения об ошибках оставляют желать лучшего), и так далее.

Он имеет зависимость от iconv, но его можно настроить без этой зависимости. Хотя это означает, что у вас будет более ограниченный набор возможных текстовых кодировок, которые он может проанализировать.

Он использует лицензию MIT.

Мне не нужно полное соответствие XML

Хорошо, так что полное соответствие XML не имеет для вас значения. Ваши XML-документы либо полностью находятся под вашим контролем, либо гарантированно используют "базовое подмножество" XML: нет пространств имен, сущностей и т.д.

Так что для вас важно? Следующий вопрос: что для вас важнее всего в работе с XML?

Максимальная производительность анализа XML

Ваше приложение должно принять XML и превратить его в структуры данных C++ так быстро, как это может произойти.

Ты выбрал:

RapidXML

Этот синтаксический анализатор XML - это именно то, что он говорит о жесте: быстрый XML. Он даже не занимается вытаскиванием файла в память; как это происходит, зависит от вас. Речь идет о синтаксическом анализе в ряд структур данных C++, к которым вы можете получить доступ. И он делает это примерно так же быстро, как требуется для сканирования байта файла байтом.

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

Кроме того, это парсер DOM-стиля. Поэтому для этого требуется, чтобы вы прочитали весь текст. Однако то, что он не делает, это скопировать любой из этого текста (обычно). То, как RapidXML получает большую часть своей скорости, - это ссылки на строки на месте. Это требует большего управления памятью с вашей стороны (вы должны сохранить эту строку в ожидании, пока RapidXML смотрит на нее).

RapidXML DOM - голые кости. Вы можете получить строковые значения для вещей. Вы можете искать атрибуты по имени. Это об этом. Нет никаких удобных функций, чтобы превращать атрибуты в другие значения (числа, даты и т.д.). Вы просто получаете струны.

Еще одним недостатком RapidXML является то, что для написания XML это очень больно. Это требует, чтобы вы делали много явного выделения памяти для имен строк, чтобы построить его DOM. Он предоставляет своего рода строковый буфер, но для этого все еще требуется много явной работы. Это, безусловно, функционально, но это боль в использовании.

Он использует лицензию MIT. Это библиотека только для заголовков без зависимостей.

  • Существует RapidXML "Патч GitHub", который позволяет ему также работать с пространствами имен.

Я забочусь о производительности, но не так много

Да, производительность важна для вас. Но, может быть, вам нужно что-то немного голые кости. Возможно, что-то, что может обрабатывать больше Unicode, или не требует такого большого количества управляемых пользователем управления памятью. Производительность по-прежнему важна, но вам нужно что-то немного менее прямое.

Ты выбрал:

PugiXML

Исторически это послужило источником вдохновения для RapidXML. Но два проекта расходятся, и Pugi предлагает больше возможностей, в то время как RapidXML полностью ориентирован на скорость.

PugiXML предлагает поддержку преобразования Unicode, поэтому, если у вас есть некоторые документы UTF-16 и вы хотите прочитать их как UTF-8, Pugi предоставит. У него даже есть реализация XPath 1.0, если вам это нужно.

Но Пуги все еще довольно быстро. Как и RapidXML, он не имеет зависимостей и распространяется под лицензией MIT.

Чтение огромных документов

Вам необходимо прочитать документы, размер которых измеряется в гигабайтах. Возможно, вы получаете их от stdin, кормили каким-то другим процессом. Или вы читаете их из массивных файлов. Или что угодно. Дело в том, что вам нужно не читать весь файл в памяти сразу, чтобы обработать его.

Ты выбрал:

LibXML2

API-интерфейс Xerces SAX будет работать в этом качестве, но LibXML2 здесь, потому что с ним немного легче работать. API SAX-стиля - это push-API: он начинает разбор потока и просто запускает события, которые вам нужно поймать. Вы вынуждены управлять контекстом, состоянием и т.д. Код, который читает API SAX-стиля, намного более распространен, чем можно было бы надеяться.

Объект LibXML2 xmlReader - это pull-API. Вы просите перейти к следующему узлу или элементу XML; вам не сказали. Это позволяет хранить контекст по своему усмотрению, обрабатывать разные объекты способом, который гораздо читабельнее в коде, чем куча обратных вызовов.

альтернативы

эмигрант

Expat - это хорошо известный парсер CN10, который использует API-интерфейс pull-parser. Это было написано Джеймсом Кларком.

Текущий статус активен. Самая последняя версия - 2.2.5, которая была выпущена в прошлом месяце (2017-10-31).

LlamaXML

Это реализация API стиля в стиле StAX. Это синтаксический анализатор, подобный xmlReader анализатору LibXML2 xmlReader.

Но он не обновлялся с 2005 года. Так снова, Caveat Emptor.

Поддержка XPath

XPath - это система для запроса элементов в дереве XML. Это удобный способ эффективного именования элемента или коллекции элемента с помощью общих свойств с использованием стандартизованного синтаксиса. Многие библиотеки XML предлагают поддержку XPath.

Здесь есть три варианта:

  • LibXML2: он обеспечивает полную поддержку XPath 1.0. Опять же, это C API, поэтому, если это вас беспокоит, есть альтернативы.
  • PugiXML: он поставляется с поддержкой XPath 1.0. Как и выше, это больше API C++, чем LibXML2, поэтому вам может быть более комфортно с ним.
  • TinyXML: он не поддерживает XPath, но есть библиотека TinyXPath, которая ее предоставляет. TinyXML претерпевает преобразование в версию 2.0, что значительно изменяет API, поэтому TinyXPath может не работать с новым API. Как и TinyXML, TinyXPath распространяется под лицензией zLib.

Просто сделайте задание

Таким образом, вы не заботитесь о правильности XML. Производительность не является проблемой для вас. Потоковая передача не имеет значения. Все, что вам нужно, это то, что получает XML в память и позволяет снова вставить его обратно на диск. Что вам нужно, это API.

Вы хотите, чтобы синтаксический анализатор XML был небольшим, простым в установке, тривиальным для использования и достаточно малым, чтобы не иметь значения для вашего возможного исполняемого размера.

Ты выбрал:

TinyXML

Я поместил TinyXML в этот слот, потому что это примерно так же просто, как и использование parsers XML. Да, это медленно, но это просто и понятно. Он имеет множество удобных функций для преобразования атрибутов и т.д.

Написание XML не проблема в TinyXML. Вы просто new некоторые объекты, прикрепить их вместе, отправить документ в std::ostream, и все счастливы.

Существует также кое-что из экосистемы, построенной вокруг TinyXML, с более удобным для итератора API и даже реализацией XPath 1.0, наложенной поверх нее.

TinyXML использует лицензию zLib, которая является более или менее лицензией MIT с другим именем.

Ответ 2

Существует другой подход к обработке XML, который вы, возможно, захотите рассмотреть, называется XML привязка данных. Особенно, если у вас уже есть формальная спецификация вашего словаря XML, например, в XML Schema.

Связывание данных XML позволяет использовать XML без фактического анализа или сериализации XML. Компилятор привязки данных автоматически генерирует весь низкоуровневый код и представляет анализируемые данные в виде классов С++, соответствующих вашему домену приложения. Затем вы работаете с этими данными, вызывая функции и работая с типами С++ (int, double и т.д.) Вместо сравнения строк и синтаксического анализа текста (это то, что вы делаете с низкоуровневыми API-интерфейсами XML, такими как DOM или SAX).

См., например, реализацию реализации привязки XML с открытым исходным кодом, которую я написал, CodeSynthesis XSD и для более легкая, свободная от зависимостей версия, CodeSynthesis XSD/е.

Ответ 4

В Secured Globe, Inc. мы используем rapidxml. Мы попробовали все остальные, но quickxml кажется лучшим выбором для нас.

Вот пример:

 rapidxml::xml_document<char> doc;
    doc.parse<0>(xmlData);
    rapidxml::xml_node<char>* root = doc.first_node();

    rapidxml::xml_node<char>* node_account = 0;
    if (GetNodeByElementName(root, "Account", &node_account) == true)
    {
        rapidxml::xml_node<char>* node_default = 0;
        if (GetNodeByElementName(node_account, "default", &node_default) == true)
        {
            swprintf(result, 100, L"%hs", node_default->value());
            free(xmlData);
            return true;
        }
    }
    free(xmlData);

Ответ 5

Еще одна заметка об Expat: стоит посмотреть на работу встроенных систем. Однако документация, которую вы, вероятно, найдете в Интернете, является древней и неправильной. Исходный код на самом деле имеет довольно тщательные комментарии на уровне функций, но для них будет разумным понимание.

Ответ 6

Хорошо, тогда. Я создал новый, так как ни один из этих списков не соответствовал моим потребностям.

Выгоды:

  1. Pull-parser Streaming API на низком уровне (Java StAX нравится)
  2. Исключения и режимы RTTI поддерживаются
  3. Ограничение использования памяти, поддержка больших файлов (проверено на 100 mib XMark файл, скорость зависит от аппаратного обеспечения)
  4. Поддержка UNICODE и автоматическое обнаружение для кодирования входного источника
  5. API высокого уровня для чтения в структуры/POCO
  6. Мета-программирующий API для записи и генерации XSD из структур/POCO с поддержкой структуры xml (атрибуты и теги вложенности) (для генерации XSD нужен RTTI, но он может использоваться только для отладки, чтобы сделать его один раз)
  7. C++ 11 - GCC и V C++ 15+

Недостатки:

  1. Проверка DTD и XSD еще не предоставлена
  2. Получение XML/XSD по протоколу HTTP/HTTPS выполняется, еще не сделано
  3. Новая библиотека

Проект дома