Instruction RPG full free · IBM i (AS/400) · Données et calculs
XML-INTO
Lire un document XML
Lit un document XML, ici une chaîne en mémoire, et range son contenu dans une structure de données ou un tableau, sans analyse à la main.
Syntaxe
XML-INTO cible %XML(document : options);
XML-INTO(E) cible %XML(document : options);
cible- Une variable, une structure de données ou un tableau. Les noms des sous-zones doivent correspondre aux noms des éléments XML.
document- Le XML lui-même, dans une zone caractère ou une chaîne variable (avec l'option
doc=string). doc=string- Indique que le premier paramètre de
%XMLest le document lui-même et non un nom de fichier. case=any- Ne tient pas compte de la casse entre les noms XML et les noms des sous-zones.
countprefix=nb- Pour chaque tableau, range le nombre d'éléments lus dans une zone entière de nom
nbsuivi du nom du tableau. allowmissing=yes- Accepte qu'un élément du document soit absent de la cible ; sans cela, l'absence est une erreur.
- Effet
- Remplit la cible. En cas de document qui ne correspond pas à la cible, le programme lève RNX0353 (RNQ0353 sans surveillance), avec un code raison. Avec l'extension (E), l'erreur est conservée dans
%ERROR, au lieu d'arrêter le programme.
À quoi ça sert
Beaucoup de services web et de fichiers d'échange renvoient du XML. Avant XML-INTO, il fallait un analyseur d'événements et beaucoup de code. Ici, on déclare la structure qui ressemble au document et le système fait la correspondance, y compris les conversions : texte vers packed, éléments répétés vers tableau.
La structure de l'exemple décrit numcli, nom, ville et solde, et un seul XML-INTO les lit.
Exemple 1 : Un client
**free
// XML-INTO : lire un document XML en memoire dans une structure.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-ds client qualified;
numcli packed(5:0);
nom varchar(30);
ville varchar(20);
solde packed(9:2);
end-ds;
dcl-s xml varchar(500);
xml = '<client><numcli>100</numcli><nom>Dupont SA</nom>'
+ '<ville>Montpellier</ville><solde>1250.50</solde></client>';
xml-into client %xml(xml : 'doc=string case=any');
snd-msg 'Numcli : ' + %char(client.numcli);
snd-msg 'Nom : [' + client.nom + ']';
snd-msg 'Ville : [' + client.ville + ']';
snd-msg 'Solde : ' + %char(client.solde);
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Numcli : 100
Nom : [Dupont SA]
Ville : [Montpellier]
Solde : 1250.50
Le document est construit dans une chaîne variable, puis lu avec doc=string et case=any. Chaque élément va dans la sous-zone de même nom, avec conversion : 1250.50 devient un packed(9:2).
Exemple 2 : Éléments répétés et élément manquant
**free
// XML-INTO : un element repete va dans un tableau ; un element manquant est une erreur.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-ds cli qualified template;
numcli packed(5:0);
nom varchar(30);
end-ds;
dcl-ds sanscompte qualified;
client likeds(cli) dim(10);
end-ds;
dcl-ds liste qualified;
nbclient int(10);
client likeds(cli) dim(10);
end-ds;
dcl-s xml varchar(500);
dcl-s i int(10);
xml = '<liste><client><numcli>100</numcli><nom>Dupont SA</nom></client>'
+ '<client><numcli>200</numcli><nom>Martin et fils</nom></client></liste>';
monitor;
xml-into sanscompte %xml(xml : 'doc=string case=any');
snd-msg 'Sans compteur : lu';
on-error;
snd-msg 'Sans compteur : echec, statut ' + %char(%status);
endmon;
xml-into liste %xml(xml : 'doc=string case=any countprefix=nb');
snd-msg 'Elements lus : ' + %char(liste.nbclient);
for i = 1 to liste.nbclient;
snd-msg %char(liste.client(i).numcli) + ' ' + liste.client(i).nom;
endfor;
// Un element manquant dans le document (le nom du client 300)
xml = '<liste><client><numcli>300</numcli></client></liste>';
monitor;
xml-into liste %xml(xml : 'doc=string case=any countprefix=nb allowmissing=yes');
snd-msg 'Avec allowmissing : nom = [' + liste.client(1).nom + ']';
on-error;
snd-msg 'Avec allowmissing : echec';
endmon;
xml-into liste %xml(xml : 'doc=string case=any countprefix=nb');
snd-msg 'Cette ligne n est pas atteinte';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Sans compteur : echec, statut 353
Elements lus : 2
100 Dupont SA
200 Martin et fils
Avec allowmissing : nom = [Dupont SA]
Erreur : RNQ0353 - (C G D F) Le document XML ne correspond pas à la variable RPG.
Deux éléments client alimentent un tableau de dix. Sans zone de comptage, la lecture échoue (statut 353), puisque le tableau n'est pas plein. Avec countprefix=nb, la zone nbclient reçoit 2 et la lecture réussit.
Le dernier document ne contient pas le nom. Avec allowmissing=yes, la lecture réussit, mais client(1).nom garde l'ancienne valeur Dupont SA. Sans cette option, le programme s'arrête sur RNQ0353.
Le piège
Un élément absent peut laisser l'ancienne valeur. Avec allowmissing=yes, une sous-zone sans élément XML n'est pas remise à blanc : dans le deuxième exemple, le nom du client 300 est Dupont SA, celui du client 100. Faites un CLEAR de la cible avant chaque lecture.
Et sans cette option, l'élément manquant est fatal (RNQ0353, code raison 4). De même, un tableau partiellement rempli sans zone de comptage fait échouer la lecture (statut 353, test avec 2 éléments pour 10 places). Entourez toujours XML-INTO de MONITOR ou de l'extension (E) pour une donnée qui vient de l'extérieur.