web-dev-qa-db-fra.com

Utilisation de Boost pour lire et écrire des fichiers XML

Existe-t-il un bon moyen (et un moyen simple aussi) d'utiliser Boost pour lire et écrire des fichiers XML?

Je n'arrive pas à trouver d'exemple simple pour lire des fichiers XML à l'aide de Boost. Pouvez-vous me montrer un exemple simple qui utilise Boost pour lire et écrire des fichiers XML?

Sinon Boost, existe-t-il une bibliothèque simple et efficace pour lire et écrire des fichiers XML que vous pouvez recommander? (ce doit être une bibliothèque C++)

68
Nuno

Vous devriez essayer pugixml Analyseur XML léger, simple et rapide pour C++

La meilleure chose à propos de pugixml est le support XPath , qui manque à TinyXML et RapidXML.

Citant l'auteur de RapidXML "Je voudrais remercier Arseny Kapoulkine pour son travail sur pugixml, qui a été une source d'inspiration pour ce projet" et "5% - 30% plus rapide que pugixml, l'analyseur XML le plus rapide que je connaisse" Il avait testé avec la version 0.3 de pugixml, qui a récemment atteint la version 0.42.

Voici un extrait de la documentation pugixml:

Les principales caractéristiques sont:

  • faible consommation de mémoire et fragmentation (la victoire sur pugxml est ~ 1,3 fois, TinyXML - ~ 2,5 fois, Xerces (DOM) - ~ 4,3 fois 1). Les nombres exacts peuvent être vus dans la section Comparaison avec les analyseurs existants.
  • vitesse d'analyse extrêmement élevée (la victoire sur pugxml est ~ 6 fois, TinyXML - ~ 10 fois, Xerces-DOM - ~ 17,6 fois 1
  • vitesse d'analyse extrêmement élevée (enfin, je me répète, mais c'est tellement rapide, qu'il surpasse 2,8 fois Expat au test XML) 2
  • plus ou moins conforme aux normes (il analysera correctement tout fichier conforme aux normes, à l'exception des problèmes liés à la DTD)
  • à peu près ignorant les erreurs (il ne s'étouffera pas avec quelque chose comme You & Me, comme l'expatrié; il analysera les fichiers avec des données dans un mauvais codage; et ainsi de suite)
  • interface propre (celle de pugxml fortement refactorisée)
  • plus ou moins compatible Unicode (en fait, il suppose un codage UTF-8 des données d'entrée, bien qu'il fonctionnera facilement avec ANSI - pas UTF-16 pour l'instant (voir Travaux futurs), avec des fonctions de conversion d'aide (UTF-8 <- > UTF-16/32 (quelle que soit la valeur par défaut pour std :: wstring & wchar_t))
  • code C++ entièrement standard (approuvé par le mode strict Comeau); la bibliothèque est multiplateforme (voir référence pour la liste des plateformes)
  • grande flexibilité. Vous pouvez contrôler de nombreux aspects de l'analyse des fichiers et de la construction de l'arborescence DOM via les options d'analyse.

D'accord, vous pourriez demander - quel est le problème? Tout est si mignon - c'est une solution petite, rapide, robuste et propre pour analyser XML. Que manque-t-il? Ok, nous sommes des développeurs équitables - voici donc une liste de défauts:

  • consommation de mémoire. Il bat tous les analyseurs basés sur DOM que je connaisse - mais lorsque l'analyseur SAX arrive, il n'y a aucune chance. Vous ne pouvez pas traiter un fichier XML de 2 Go avec moins de 4 Go de mémoire - et faites-le rapidement. Bien que pugixml se comporte mieux que tous les autres analyseurs basés sur DOM, donc si vous êtes coincé avec DOM, ce n'est pas un problème.
  • consommation de mémoire. Ok, je me répète. Encore. Lorsque d'autres analyseurs vous permettront de fournir un fichier XML dans un stockage constant (ou même en tant que zone mappée en mémoire), pugixml ne le fera pas. Vous devrez donc copier l'intégralité des données dans un stockage non constant. De plus, il devrait persister pendant la durée de vie de l'analyseur (les raisons de cela et plus sur les durées de vie sont écrites ci-dessous). Encore une fois, si vous êtes d'accord avec DOM - cela ne devrait pas être un problème, car la consommation globale de mémoire est inférieure (enfin, bien que vous ayez besoin d'un morceau de mémoire contigu, ce qui peut être un problème).
  • manque de validation, traitement DTD, espaces de noms XML, bonne gestion de l'encodage. Si vous en avez besoin - prenez MSXML ou XercesC ou quelque chose comme ça.
63
Cristian Adam

TinyXML est probablement un bon choix. Quant à Boost:

Il y a la bibliothèque Property_Tree dans le Boost Repository . Il a été accepté, mais le support semble faire défaut pour le moment (EDIT: Property_Tree fait maintenant partie de Boost depuis la version 1.41 , lisez la documentation = concernant sa fonctionnalité XML).

Daniel Nuffer a implémenté un analyseur xml pour Boost Spirit.

23
stephan

Il y a aussi TinyXML , qui est une belle et petite bibliothèque C++. Si vous recherchez une bibliothèque de niveau inférieur, RapidXML est un excellent point de départ.

16
Anteru

Boost utilise RapidXML comme décrit dans - chapitre Analyseur XML de la page Comment remplir un arbre de propriétés :

Malheureusement, il n'y a pas XML analyseur dans Boost au moment de la rédaction de cet article. La bibliothèque contient donc l'analyseur rapide et minuscule RapidXML (actuellement dans la version 1.13) pour fournir un support d'analyse XML. RapidXML ne prend pas entièrement en charge la norme XML; il n'est pas capable d'analyser les DTD et ne peut donc pas effectuer de substitution d'entité complète.

Veuillez également vous référer au tutoriel de boost XML .

Comme l'OP veut un "moyen simple d'utiliser boost pour lire et écrire des fichiers xml", je fournis ci-dessous un exemple très basique:

<main>
    <owner>Matt</owner>
    <cats>
        <cat>Scarface Max</cat>
        <cat>Moose</cat>
        <cat>Snowball</cat>
        <cat>Powerball</cat>
        <cat>Miss Pudge</cat>
        <cat>Needlenose</cat>
        <cat>Sweety Pie</cat>
        <cat>Peacey</cat>
        <cat>Funnyface</cat>
    </cats>
</main>

(les noms de chats viennent de page d'accueil de Matt Mahoney )

La structure correspondante en C++:

struct Catowner
{
    std::string           owner;
    std::set<std::string> cats;
};

read_xml() utilisation:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

Catowner load(const std::string &file)
{
    boost::property_tree::ptree pt;
    read_xml(file, pt);

    Catowner co;

    co.owner = pt.get<std::string>("main.owner");

    BOOST_FOREACH(
       boost::property_tree::ptree::value_type &v,
       pt.get_child("main.cats"))
       co.cats.insert(v.second.data());

    return co;
}

write_xml() utilisation:

void save(const Catowner &co, const std::string &file)
{
   boost::property_tree::ptree pt;

   pt.put("main.owner", co.owner);

   BOOST_FOREACH(
      const std::string &name, co.cats)
      pt.add("main.cats.cat", name);

   write_xml(file, pt);
}
10
olibre

Boost ne fournit pas d'atmosphère d'analyseur XML.

Poco XML (une partie des bibliothèques Poco C++ ) est bon et simple.

4
StackedCrooked

Eh bien, il n'y a pas de bibliothèque spécifique dans boost pour l'analyse XML, mais il existe de nombreuses alternatives, en voici quelques-unes: libxml , Xerces , Expat

Bien sûr, vous pouvez utiliser certaines des autres bibliothèques de boost pour vous aider à créer votre propre bibliothèque, mais ce sera probablement une entreprise.

Et voici n article entier sur le sujet par IBM.

4
Skurmedel

Il semblerait que la sérialisation de boost puisse lire et écrire des archives en XML, si cela est suffisant pour vos besoins.

XML plus simple avec Boost

4
Stuart

Définitivement utiliser TinyXML * pouce en l'air *

3
StfnoPad

Si vous recherchez uniquement la fonctionnalité DOM, il y a déjà quelques suggestions dans ce fil. Personnellement, je ne m'embêterais probablement pas avec une bibliothèque sans support XPath, et en C++, j'utiliserais Qt. Il y a aussi TinyXPath, et Arabica prétend avoir le support XPath, mais je ne peux rien dire à ce sujet.

2
Vladimir Prus

Jetez un oeil à Arabica

2
Nemanja Trifunovic

D'après mes expériences qui se cachent sur la liste de diffusion Boost, il apparaît que chaque fois que XML apparaît comme sujet, il est détourné vers une discussion sur Unicode. Cependant, étant donné qu'une bibliothèque Unicode potentielle se profile actuellement, je ne pense pas qu'il faudra trop de temps pour qu'une bibliothèque XML y apparaisse.

En attendant, moi aussi j'utilise TinyXML.

Lien intéressant sur RapidXML. Je vais y jeter un œil.

1
Kaz Dragon

Il y a un travail proposé par le GSoC pour améliorer la proposition existante de Boost.XML: https://github.com/stefanseefeld/boost.xml mais comme Andrzej l'a proposé, Boost.PropertyTree est bien pour cette tâche. En fonction naturellement de la taille xml et du support de validation nécessaire.

Il y a aussi une bibliothèque qui a été récemment proposée sur la liste de diffusion Boost: http://www.codesynthesis.com/projects/libstudxml/doc/intro.xhtml

1
daminetreg

Un avertissement. J'adore RapidXML, mais il a un bug très méchant lors de l'analyse UTF16. Certaines valeurs valides le font planter.

J'adorerais recommander pugixml - mais il manque le support de l'espace de noms, ce qui, je le sais, va me poser des problèmes.

1
Simon Featherstone

Et boost.spirit?

Ici , ils affichent un analyseur " Mini XML "

0
tagoma
<?xml version="1.0"?>
<Settings>
  <GroupA>
      <One>4</One>
      <Two>7</Two>
      <Three>9</Three> 
  </GroupA>
  <GroupA>
      <One>454</One>
      <Two>47</Two>
      <Three>29</Three> 
  </GroupA>
  <GroupB>
      <A>String A</A>
      <B>String B</B>  
  </GroupB>  
</Settings>

Il existe un moyen simple de lire XML avec BOOST. Cet exemple est basé sur std :: wstring:

#include <string> 
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>

bool CMyClass::ReadXML(std::wstring &full_path)
{
    using boost::property_tree::wptree;

    // Populate tree structure pt:
    wptree pt;
    std::wstringstream ss; ss << load_text_file(full_path); // See below for ref.
    read_xml(ss, pt);

    // Traverse pt:
    BOOST_FOREACH(wptree::value_type const& v, pt.get_child(L"Settings"))
    {
        if (v.first == L"GroupA")
        {
            unsigned int n1 = v.second.get<unsigned int>(L"One");
            unsigned int n2 = v.second.get<unsigned int>(L"Two");
            unsigned int n3= v.second.get<unsigned int>(L"Three");
        }
        else if (v.first == L"GroupB")
        {
            std::wstring wstrA = v.second.get<std::wstring>(L"A");
            std::wstring wstrB = v.second.get<std::wstring>(L"B");
        }
    };
}

La lecture des attributs est un peu plus compliquée.

-

Juste pour la référence:

std::wstring load_text_file(std::wstring &full_path)
{
    std::wifstream wif(full_path);

    wif.seekg(0, std::ios::end);
    buffer.resize(wif.tellg());
    wif.seekg(0);
    wif.read(buffer.data(), buffer.size());

    return buffer;
}
0
Amit G.