Какой анализатор XML я должен использовать в C ++? [закрыто]

344

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

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

Николь Болас
источник
Мне нравится tiCpp code.google.com/p/ticpp , документы не очень хороши (пока?), Но мне нравится библиотека, хороший чистый код.
Я написал свой собственный github.com/igagis/mikroxml
igagis

Ответы:

679

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

введите описание изображения здесь

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

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

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

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

Мне нужно точное соответствие DOM и / или SAX

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

Ты выбрал:

Xerces

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

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

Меня не волнует соответствие DOM и / или SAX

Ты выбрал:

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 не затрагивает пространства имен, типы документов, сущности (за исключением символьных сущностей и 6 основных XML) и так далее. Так что в основном узлы, элементы, атрибуты и тому подобное.

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

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

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

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

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

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

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

Ты выбрал:

PugiXML

Исторически это послужило вдохновением для 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.9, выпущенная (2019-09-25).

LlamaXML

Это реализация API в стиле StAX. Это парсер, похожий на xmlReaderпарсер LibXML2 .

Но он не обновлялся с 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

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

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

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

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

Николь Болас
источник
6
Это немного похоже на копирование-вставку. Можете ли вы связать исходный документ?
Джоэл
28
@Joel: довольно часто, когда кто-то отвечает на свой собственный вопрос длинным постом, это происходит потому, что он следует духу советов Джеффа - особенно потому, что вопрос, который выглядит так себе, часто можно закрыть, прежде чем хороший ответ сможет быть отправленным, если человек пишет ответ прямо тогда и там. Потратив некоторое время на подготовку ответа, прежде чем он задал вопрос :) Ник предоставит нам всем отличную кандидатуру для вопросов Close-> Duplicate в будущем.
Sarnold
28
@Joel: боюсь, я не могу. Это был просто временный документ, который я скопировал в Notepad ++. Я никогда не сохранял его, поэтому не могу связать вас с ним;)
Никол Болас
6
Стоит упомянуть более новую версию TinyXML: TinyXML-2 использует API, аналогичный TinyXML-1, и те же богатые тестовые примеры. Но реализация парсера полностью переписана, чтобы сделать его более подходящим для использования в игре. Он использует меньше памяти, работает быстрее и использует очень мало памяти.
Джонбейкерс
6
Мне нравится этот вопрос и ответ, но я нахожу его слишком предвзятым для Unix. Нет упоминаний о MSXML и XmlLite? Если причиной исключения таких проблем является мобильность с помощью нескольких платформ, это должно быть четко указано в вопросе и ответе. (В противном случае некоторые люди могут в конечном итоге выбрать, например, Libxml2 для проекта только для Windows, который требует головной боли, которых можно было бы легко избежать.)
Scrontch
17

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

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

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

Борис Колпаков
источник
13
Я не возражаю против этой статьи, но политика SO утверждает, что если вы предлагаете что-то, что написали, вы должны упомянуть, что написали это в интересах полного раскрытия.
Никол Болас
@Nicol Я отредактировал это в ответ.
Дж.Бентли
Возможно, полезен этот список, но я не смог выяснить, кто автор (ы) этого списка (без публичного раскрытия я не могу увидеть, являются ли описания и оценки значимыми). Возможно, можно взглянуть на рабочую группу по связыванию данных W3C, которая перечисляет несколько инструментов связывания данных, которые являются общественным достоянием и использовались для тестирования и составления отчетов (полное раскрытие: я не связан с CodeSynthesis, я помог gsoap, перечисленному в W3C инструменты).
Доктор Алекс RE
1

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

точка остановки
источник
0

Поставь и мою.

http://www.codeproject.com/Articles/998388/XMLplusplus-version-The-Cplusplus-update-of-my-XML

Нет возможностей проверки XML, но быстро.

Майкл Чурдакис
источник
2
Это быстрее или более широко используется, чем RapidXML? Или PugiXML? Доменное пространство для «быстрого, не полностью XML» синтаксического анализатора C ++ было довольно хорошо освещено.
Николь Болас
0

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

Преимущества:

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

Недостатки:

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

Проект дома

Виктор Губин
источник
1
Не могли бы вы добавить тесты?
Вадим Перетокин
-1

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

Вот пример:

 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);
Майкл Хефрати
источник