Invité Invité
| Sujet: Lire / Ecrire - Fichier XML Jeu 28 Juil 2011 - 19:48 | |
| Lire & Ecrire sur un fichier XML Les fichiers ini c'est bien, mais c'est assez limité. Il n'y a pas la possibilité de créer des sections dans les sections et on ne peut ouvrir qu'un ini à la fois. Les fichiers XML c'est mieux pour mon jeu dont les données sont souvent externe à l'executable. Avec les fichiers XML, on peut stocker des données sous une structure élaboré avec des balises. Les balises que j'utilise sont des des chaînes entre des crochets ( <score>500</score>). Exemple d'un contenu de fichier XML: - Spoiler:
- Code:
-
<sauvegardes> <Nicolas> <score>550</score> <progression_histoire>22</progression_histoire> </Nicolas> <Sebastien> <score>123</score> <progression_histoire>10</progression_histoire> </Sebastien> </sauvegardes>
J'ai donc élaboré des fonctions permettant de traiter ces fichiers. Je sais qu'il existe une DLL permettant de traiter les fichiers XML mais elle est limité en rang. On peut soit lire une donnée, soit remplacer une valeur dans une balise existante. Le fichiers XML doivent respecter certaines contraintes : - L'utilisation des caractères §, #, <, > sont à proscrire. (Si vous souhaitiez utiliser le symbole # pour les retour à la ligne des chaînes, sachez que la fonction XML_lire détecte les retour à la ligne dans le fichier XML et ajoute les caractères # automatiquement).
- Les balises ne doivent pas se chevaucher.
Exemple: - Spoiler:
<a>abc<b>def</a>ghi</b> est incorrect, il faut ecrire <a>abc<b>def</b>ghi</a>
- Le nom d'une balise ne doit pas être séparé d'un espace avec les crochets.
Exemple : - Spoiler:
< abc > est incorrect si vous vous voulez lire la valeur contenu dans abc, en effet, la fonction comprendra que vous cherchez la valeur de " abc " et pas de "abc"; il faut ecrire <abc>
- Les balises ne doivent pas contenir d'attributs comme <abc couleur="rouge"> (les élèments en rouge sont des attributs).
- Les fonctions ne peuvent lire les données des balises au 1er rang.
Exemple: - Spoiler:
- Code:
-
<sauvegardes> <Nicolas> <score>550</score> <progression_histoire>22</progression_histoire> </Nicolas> <Sebastien> <score>123</score> <progression_histoire>10</progression_histoire> </Sebastien> </sauvegardes> <volume>75</volume>
Dans cet exemple, je peut lire la valeur des balises scores et progression_histoire. Par contre, je ne peut pas lire la valeur du volume, en effet les balises volume ne sont pas compris dans une autre balise. Si je veut lire cette valeur, je dois faire comme ceci: - Code:
-
<musique> <volume>75</volume> </musique>
- Le fichier ne doit pas être forcement au format XML (vous pouvez utiliser le format .txt si vous voulez).
- La casse est respectée.
Il y quatre fonctions que j'ai créer pour utiliser ce format. XML_charger(file) - Citation :
- Pour utiliser un fichier XML, il faut le charger.
Cette fonction retourne le contenu du fichier formaté de façon à pouvoir être utilisé par les autres fonction; on peut donc considerer que cette fonction retourne l'identifiant du fichier. Vous avez la possibilité de charger autant de fichiers XML que vous souhaitez (vous n'êtes pas limité aux 32 fichiers ouvert maximum par les fonctions file_text_...). La variable qui contient ce que retourne cette fonction je l'appelerais xml (super original ).
- Spoiler:
Essayez d'afficher le contenu de cette variable xml, vous verrez qu'elle contient en fait le contenu du fichier XML à quelques exceptions près, comme l'usage du symbole § pour signifier un retour à la ligne ou que les balises sont numerotées en fonction de leur rang.
Je dois cependant vous définir ce que j’appellerais une clef. Une clef, c'est comme pour les fichiers ini, sa identifie une valeur. Mais dans un fichier XML, il y a des sections comparativement à un ini, mais il y a aussi des sous-sections. Voici un exemple de fichier XML: - Spoiler:
- Code:
-
<sauvegardes> <Nicolas> <score>550</score> <progression_histoire>22</progression_histoire> </Nicolas> <Sebastien> <score>123</score> <progression_histoire>10</progression_histoire> </Sebastien> </sauvegardes>
Quelle est la clef de la valeur du score de Nicolas ? Sa clef peut être assimiler à la balise score. Mais comment différencié le score de Nicolas et de Sébastien ? Dorénavant, quand vous spécifiez une clef, vous devez préciser toute les balises en amont de cette valeur. Vous séparerez le nom des différentes balises par un slash (/). Par exemple, si je veut relever le score de Nicolas, la clef est sauvegardes/Nicolas/score. Pour lire la progression de l'histoire de Sébastien, la clef seras sauvegardes/Sebastien/progression_histoireXML_lire(xml,clef,valdef) - Citation :
Une fois la fonction chargée dans la variable xml (vous n'êtes pas obligé de nommer cette variable xml, vous pouvez la nommer autrement) vous pouvez extraire des données. Vous avez trois arguments :
- xml: c'est la variables qui contient se qui a été retourné par la fonction XML_charger.
- clef: c'est la clef de la valeur que vous souhaitez extraire. Lisez ci-dessus pour en savoir plus sur les clefs.
- valdef: si une erreur devait survenir inopinément, la fonction retournera cette valeur. Cette valeur doit-être une chaîne.
Cette fonction peut-être utile pour determiner l'existence d'une balise, en effet, si la clef est introuvable, la valeur par defaut sera retournée. Cette fonction retourne donc la valeur de la clef sous forme d'une chaîne.
XML_ecrire(xml,clef,val) - Citation :
Cette fonction remplace la valeur d'une clef par une que vous aurez définis. C'est l'équivalent de la fonction ini_write comparativement. Il y a trois arguments :
- xml: c'est la variables qui contient se qui a été retourné par la fonction XML_charger.
- clef: c'est la clef de la valeur que vous souhaitez remplacer. Lisez ci-dessus pour en savoir plus sur les clefs.
- val: c'est la valeur qui remplacera celle déjà présente dans la clef spécifiés. Cette valeur doit-être une chaîne.
La fonction retourne la variable xml modifiée. Exemple: - Code:
-
xml = XML_ecrire(xml,"sauvegardes\Nicolas\score","2500"); XML_sauvegarder(xml,file) - Citation :
Si vous avez opéré des modifications avec la fonction XML_ecrire, sachez que ces modifications sur le fichier ne seront prisent en compte uniquement quand vous aurez sauvegardé les modif'. Il y a deux arguments:
- xml: c'est la variables qui contient se qui a été retourné par la fonction XML_ecrire.
- file: le fichier où seront enregistrés les données, il peut-être différent de celui qui a été chargé à l'origine. Attention: Le fichier concerné sera ecrasé.
Si la sauvegarde c'est déroulée correctement, la fonction retourne true, sinon, elle retourne false.
Je vous ai présenté les 4 fonctions opérant sur les fichiers XML. Ce n'est pas beaucoup, mais sa m'est très utile pour mon jeu. Et comme rien ne vaut un exemple, je vous montre un code GML qui charge un fichier XML, qui lit la valeur d'une clef et ensuite l'affiche sous forme d'une boite de dialogue . Après, on modifie une valeur et ensuite on la sauvegarde. fichier.XML: - Spoiler:
- Code:
-
<sauvegardes> <Nicolas> <score>550</score> <progression_histoire>22</progression_histoire> </Nicolas> <Sebastien> <score>123</score> <progression_histoire>10</progression_histoire> </Sebastien> </sauvegardes>
Code GML: - Spoiler:
- Code:
-
var xml,valeur; //Déclaration des variables
xml = XML_charger("fichier.xml"); //chargement d'un fichier XML dans une variable valeur = XML_lire(xml,"sauvegardes/Nicolas/score","0"); //lecture de la valeur du score de Nicolas show_message("Le score de Nicolas est de "+valeur); xml = XML_ecrire(xml,"sauvegardes\Nicolas\score","2500"); //le nouveau score pour Nicolas est maintenant de 2500, la modification est apporté au fichier chargé dans la variable xml valeur = XML_lire(xml,"sauvegardes\Nicolas\score","0"); //lecture de la nouvelle valeur du score de Nicolas show_message("La nouvelle valeur du score de Nicolas est de "+valeur); XML_sauvegarder(xml,"fichier.xml"); //Le contenu charger dans la variable xml est sauvegarder dans le fichier "fichier.xml"
Après l'execution de ce script, le contenu du fichier fichier.xml est maintenant : - Code:
-
<sauvegardes> <Nicolas> <score>2500</score> <progression_histoire>22</progression_histoire> </Nicolas> <Sebastien> <score>123</score> <progression_histoire>10</progression_histoire> </Sebastien> </sauvegardes>
Bon maintenant que j'ai décris les fonctions, je vous donne mes codes sources, en GML bien entendu. Désolé pour la tonne d'explications donnée si-dessus , mais j'aime bien que tout soit bien clair. Je n'est pas la prétention d'être un génie en matière de GML, mais ces codes fonctionnent correctement. Vous remarquerez, qu'il n'y a pas le principe de ouvrir/fermer un fichier. Ici, vous chargez le contenu d'un fichier XML dans une variable, et si vous avez fait des modifications à partir de cette variable, vous devez sauvegarder. XML_charger- Spoiler:
- Code:
-
/* XML_charger(fichier)
arg0 : chemin du fichier XML à charger.
return false -> Fichier XML introuvable ou ouverture du fichier impossible ou fichier vide. return != false -> contenu du fichier XML. Doit-être utilisé pour opérer sur ce fichier.
*/
var xml,f,ligne,tmp,i,n; xml = ""; tmp="";
if !file_exists(string(argument0)) { return false; }
f = file_text_open_read(string(argument0));
n=1; while !file_text_eof(f) {
ligne = file_text_read_string(f);
tmp ="a"; i=1; while tmp !="" { tmp = string_char_at(ligne,i); if (tmp =="<")&&(string_char_at(ligne,i+1) != "/") { xml += "<"+string(n)+"-"; n += 1; } else if (tmp =="<")&&(string_char_at(ligne,i+1) == "/") { n -=1; xml += "<"; } else { xml += tmp; } i += 1; }
xml += "§";
file_text_readln(f); }
file_text_close(f);
return xml;
XML_lire- Spoiler:
- Code:
-
/* XML_lire(xml,clef,valdef)
argument0: contenu du fichier XML retourné par la fonction XML_charger argument1: clef de la valeur recherchée (exemple: personnage\sante) argument2: valeur par defaut si clef incorrecte ou fichier XML incorrect
return = valeur de la clef retournée */
//ini var xml,tmp,clef,balise,n,nmax,i,resultat,ndc; xml = string(argument0); clef[0] = string(argument1); nmax=0; resultat=""; balise =""; ndc=0;
/* -- */
//Extraction des clefs n=1; i=1; tmp="a"; clef[n]="";
while tmp != "" { // < while (tmp != "")&&(tmp != "/") { tmp = string_char_at(clef[0],i); if (tmp != "")&&(tmp != "/") { clef[n] += tmp; i += 1; } } if tmp == "/" { i += 1; n += 1; tmp ="a"; clef[n] = ""; } } // > nmax = n;
//Fin d'extraction des clefs
//Lire la clef - trouver balise i=0;n=1;balise="";
while n<=nmax { i += 1; balise = "<"+string(n)+ "-" + clef[n] +">"; ndc = string_length(balise); tmp="a"; while (tmp != balise)&&(tmp != "") { tmp = string_copy(xml,i,ndc); i += 1; } if tmp == balise { n += 1; } if tmp == "" { return argument2; } }
// lire la balise i += ndc-1; tmp ="a";
balise = ceil(log10(nmax)); while string_copy(xml,i,ndc-balise) != ("</" +clef[nmax] +">") { tmp = string_char_at(xml,i); if tmp == "§" { resultat += "#"; } if tmp == "" { return argument2; } if (tmp != "§")&&(tmp != "") { resultat += tmp; }
i +=1; }
//elimination des espaces et tabulations excedentaires
tmp=resultat; resultat=string_replace_all(tmp," ",""); tmp=resultat; resultat=string_replace_all(tmp," ","");
if string_char_at(resultat,1) == "#" { tmp=resultat; resultat=string_replace(tmp,"#",""); }
//fin
return resultat;
XML_ecrire- Spoiler:
- Code:
-
/* XML_ecrire(xml,clef,val)
argument0: contenu du fichier XML retourné par la fonction XML_charger argument1: la clef de la valeur à remplacer argument2: valeur qui remplacera celle de la clef(chaîne ou nombre)
La fonction retourne la valeur de l'argument0 avec les modifications effectues, pour prendre en compte les modifications sur le fichier XML, utilisez la fonction XML_sauvegarder. Si une erreur survient, aucune modification ne serat faites. */
//ini var xml,tmp,clef,balise,n,nmax,i,resultat,ndc; xml = string(argument0); clef[0] = string(argument1); nmax=0; resultat=""; balise =""; ndc=0;
/* -- */
//Extraction des clefs n=1; i=1; tmp="a"; clef[n]="";
while tmp != "" { // < while (tmp != "")&&(tmp != "/") { tmp = string_char_at(clef[0],i); if (tmp != "")&&(tmp != "/") { clef[n] += tmp; i += 1; } } if tmp == "/" { i += 1; n += 1; tmp ="a"; clef[n] = ""; } } // > nmax = n;
//Fin d'extraction des clefs
//Lire la clef - trouver balise i=0;n=1;balise="";
while n<=nmax { i += 1; balise = "<"+string(n)+ "-" + clef[n] +">"; ndc = string_length(balise); tmp="a"; while (tmp != balise)&&(tmp != "") { tmp = string_copy(xml,i,ndc); i += 1; } if tmp == balise { n += 1; } if tmp == "" { return xml; } }
// lire la balise i += ndc-1; tmp ="a";
balise = ceil(log10(nmax)); while string_copy(xml,i,ndc-balise) != ("</" +clef[nmax] +">") { tmp = string_char_at(xml,i); if tmp == "§" { resultat += "#"; } if tmp == "" { return xml; } if (tmp != "§")&&(tmp != "") { resultat += tmp; }
i +=1; }
//Valeur de la balise obtenue ! //Remplacement de la valeur ndc = string_length(resultat); i -= ndc; tmp = string_delete(xml,i,ndc); resultat = string_insert(argument2,tmp,i);
return resultat;
XML_sauvegarder- Spoiler:
- Code:
-
/* XML_Sauvegarder(xml,file)
argument0: contenu du fichier XML retourné par la fonction XML_charger argument1: chemin du fichier où sera enregistré le fichier
return false = erreur return true = sauvegarde effectuée avec succès */
//ini var i,tmp,f,xml,n,tmp2;
i=1;tmp="a";tmp2="a"; xml=string(argument0); n=0;
f = file_text_open_write(argument1); f = file_text_close(f); f = file_text_open_append(argument1);
while tmp != "" { tmp = string_char_at(xml,i); if (tmp=="§")||(tmp=="#") { file_text_writeln(f); } if (tmp=="<")&&(string_char_at(xml,i+1) != "/") { n=0;tmp2="a"; while tmp2 != "-" { n +=1; tmp2 = string_char_at(xml,i+n); if tmp2 == "" { file_text_close(f); return xml; } } i += n; file_text_write_string(f,"<"); } if (tmp != "§")&&(tmp != "#")&&((tmp != "<")||(string_char_at(xml,i+1) == "/")) { file_text_write_string(f,tmp); } i +=1; }
file_text_close(f);
return true;
Voilà, c'est tout, mais si vous remarquez une erreur, ou une proposition d'amélioration, je suis tout ouï. PS: Excusez-moi si il y a des fautes d'orthographes.
Dernière édition par NVR le Mar 28 Fév 2012 - 8:50, édité 7 fois |
|