OVH Cloud OVH Cloud

XML en C++ : générer le xml et le parser

101 réponses
Avatar
noone
Bonjour,

je débute en C++ (j'ai fait un peu de C# avant)
L'avantage du C# était de pouvoir sérialiser facilement des objets c'est
à dire les stocker en XML.

Je ne sais pas trop comment m'y prendre en C++.

Quelle librairie utiliser (dans un projet utilisant déjà wxWidgets pour
l'interface graphique) ?

Pour les stocker je fais ceci :

// ===============================

#include <iostream> // pour cout
#include <fstream> // pour ofstream

using namespace std;

class Complexe {
public:
double x;
double y;

void Show()
{
cout << this->x << "+i*" << this->y << endl;
}
};

ostream & operator << (ostream & o,const Complexe & c)
{
return o
<< "<?xml version=\"1.0\"?>" << endl
<< "<Complexe" << " "
<< "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" << endl
<< "<Re>" << c.x << "</Re>" << endl
<< "<Im>" << c.y << "</Im>" << endl
<< "</Complexe>" << endl;
}


int main()
{
Complexe cplx;
cplx.x=1;
cplx.y=2;

cplx.Show();

ofstream ofs("cplx.xml");

ofs << cplx << endl;
cout << cplx << endl;
}

// ======================


C'est un peu lourd à gérer non ?

Donc en clair avez vous une technique pour générer du xml simplement (et
avec fiabilité) ?

Comment parser ensuite ce fichier XML ?

Merci d'avance de vos réponses.

10 réponses

Avatar
Gabriel Dos Reis
Olivier Azeau writes:

| Gabriel Dos Reis wrote:
| > writes:
| [snip]
| > | on peut tout faire à la main, maintenant quand est-ce que c'est
| > | rentable/intéressant, et quand est-ce qu'on a intérêt a choisir une
| > | solution "standard", éprouvée et déjà faite...
| > Mais c'est quoi la solution standard ici ?
|
| Une solution où les analyses lexicales et syntaxiques de l'échange de
| données ne coutent rien à écrire et où l'on va donc pouvoir se
| concentrer sur la sémantique.

Aha ?

| Le traitement sémantique est d'ailleurs relativement aisé si on prend
| la peine de faire un peu de XPath.

Bah, toutes mes expériences personnelles avec XML sont plutôt négatives
sur ce point. Chaque fois que je regarde mon code, ou celui de mes
collègues (qui en passant sont hautement plus qualifiés que moi en
programmation, C++, XML et toussa), j'arrive à une conclusion
partagée avec eux : il y a bien trop de codes inutiles et
obfuscatoires, en grosse partie dûe à XML.
Ma dernière expérience en date est XPR -- la forme persistante de IPR.
On a comparé plusieurs versions de XPR (du très bourrin à relativement
fines) à plusieurs « variantes » de formats XML. On arrive toujours à
la même conclusion. Et en passant, la forme XPR gagne toujours tant
sur la lisibilité que sur la performance des parseurs (le critère
idéal est que parser la forme persistante de IPR devrait être aussi
rapide que faire un « cat » ; XPR n'est pas encore ça, mais les
variantes XML sont très loins derrière).

| Une solution où même si la lisibilité des données par un humain n'est
| pas immédiate (lire du XML, même bien formatté, avec un editeur de
| texte de base c'est n'importe quoi), elle ne coute pas bien cher avec
| un peu d'XSLT.

pas cher en termes de quoi exactement ?

[...]

[ je remets l'analogies originelle de Arnaud Debaene, même si tu ne
sembles pas l'aimer... ]

# Ta réaction me fait un peu penser aux gens qui disent "à quoi ca sert
# std::vector, je peux très bien faire mes tableaux à la main". Certes

| > Analogie pour analogie, c'est comme si tu me disais que je dois
| > systématiquement choisir d'écrire mes programmes en C++, en place et
| > lieu de Python ou Perl parce que C++ a un standard ISO.
|
| L'analogie serait plutôt de dire que, quand on fait du C++ il faut
| utiliser la STL en lieu et place de classes faites maison pour gérer
| des listes ou des chaînes de caractère.
| On ne va pas utiliser la STL parce qu'un groupe de personnes l'a
| "standardisé"

peut-être mais c'est bien l'argument analogique (sic) avancé par Arnaud.

| ... mais parce que l'on va y trouver toute une panoplie de
| services que l'on aurait bien du mal à réécrire soi même.

*si* ces services *conviennent* à l'application donnée. Ce qui est loin
d'être acquis et c'est bien l'objet du débat (je parle toujours de XML
et non de la STL).

| Et peut être
| aussi un peu parce qu'un développeur pris au hasard aura bien plus de
| chances de comprendre un code C++ qu'il ne connait pas si celui-ci
| utilise la STL.

À la différence importante ici est que la STL fait partie de C++.
Mais ce n'est pas important parce que ce n'est qu'une analogie et
toussa hein ? Pfff.

-- Gaby
Avatar
Jean-Marc Bourguet
Laurent Deniau writes:

Jean-Marc Bourguet wrote:
Laurent Deniau writes:

Et pourquoi veux-tu mettre toutes ces balises?
Si je comprends bien, tu es en train de dire qu'il y a moyen de

detourner XML? Nous sommes d'accord, c'est une solution si XML est
impose par quelqu'un qui s'y connait vraiment pas.


Pas seulement, je dis aussi que l'on peut mettre le strict minimum
pour que la serialisation puisse reconstruire les objets tout en
etant compatible avec XML. A quoi ca sert que XML sache qu'un
complexe a une partie reelle et une partie imaginaire si tu ne veux
pas ecrire faire de calcul avec. Et meme a quoi ca sert que XML
sache que l'objet serialise entre les balises soit un complexe?


A quoi ca sert d'utiliser XML si la structure n'est pas decrite en XML
a par remplir des contraintes formelles stupides? C'est exactement ce
que j'appelle du detournement.

Comme son nom l'indique (Markup Language) l'origine d'XML est de
l'annotation et de la structuration de texte. Vouloir en faire le
format texte universel pour tout fichier structure est pousser le
principe trop loin. Sur ce point, c'est une experience qui a echoue
mais il y a des gens qui ne s'en sont pas encore rendu compte. Chez
les autres il y a meme un risque de rejet a priori d'XML meme dans les
contextes ou il serait peut-etre approprie.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
adebaene
Loïc Joly wrote:


Oui, yapluka l'écrire, et probablement le refaire (ou le modifier)
pour chaque nouveau projet, si les contraintes sont différentes...


C'est là dessus le mauvais point d'XML dans mon expérience. Un
parseur

classique, en cas de modification des classes, demande à modifier :
- La classe
- Les fichiers de données
- Le code qui parse
Ce qui en exploitation se traduit par un programme et un fichier.


Un parseur XML demande lui de modifier :
- La classe
- Les fichiers de données
- Le code qui parse
- Les schéma
Ce qui en exploitation se traduit par un programme et deux fichiers.


Sauf que avec les langages supportant l'introspection, le schéma est
généré par une moulinette à partir de la classe. Il y a même de
cas où il n'y a pas besoin de générer explicitement le schéma : la
mécanisme de sérialisation le fait pour toi à la volée selon les
besoins.


Donc, pour le développeur ou la personne qui déploie, il est moins
facile à modifier. On l'a clairement expérimenté au boulot.
Peut-être que vous n'aviez pas les bons outils?


Si on devait
reprende ce programme, le remplacement de ce format de fichier par un

truc issu de boost::serialisation serait certainement l'une des
premières étapes. En terme de pocker, XML, on a payé pour voir,
c'était

du bluff.


Je crois surtout que comme il y a effectivement beaucoup de "hype"
commercial autour de XML ce temps-ci, tout le monde veut absolument
utiliser toutes les extensions possibles et imaginables de XML (XSLT,
SOAP, tous les "standards" de sécurité et d'authentification,
etc...). C'est un peu comme les gens pour qui UML veut dire aller
jusqu'à la génération automatique de code à partir des schémas
UML, alors que l'utilisation la plus profitable d'UML c'est
probablement les schémas griffonnées sur un paperboard.

Pour moi, l'un des gros avantages de XML est qu'il est souple et qu'il
peut être utilisé de manière "crade" : je n'utilise un schéma que
si je veux effectivement valider de manière stricte un document. La
plupart du temps, ce n'est pas le cas : Du moment que le mécanisme de
sérialisation peut retrouver les champs "vitaux" de l'objet que je
veux reconstruire dans le document XML, peut importe si le document
colle exactement ou pas à la structure complète de mon objet.

Mais, cela peut être aussi le cas de mon propre format ASCII (AWK,
Perl, ...).


On parle de C++, non ?


| L'idiome qui va permettre à un autre développeur de comprendre
| immédiatement ce qui a été fait ?

Mais cela peut être aussi le cas de mon propre format ASCII.



Entre ton format ASCII maison (aussi bien conçu soit-il), et un
standard du W3C, il n'y a pas photo pour ce qui est de la facilité
de


trouver un développeur compétent et capable de réutiliser
facilement


le format...


Oui, je pense que le format maison est largement gagnant.


Gagnant en terme de quoi? Je parlais de la facilité à trouver
quelqu'un de compétent pour reprendre le code / réutiliser les
fichiers correspondants. Je ne pense pas que beaucoup de gens soient
compétents en théorie des langages, chose qu'il faut voir un minimum
pour gérer soit même un parser.


Ta réaction me fait un peu penser aux gens qui disent "à quoi ca
sert


std::vector, je peux très bien faire mes tableaux à la main".
Certes


on peut tout faire à la main, maintenant quand est-ce que c'est
rentable/intéressant, et quand est-ce qu'on a intérêt a choisir
une


solution "standard", éprouvée et déjà faite...


Lex et Yacc sont plus éprouvé qu'XML.


Et beaucoup moins accessibles au commun de mortels (et des
développeurs) AMHA.

Arnaud



Avatar
Laurent Deniau
Jean-Marc Bourguet wrote:
Laurent Deniau writes:

Pas seulement, je dis aussi que l'on peut mettre le strict minimum
pour que la serialisation puisse reconstruire les objets tout en
etant compatible avec XML. A quoi ca sert que XML sache qu'un
complexe a une partie reelle et une partie imaginaire si tu ne veux
pas ecrire faire de calcul avec. Et meme a quoi ca sert que XML
sache que l'objet serialise entre les balises soit un complexe?



A quoi ca sert d'utiliser XML si la structure n'est pas decrite en XML
a par remplir des contraintes formelles stupides? C'est exactement ce
que j'appelle du detournement.


Ce n'est pas moi qui demande du XML. Je le trouve completement inutile
pour la serialisation d'objet qui rappelons le a une semantique de
valeur. On rend persistant des instances. Si en revanche on veut generer
une jolie arborescence de classes avec le nom des methodes en coleur et
toussa, alors on peut discuter de son utilite.

Comme son nom l'indique (Markup Language) l'origine d'XML est de
l'annotation et de la structuration de texte.


Tout comme avant lui SGML, HTML, ??ML. Et alors? Est-ce que tu
serialiserait des objets en format roff?

a+, ld.


Avatar
kanze
wrote:
Gabriel Dos Reis wrote:


[...]
Mais cela dépend de mon propre format ASCII : est-il plus
simple d'utiliser ton validateur DTD que mon propre
vérificateur de format qui eput Être de loin plus simple
selon mon propre format ASCII ? Mon propre vérificateur peut
être aussi auto-correcteur ou non redondant.


Oui, yapluka l'écrire, et probablement le refaire (ou le
modifier) pour chaque nouveau projet, si les contraintes sont
différentes...


D'après mes expériences, pour les cas simples, on a plus vite
fait d'écrire son propre parseur que d'avoir défini le DTD et
d'avoir configurer le parseur XML.

[...]
Entre ton format ASCII maison (aussi bien conçu soit-il), et
un standard du W3C, il n'y a pas photo pour ce qui est de la
facilité de trouver un développeur compétent et capable de
réutiliser facilement le format...


En effet. Trouver les développeurs qui savent lire un DTD et en
comprendre toutes les implications à la première vue n'est pas
facile. (Malheureusement, la même chose vaut pour les
développeurs qui comprenent toutes les nuances de C++.)

Bref.


Ta réaction me fait un peu penser aux gens qui disent "à quoi
ca sert std::vector, je peux très bien faire mes tableaux à la
main".


L'analogie que je vois, ce serait plutôt quelqu'un qui réfuse
d'utiliser std::vector parce que la SQL permet beaucoup plus de
chose, et qu'il y en a des implémentations existantes.

Certes on peut tout faire à la main, maintenant quand est-ce
que c'est rentable/intéressant, et quand est-ce qu'on a
intérêt a choisir une solution "standard", éprouvée et déjà
faite...


Quand est-ce qu'il est intéressant d'implémenter une classe
avec deux ou trois std::vector, quand il y a une solution
standard, éprouvée et déjà faite... qui s'appelle le SQL ?

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
Gabriel Dos Reis wrote:

[...]
| ... mais parce que l'on va y trouver toute une panoplie de
| services que l'on aurait bien du mal à réécrire soi même.

*si* ces services *conviennent* à l'application donnée. Ce qui
est loin d'être acquis et c'est bien l'objet du débat (je
parle toujours de XML et non de la STL).


Mais pourquoi pas parler de la STL aussi. J'écris encore :
int i = 0 ;
et non :
std::vector< int > i( 1, 0 ) ;
Je n'utilise la STL que quand il fait quelque chose dont j'ai
besoin. Je ne l'utilise pas juste pour dire que je l'utilise, ou
parce que c'est in.

Le problème que je vois avec le XML, en fait, c'est qu'il essaie
de fournir std::map sans vouloir même admettre l'existance
possible de std::vector ni d'int.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
kanze
Jean-Marc Bourguet wrote:

Le seul avantage, c'est si le DTD est deja definit par
ailleurs et pas controle par un concurrent. Mais ce n'est pas
un avantage d'XML, c'est un avantage d'un format definit.


L'avantage dans ce cas-ci, c'est que si le format défini par
ailleurs est défini au moyen du DTD, tu en as des parseurs tout
faits. Si les structures sont simples, c'est vrai que tu
pourrais en faire un toi-même bien plus vite que de te mettre à
un parseur existant XML. Mais en général, quand il s'agit des
formats « normalisés », il s'agit des formats capables de
traiter beaucoup de cas différents, et donc, de formats
potentiellement assez compliqués. Dans ces cas-là, je vois bien
XML.

La plupart du temps, en revanche, j'ai besoin de la
sérialisation pour une de deux choses : la persistence, ou la
communication entre deux de mes propres programmes. En général,
la structure des données est assez simple et surtout assez peu
dynamique (peu de champs « faculatifs », par exemple). Dans ces
cas-là, il me faut en général moins d'une journée pour écrire le
code de sérialisation et de désérialisation.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
kanze
Loïc Joly wrote:
Jean-Marc Bourguet wrote:

J'ai une proportion non negligeable de classes pour
lesquelles la persistance ou la serialisation sont
pertinentes mais qui ont des membres ne devant pas etre
serialises ou rendus persistants. Comment de l'introspection
seule peut-elle rendre la chose automatique sans avoir un
attribut supplementaire pour indiquer ce fait (ce qu'a Java
si j'ai bonne memoire)?


Je ne sais pas pour Java, mais c'est le genre d'option retenue
dans les langages .NET. Avec de mémoire la possibilité d'aller
plus loin qu'un simple on/off, mais de donner des infos sur
comment sérialiser.


Je me démande si ce genre de décision doit appartenir à la
classe.

Et je n'aime pas trop. Déjà on peut imaginer vouloir
sérialiser différemment une seule classe, mais surtout, je
trouve que ça rajoute dans la définition de la classe des
informations qui n'ont rien à y faire, et encombrent donc.


C'est en fait mon expérience avec la sérialisation de Java. On
devait supporter à la fois la RMI et la persistence, mais les
éléments qu'il fallait stocker (ou plutôt comment les stocker)
était différent dans chaque cas.

En fait, le problème toujours (que ce soit du C++ ou du Java),
c'est comment suivre les pointeurs. Il y a en fait plusieurs
cas :

-- le pointeur désigne des données à toi -- il faut faire une
copie profonde,

-- le pointeur désigne quelque chose de temporaire
(l'utilisateur qui a locké les données actuellement, par
exemple), il faut simplement l'ignorer, et

-- le pointeur crée un rapport avec d'autres objets dans le
système, il faut le remplacer par une clé qui permet de
rétrouver ces autres objets.

C'est ce dernier usage pour lequel je n'ai jamais réussi à
trouver une solution générique. Dans toutes les applications que
je connais, ou prèsque, les objets intéressants font une graphe,
dont les vertices sont représentées par des pointeurs. Lors de
la sérialisation, je ne peux pas sérialiser un pointeur -- il
faut bien où bien que je sérialise ce auquel il pointe, ou bien,
que je l'ignore, ou bien, que je le remplace par une espèce
d'identificateur de façon à pouvoir rétablir la connection par
la suite. Seulement, je ne connais pas de façon à gérer ces
identificateurs de façon générique.

(Dans un cas, il n'y avait rien dans le système qui pouvait
servir. Le problème était la persistence, et on écrivait tout
d'un coup -- à la fin, j'ai parcouru la graphe en affectant un
entier à chaque élément, et en créant un map adresse_d_element
-> id, puis j'ai parcouru une deuxième fois dans le même ordre
en sérialisant, et en remplaçant les adresses par les
identificateurs. À la lecture, affectais les identificateurs de
la même façon au fur et à mésure que je lisais les objets. Quand
je rencontrais un pointeur, je lisais l'entier, que j'affectais
au pointeur au moyen d'un cast affreux. Ensuite, quand j'avais
l'adresse de tous les objets, je faisais une deuxième passe,
pour remplacer les pointeurs qui contentaient en fait des
entiers par de vrais pointeurs. Affreux ! Mais ça marchait.)

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote:
|
| [...]
| > | ... mais parce que l'on va y trouver toute une panoplie de
| > | services que l'on aurait bien du mal à réécrire soi même.
|
| > *si* ces services *conviennent* à l'application donnée. Ce qui
| > est loin d'être acquis et c'est bien l'objet du débat (je
| > parle toujours de XML et non de la STL).
|
| Mais pourquoi pas parler de la STL aussi. J'écris encore :

un débat à la fois, autrement les arguments se croisent et cela
devient tout confus -- comme souvent avec les analogies. Mais tu peux
en parler ;-)

-- Gaby
Avatar
drkm
Laurent Deniau writes:

drkm wrote:

Laurent Deniau writes:

drkm wrote:

writes:

-- plus lisible par un être humain normalement constitué, et
-- plus simple à générer et surtout à parser (et donc, moins
consumateur du temps CPU).


Malheureusement, l'idée contraire est je pense fort répandue (XML,
compromis lisible par les humains et les machines).


question de point de vue:

<MyFormat>
Complex 1 2
</MyFormat>

Pas lisible? Complique?


Ce n'est pas exactement la question. Je trouve « (1;2) » *plus*
lisible, et par un humain, et par une machine.


A quoi sert "(;)", quelle information cela apporte-t-il (machine +
humain)? Si cela denote la semantique d'un complexe pour eviter
d'appeler un chat un chat (i.e. prefixer par Complex),


Mais l'on recherche justement la manière d'appeler un chat. Selon
le type d'application, on peut utiliser (admettons que l'on veuille
fixer un membre m à j) :

m = #c(0 1) ;; pour reprendre la notation à CL

ou :

Member m ::= Complex 0 1

ou :

<member name="m">
<complex real="0" imag="1"/>
</member>

ou même :

<member name="m">
<complex>
<real>0</real>
<imaginary>1</imaginary>
</complex>
</member>

Chacune a ses avantages et inconvénients (bien que, la
dernière ...). Mais je ne dirais pas que les deux solutions en XML
sont plus lisible que les deux en ASCII (et par un humain, et par une
machine).

quelle semantique
alambiquee/compliquee proposes-tu pour un array, une liste, un tuple, un
quaternion, etc...


Heu ... Je comprend pas, là.

--drkm