Quel analyseur XML dois-je utiliser en C ++? [fermé]

344

J'ai des documents XML que j'ai besoin d'analyser et / ou j'ai besoin de créer des documents XML et de les écrire dans du texte (fichiers ou mémoire). Étant donné que la bibliothèque standard C ++ n'a pas de bibliothèque pour cela, que dois-je utiliser?

Remarque: Ceci est destiné à être une question définitive de style C ++ - FAQ pour cela. Alors oui, c'est un double des autres. Je ne me suis pas simplement approprié ces autres questions parce qu'elles avaient tendance à demander quelque chose d'un peu plus spécifique. Cette question est plus générique.

Nicol Bolas
la source
J'aime tiCpp code.google.com/p/ticpp , les documents ne sont pas géniaux (encore?), Mais j'aime la bibliothèque, joli code propre.
J'ai écrit mon propre github.com/igagis/mikroxml
igagis

Réponses:

679

Tout comme avec les conteneurs de bibliothèque standard, la bibliothèque que vous devez utiliser dépend de vos besoins. Voici un organigramme pratique:

entrez la description de l'image ici

La première question est donc la suivante: de quoi avez-vous besoin?

J'ai besoin d'une conformité XML complète

OK, vous devez donc traiter XML. Ce n'est pas un jouet XML, un vrai XML. Vous devez être en mesure de lire et d'écrire toutes les spécifications XML, pas seulement les bits de faible taille et faciles à analyser. Vous avez besoin d'espaces de noms, de DocTypes, de substitution d'entités, de travaux. La spécification XML W3C, dans son intégralité.

La question suivante est: votre API doit-elle être conforme à DOM ou SAX?

J'ai besoin d'une conformité DOM et / ou SAX exacte

OK, vous avez donc vraiment besoin que l'API soit DOM et / ou SAX. Il ne peut pas simplement s'agir d'un analyseur push de style SAX ou d'un analyseur conservé de style DOM. Il doit s'agir du DOM réel ou du SAX réel, dans la mesure où C ++ le permet.

Tu as choisi:

Xerces

C'est ton choix. C'est à peu près le seul analyseur / graveur XML C ++ qui a une conformité complète (ou aussi proche que C ++ le permet) DOM et SAX. Il prend également en charge XInclude, la prise en charge du schéma XML et une pléthore d'autres fonctionnalités.

Il n'a pas de réelles dépendances. Il utilise la licence Apache.

Je me fiche de la conformité DOM et / ou SAX

Tu as choisi:

LibXML2

LibXML2 propose une interface de style C (si cela vous dérange vraiment, allez utiliser Xerces), bien que l'interface soit au moins quelque peu basée sur des objets et facilement encapsulée. Il fournit de nombreuses fonctionnalités, comme la prise en charge de XInclude (avec des rappels pour que vous puissiez lui dire d'où il tire le fichier), un reconnaisseur XPath 1.0, la prise en charge de RelaxNG et Schematron (bien que les messages d'erreur laissent beaucoup à désirer), et ainsi de suite.

Il a une dépendance sur iconv, mais il peut être configuré sans cette dépendance. Bien que cela signifie que vous disposerez d'un ensemble plus limité d'encodages de texte possibles qu'il pourra analyser.

Il utilise la licence MIT.

Je n'ai pas besoin d'une conformité XML complète

OK, donc la conformité XML complète n'a pas d'importance pour vous. Vos documents XML sont entièrement sous votre contrôle ou sont garantis pour utiliser le "sous-ensemble de base" de XML: pas d'espaces de noms, d'entités, etc.

Alors qu'est-ce qui vous importe? La question suivante est: Quelle est la chose la plus importante pour vous dans votre travail XML?

Performances d'analyse XML maximales

Votre application doit prendre XML et le transformer en infrastructures de données C ++ aussi rapidement que cette conversion peut se produire.

Tu as choisi:

RapidXML

Cet analyseur XML est exactement ce qu'il dit sur l'étain: XML rapide. Il ne traite même pas de l'extraction du fichier en mémoire; comment cela se fait dépend de vous. Ce qu'il traite, c'est l'analyse de cela en une série de structures de données C ++ auxquelles vous pouvez accéder. Et il le fait aussi rapidement qu'il le faut pour analyser le fichier octet par octet.

Bien sûr, un déjeuner gratuit n'existe pas. Comme la plupart des analyseurs XML qui ne se soucient pas de la spécification XML, Rapid XML ne touche pas les espaces de noms, les DocTypes, les entités (à l'exception des entités de caractères et des 6 entités XML de base), etc. Donc, fondamentalement, les nœuds, les éléments, les attributs, etc.

Il s'agit également d'un analyseur de style DOM. Il faut donc que vous lisiez tout le texte. Cependant, ce qu'il ne fait pas, c'est de copier tout ce texte (généralement). La façon dont RapidXML obtient la plupart de sa vitesse est en se référant aux chaînes en place . Cela nécessite plus de gestion de la mémoire de votre part (vous devez garder cette chaîne en vie pendant que RapidXML la regarde).

Le DOM de RapidXML est simple. Vous pouvez obtenir des valeurs de chaîne pour les choses. Vous pouvez rechercher des attributs par nom. C'est à peu près ça. Il n'y a pas de fonctions pratiques pour transformer les attributs en d'autres valeurs (nombres, dates, etc.). Vous obtenez juste des cordes.

Un autre inconvénient de RapidXML est qu'il est pénible pour écrire du XML. Il vous oblige à faire beaucoup d'allocation de mémoire explicite des noms de chaîne afin de construire son DOM. Il fournit une sorte de tampon de chaîne, mais cela nécessite encore beaucoup de travail explicite de votre part. C'est certainement fonctionnel, mais c'est pénible à utiliser.

Il utilise la licence MIT. Il s'agit d'une bibliothèque uniquement en-tête sans dépendances.

Je me soucie de la performance mais pas tant que ça

Oui, la performance compte pour vous. Mais peut-être avez-vous besoin de quelque chose d'un peu moins dépouillé. Peut-être quelque chose qui peut gérer plus d'Unicode, ou qui ne nécessite pas autant de gestion de mémoire contrôlée par l'utilisateur. Les performances sont toujours importantes, mais vous voulez quelque chose d'un peu moins direct.

Tu as choisi:

PugiXML

Historiquement, cela a servi d'inspiration pour RapidXML. Mais les deux projets ont divergé, Pugi offrant plus de fonctionnalités, tandis que RapidXML se concentre entièrement sur la vitesse.

PugiXML offre un support de conversion Unicode, donc si vous avez des documents UTF-16 et que vous souhaitez les lire en UTF-8, Pugi vous fournira. Il a même une implémentation XPath 1.0, si vous avez besoin de ce genre de chose.

Mais Pugi est encore assez rapide. Comme RapidXML, il n'a pas de dépendances et est distribué sous la licence MIT.

Lire d'énormes documents

Vous devez lire des documents mesurés en gigaoctets . Peut-être que vous les obtenez de stdin, alimentés par un autre processus. Ou vous les lisez à partir de fichiers volumineux. Ou peu importe. Le fait est que ce dont vous avez besoin est de ne pas avoir à lire tout le fichier en mémoire d'un coup pour le traiter.

Tu as choisi:

LibXML2

L'API de style SAX de Xerces fonctionnera dans cette capacité, mais LibXML2 est là parce que c'est un peu plus facile à utiliser. Une API de style SAX est une API push: elle commence à analyser un flux et déclenche simplement les événements que vous devez intercepter. Vous êtes obligé de gérer le contexte, l'état, etc. Le code qui lit une API de style SAX est beaucoup plus répandu qu'on ne pourrait l'espérer.

L' xmlReaderobjet de LibXML2 est une pull-API. Vous demandez d'aller au prochain nœud ou élément XML; on ne vous le dit pas. Cela vous permet de stocker le contexte comme bon vous semble, pour gérer différentes entités d'une manière beaucoup plus lisible dans le code qu'un tas de rappels.

Alternatives

Expat

Expat est un analyseur C ++ bien connu qui utilise une API pull-parser. Il a été écrit par James Clark.

Son état actuel est actif. La version la plus récente est la 2.2.9, qui a été publiée le (2019-09-25).

LlamaXML

Il s'agit d'une implémentation d'une API de style StAX. Il s'agit d'un analyseur par pull, similaire à l' xmlReaderanalyseur de LibXML2 .

Mais il n'a pas été mis à jour depuis 2005. Encore une fois, Caveat Emptor.

Prise en charge XPath

XPath est un système pour interroger des éléments dans une arborescence XML. C'est un moyen pratique de nommer efficacement un élément ou une collection d'éléments par des propriétés communes, en utilisant une syntaxe standardisée. De nombreuses bibliothèques XML offrent le support XPath.

Il y a effectivement trois choix ici:

  • LibXML2 : il fournit une prise en charge complète de XPath 1.0. Encore une fois, c'est une API C, donc si cela vous dérange, il existe des alternatives.
  • PugiXML : Il est également compatible avec XPath 1.0. Comme ci-dessus, il s'agit plus d'une API C ++ que de LibXML2, vous pouvez donc être plus à l'aise avec elle.
  • TinyXML : Il ne vient pas avec le support XPath, mais il y a la bibliothèque TinyXPath qui le fournit. TinyXML subit une conversion vers la version 2.0, qui modifie considérablement l'API, donc TinyXPath peut ne pas fonctionner avec la nouvelle API. Comme TinyXML lui-même, TinyXPath est distribué sous la licence zLib.

Faites simplement le travail

Donc, vous ne vous souciez pas de l'exactitude XML. La performance n'est pas un problème pour vous. Le streaming n'est pas pertinent. Tout ce que vous voulez, c'est quelque chose qui obtient XML en mémoire et vous permet de le coller à nouveau sur le disque. Ce qui vous intéresse, c'est l'API.

Vous voulez un analyseur XML qui sera petit, facile à installer, trivial à utiliser et suffisamment petit pour ne pas être pertinent pour la taille de votre éventuel exécutable.

Tu as choisi:

TinyXML

J'ai mis TinyXML dans cet emplacement car il est à peu près aussi simple à utiliser que les analyseurs XML. Oui, c'est lent, mais c'est simple et évident. Il a beaucoup de fonctions pratiques pour convertir des attributs et ainsi de suite.

L'écriture XML n'est pas un problème dans TinyXML. Vous venez de newmonter quelques objets, de les attacher ensemble, d'envoyer le document à un std::ostream, et tout le monde est content.

Il y a aussi quelque chose d'un écosystème construit autour de TinyXML, avec une API plus conviviale pour les itérateurs, et même une implémentation XPath 1.0 superposée.

TinyXML utilise la licence zLib, qui est plus ou moins la licence MIT avec un nom différent.

Nicol Bolas
la source
6
Cela ressemble un peu à un copier-coller. Pouvez-vous lier le document source?
Joel
28
@Joel: assez souvent, lorsque quelqu'un répond à sa propre question avec un bon long message, c'est parce qu'il suit l'esprit de Jeff - en particulier parce que ce qui ressemble à une question comme ça peut souvent être fermé avant qu'une bonne réponse ne puisse être affiché, si la personne écrit la réponse tout de suite. En prenant le temps de préparer une réponse avant qu'il ne pose la question :) Nicol nous fournit à tous un excellent candidat pour les questions Close-> Duplicate à l'avenir.
sarnold
28
@ Joel: J'ai bien peur de ne pas pouvoir. C'était juste un document temporaire à partir duquel j'ai copié dans Notepad ++. Je ne l'ai jamais enregistré, donc je ne peux pas vous lier à lui;)
Nicol Bolas
6
Il peut être utile de mentionner la nouvelle version de TinyXML: TinyXML-2 utilise une API similaire à TinyXML-1 et les mêmes cas de test riches. Mais l'implémentation de l'analyseur est complètement réécrite pour le rendre plus approprié pour une utilisation dans un jeu. Il utilise moins de mémoire, est plus rapide et utilise très peu d'allocations de mémoire.
johnbakers
6
J'aime cette question et sa réponse, mais je la trouve trop orientée Unix. Aucune mention de MSXML et XmlLite? Si la portabilité multi-palt est votre raison d'exclure ceux-ci, alors cela devrait être clairement mentionné dans la question et la réponse. (Sinon, certaines personnes pourraient finir par choisir par exemple Libxml2 pour un projet Windows uniquement, qui demande des maux de tête qui auraient facilement pu être évités.)
Scrontch
17

Il existe une autre approche de la gestion du XML que vous voudrez peut-être envisager, appelée liaison de données XML. Surtout si vous avez déjà une spécification formelle de votre vocabulaire XML, par exemple, dans XML Schema.

La liaison de données XML vous permet d'utiliser XML sans effectuer aucune analyse ou sérialisation XML. Un compilateur de liaison de données génère automatiquement tout le code de bas niveau et présente les données analysées sous forme de classes C ++ qui correspondent à votre domaine d'application. Vous travaillez ensuite avec ces données en appelant des fonctions et en travaillant avec des types C ++ (int, double, etc.) au lieu de comparer des chaînes et d'analyser du texte (ce que vous faites avec les API d'accès XML de bas niveau telles que DOM ou SAX).

Voir, par exemple, une implémentation de liaison de données XML open source que j'ai écrite, CodeSynthesis XSD et, pour une version plus légère et sans dépendance, CodeSynthesis XSD / e .

Boris Kolpackov
la source
13
Cela ne me dérange pas, mais la politique de SO stipule que si vous suggérez quelque chose que vous avez écrit, vous devez mentionner que vous l'avez écrit, dans l'intérêt d'une divulgation complète.
Nicol Bolas
@Nicol Je l'ai édité dans la réponse.
JBentley
Cette liste est peut-être utile, mais je n'ai pas pu savoir qui sont les auteurs de cette liste (sans divulgation publique, je ne peux pas voir si les descriptions et les évaluations sont significatives). On peut peut-être regarder le groupe de travail sur la liaison de données du W3C qui répertorie plusieurs outils de liaison de données qui sont dans le domaine public et qui ont été utilisés pour les tests et les rapports (divulgation complète: je ne suis pas affilié à CodeSynthesis, j'ai aidé gsoap répertorié avec le W3C outils).
Dr.Alex RE
1

Une autre remarque sur Expat: cela vaut la peine de regarder pour le travail sur les systèmes embarqués. Cependant, la documentation que vous trouverez probablement sur le Web est ancienne et erronée. Le code source a en fait des commentaires assez approfondis au niveau de la fonction, mais il leur faudra un peu de lecture pour avoir du sens.

point d'arrêt
la source
0

Alors ok. J'en ai créé un nouveau, car aucune de la liste ne répondait à mes besoins.

Avantages:

  1. Pull-parser Streaming API au bas niveau ( comme Java StAX )
  2. Exceptions et modes RTTI pris en charge
  3. Limite d'utilisation de la mémoire, prise en charge des fichiers volumineux (testé avec un fichier XMark de 100 mib de, la vitesse dépend du matériel)
  4. Prise en charge UNICODE et détection automatique pour l'encodage de la source d'entrée
  5. API de haut niveau pour la lecture dans les structures / POCO
  6. API de méta-programmation pour l'écriture et la génération de XSD à partir de structures / POCO avec prise en charge de la structure xml (attributs et balises d'imbrication) (la génération XSD nécessite RTTI, mais ne peut être utilisée que sur le débogage pour le faire une fois)
  7. C ++ 11 - GCC et VC ++ 15+

Désavantages:

  1. Validation DTD et XSD non encore fournies
  2. Obtention de XML / XSD par HTTP / HTTPS en cours, pas encore terminée
  3. Nouvelle bibliothèque

Accueil du projet

Victor Gubin
la source
1
Pourriez-vous ajouter des repères?
Vadim Peretokin
-1

Dans Secured Globe , Inc., nous utilisons rapidxml . Nous avons essayé tous les autres mais rapidxml semble être le meilleur choix pour nous.

Voici un exemple:

 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);
Michael Haephrati
la source