Какой анализатор XML я должен использовать в C++?
У меня есть XML-документы, которые мне нужно проанализировать и / или мне нужно создать XML-документы и записать их в текст (файлы или память). Что стандартная библиотека C++ не имеет библиотеки для этого, что я должен использовать?
Примечание: это должно быть окончательным вопросом C++-FAQ для этого. Так что да, это дубликат других. Я не просто присваивал эти другие вопросы, потому что они имели тенденцию задавать что-то немного более конкретное. Этот вопрос более общий.
6 ответов
Как и со стандартными контейнерами библиотеки, какую библиотеку вам следует использовать, зависит от ваших потребностей. Вот удобная блок-схема:
Итак, первый вопрос: что вам нужно?
Мне нужно полное соответствие XML
Итак, вам нужно обработать XML. Не игрушечный XML, настоящий XML. Вы должны уметь читать и записывать все спецификации XML, а не только низколежащие, легко разбираемые биты. Вам нужны Пространства имен, DocTypes, замена сущностей, все работы. Спецификация W3C XML в полном объеме.
Следующий вопрос: должен ли ваш API соответствовать DOM или SAX?
Мне нужно точное соответствие DOM и / или SAX
Итак, вам действительно нужно, чтобы API был DOM и / или SAX. Это не может быть просто push-анализатор в стиле SAX или сохраненный синтаксический анализатор в стиле DOM. Это должен быть фактический DOM или фактический SAX, если это позволяет C++.
Ты выбрал:
Это ваш выбор. Это практически единственный синтаксический анализатор / писатель C++ XML, имеющий полное (или настолько близкое, насколько позволяет C++) соответствие DOM и SAX. Он также имеет поддержку XInclude, поддержку XML-схемы и множество других функций.
У него нет реальных зависимостей. Он использует лицензию Apache.
Меня не волнует соответствие DOM и / или SAX
Ты выбрал:
LibXML2 предлагает интерфейс в стиле C (если вас это действительно беспокоит, используйте Xerces), хотя интерфейс по крайней мере в некоторой степени основан на объектах и легко оборачивается. Он предоставляет множество функций, таких как поддержка XInclude (с обратными вызовами, чтобы вы могли сказать ему, откуда он получает файл), распознаватель XPath 1.0, поддержка RelaxNG и Schematron (хотя сообщения об ошибках оставляют желать лучшего), и так далее.
У него есть зависимость от iconv, но его можно настроить без этой зависимости. Хотя это означает, что у вас будет более ограниченный набор возможных кодировок текста, которые он может анализировать.
Он использует лицензию MIT.
Мне не нужно полное соответствие XML
Итак, полное соответствие XML не имеет значения для вас. Ваши XML-документы либо полностью находятся под вашим контролем, либо гарантированно используют "базовое подмножество" XML: никаких пространств имен, сущностей и т. Д.
Так что для вас важно? Следующий вопрос: что для вас самое важное в работе с XML?
Максимальная производительность парсинга XML
Ваше приложение должно взять XML и превратить его в структуры данных C++ настолько быстро, насколько возможно это преобразование.
Ты выбрал:
Этот синтаксический анализатор XML именно то, что он говорит о жестяной коробке: быстрый XML. Это даже не имеет дело с извлечением файла в память; как это происходит, зависит от вас. Что он делает, так это разбирает его на ряд структур данных C++, к которым вы можете получить доступ. И это происходит примерно так же быстро, как и сканирование файла за байтом.
Конечно, нет такого понятия, как бесплатный обед. Как и большинство синтаксических анализаторов XML, которые не заботятся о спецификации XML, Rapid XML не затрагивает пространства имен, типы документов, сущности (за исключением символьных сущностей и 6 основных XML) и так далее. Так что в основном узлы, элементы, атрибуты и тому подобное.
Кроме того, это синтаксический анализатор в стиле DOM. Поэтому требуется, чтобы вы прочитали весь текст. Однако он не копирует этот текст (обычно). RapidXML получает большую часть своей скорости, обращаясь к строкам на месте. Это требует большего управления памятью с вашей стороны (вы должны поддерживать эту строку, пока RapidXML просматривает ее).
DOM RapidXML является голым. Вы можете получить строковые значения для вещей. Вы можете искать атрибуты по имени. Вот и все. Нет удобных функций для преобразования атрибутов в другие значения (числа, даты и т. Д.). Вы просто получаете строки.
Еще один недостаток RapidXML в том, что это болезненно для написания XML. Это требует, чтобы вы сделали много явного выделения памяти имен строк, чтобы построить его DOM. Это обеспечивает своего рода строковый буфер, но это все еще требует много явной работы с вашей стороны. Это, конечно, функционально, но это боль в использовании.
Он использует лицензию MIT. Это библиотека только для заголовков без каких-либо зависимостей.
- Существует RapidXML "GitHub patch", который позволяет ему также работать с пространствами имен.
Я забочусь о производительности, но не так уж много
Да, производительность важна для вас. Но, может быть, вам нужно что-то чуть менее голое. Может быть, что-то, что может обрабатывать больше Unicode, или не требует так много контролируемого пользователем управления памятью. Производительность по-прежнему важна, но вы хотите что-то немного менее прямое.
Ты выбрал:
Исторически это послужило вдохновением для RapidXML. Но оба проекта разошлись: Pugi предлагает больше возможностей, а RapidXML полностью ориентирован на скорость.
PugiXML предлагает поддержку преобразования Unicode, поэтому, если у вас есть несколько документов в формате UTF-16 и вы хотите прочитать их как UTF-8, Pugi предоставит. Он даже имеет реализацию XPath 1.0, если вам нужна такая вещь.
Но Пуги все еще довольно быстр. Как и RapidXML, он не имеет зависимостей и распространяется под лицензией MIT.
Чтение огромных документов
Вам необходимо прочитать документы, размер которых измеряется в гигабайтах. Может быть, вы получаете их от стандартного ввода, питаясь каким-то другим процессом. Или вы читаете их из массивных файлов. Или что угодно. Дело в том, что вам не нужно читать весь файл в память сразу, чтобы обработать его.
Ты выбрал:
LibXML2
API-интерфейс Xerces в стиле SAX будет работать в этом качестве, но LibXML2 здесь, потому что с ним немного проще работать. API в стиле SAX - это push-API: он начинает синтаксический анализ потока и просто запускает события, которые вы должны перехватить. Вы вынуждены управлять контекстом, состоянием и так далее. Код, который читает API в стиле SAX, гораздо более распространен, чем можно было бы надеяться.
LibXML2-х xmlReader
Объект представляет собой pull-API. Вы просите перейти к следующему узлу или элементу XML; тебе не сказали. Это позволяет вам сохранять контекст так, как вы считаете нужным, обрабатывать различные объекты так, чтобы код был гораздо более читабельным, чем набор обратных вызовов.
альтернативы
Expat - это хорошо известный синтаксический анализатор C++, использующий API-интерфейс pull-parser. Это было написано Джеймсом Кларком.
Это текущий статус активен. Самая последняя версия - 2.2.5, выпущенная в прошлом месяце (2017-10-31).
Это реализация API в стиле StAX. Это парсер, похожий на LibXML2 xmlReader
синтаксический анализатор.
Но он не обновлялся с 2005 года. Опять же, Caveat Emptor.
Поддержка XPath
XPath - это система запросов к элементам в дереве XML. Это удобный способ эффективно именовать элемент или коллекцию элементов общими свойствами, используя стандартизированный синтаксис. Многие библиотеки XML предлагают поддержку XPath.
Здесь есть три варианта:
- LibXML2: обеспечивает полную поддержку XPath 1.0. Опять же, это C API, поэтому, если вас это беспокоит, есть альтернативы.
- PugiXML: также поставляется с поддержкой XPath 1.0. Как и выше, это скорее C++ API, чем LibXML2, так что вам может быть удобнее с ним.
- TinyXML: он не поставляется с поддержкой XPath, но есть библиотека TinyXPath, которая предоставляет его. TinyXML подвергается преобразованию в версию 2.0, что значительно меняет API, поэтому TinyXPath может не работать с новым API. Как и сам TinyXML, TinyXPath распространяется под лицензией zLib.
Просто сделай работу
Таким образом, вы не заботитесь о правильности XML. Производительность не проблема для вас. Потоковое не имеет значения. Все, что вам нужно, это что-то, что помещает XML в память и позволяет вам снова вставить его на диск. Что вас волнует, так это API.
Вам нужен синтаксический анализатор XML, который будет небольшим, простым в установке, простым в использовании и достаточно маленьким, чтобы не зависеть от размера вашего исполняемого файла.
Ты выбрал:
Я поместил TinyXML в этот слот, потому что он так же прост в использовании, как и парсеры XML. Да, это медленно, но это просто и очевидно. Он имеет много удобных функций для преобразования атрибутов и так далее.
Написание XML не проблема в TinyXML. Ты только new
некоторые объекты, соедините их вместе, отправьте документ std::ostream
и все счастливы.
Существует также что-то вроде экосистемы, построенной вокруг TinyXML, с более дружественным к итератору API и даже многоуровневой реализацией XPath 1.0.
TinyXML использует лицензию zLib, которая является более или менее лицензией MIT с другим именем.
Существует другой подход к обработке XML, который вы можете рассмотреть, который называется привязка данных XML. Особенно, если у вас уже есть формальная спецификация вашего словаря XML, например, в XML Schema.
Привязка данных XML позволяет использовать XML без какого-либо анализа или сериализации XML. Компилятор привязки данных автоматически генерирует весь низкоуровневый код и представляет проанализированные данные в виде классов C++, соответствующих области вашего приложения. Затем вы работаете с этими данными, вызывая функции и работая с типами C++ (int, double и т. Д.) Вместо сравнения строк и синтаксического анализа текста (что вы делаете с низкоуровневыми API доступа к XML, такими как DOM или SAX).
См., Например, реализацию связывания данных с открытым исходным кодом XML, которую я написал, CodeSynthesis XSD и, для более легкой, свободной от зависимостей версии, CodeSynthesis XSD / e.
Хорошо, тогда. Я создал новый, так как ни один из списка не соответствовал моим потребностям.
Выгоды:
- Потоковый API-интерфейс Pull-parser на низком уровне (как Java StAX)
- Исключения и поддерживаемые режимы RTTI
- Ограничение на использование памяти, поддержка больших файлов (проверено с использованием файла XMark 100 Мб, скорость зависит от аппаратного обеспечения)
- Поддержка UNICODE и автоопределение для кодирования входного источника
- API высокого уровня для чтения в структурах /POCO
- API метапрограммирования для написания и генерации XSD из структур /POCO с поддержкой структуры xml (атрибутов и вложенных тегов) (для генерации XSD требуется RTTI, но его можно использовать только при отладке, чтобы сделать его один раз)
- C++ 11 - GCC и VC++ 15+
Недостатки:
- Проверка DTD и XSD еще не предоставлена
- Получение XML/XSD по HTTP/HTTPS в процессе, еще не сделано
- Новая библиотека
В Secured Globe, Inc. мы используем rapidxml. Мы перепробовали все остальные, но fastxml, кажется, лучший выбор для нас.
Вот пример:
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);
Еще одно замечание о Expat: стоит посмотреть на работу встроенных систем. Однако документация, которую вы, вероятно, найдете в Интернете, древняя и неправильная. Исходный код на самом деле содержит довольно подробные комментарии на уровне функций, но для их понимания потребуется некоторое время.
Поставь и мою.
http://www.codeproject.com/Articles/998388/XMLplusplus-version-The-Cplusplus-update-of-my-XML
Нет возможностей проверки XML, но быстро.