Manuel §1.2.7    

Arbres étiquetés

Sisal permet de déclarer des arbres étiquetés de données [1] . Un arbre étiqueté [2] est une structure de données rangées en arbre et donc chaque feuille ou branche est étiquetée, c'est à dire définie par un nom. Le gros intérêt de l'arbre étiqueté est de pouvoir lire ou générer un fichier XML ( eXtended Markup Language) directement à partir de et vers son contenu; ce qui représente un très gros avantage lors de l'exploitation de données structurées provenant d'internet.

Cette structure doit être déclarée dans une partie Var d ’un script ou d ’un synoptique.

LTree;

Une définition rigoureuse d'un arbre étiqueté est de dire qu'un arbre étiqueté est soit une valeur simple de Sisal identifié par un nom, soit une suite d'arbre étiqueté identifié chacun par un nom.

Cette définition étant récursive, une valeur simple sera définie par un nom composé; de même on peut définir un sous-arbre étiqueté par un nom composé.

Par exemple ce petit fichier xml définit


12.45
37.2

un sous-arbre " Measure " et deux valeurs " Measure.Offset " et " Measure.Strength ".

Donc pour définir une valeur ou un sous-arbre d'un arbre étiqueté, on utilisera la notation pointée constituée de la suite de chaque étiquette de chaque branche et feuille permettant d'accéder à la valeur recherchée, on appellera cela le chemin d ’accès.

L'exemple suivant définit un arbre étiqueté.

MyXml    Ltree;

L ’accès aux données associées à une branche ou une feuille, on utilisera les fonctions systèmes réservées (cf. Value et Set Value)

Si dans un sous-arbre plusieurs éléments ont le même nom (on appelle cela des valeurs multiples), Sisal peut les différencier par le chemin en postfixant celui-ci d'une sélection de tableau; par exemple, si on a l'arbre étiqueté suivant:


 1.0 12.55  
 2.0 13.18  
 3.0 11.42.55  

On pourra définir Value( MyXml, "Curve.Point[0].x") pour accéder à la première abscisse et Value( MyXml, "Curve.Point[2].y") pour accéder à la dernière ordonnée.

Des fonctions système spécifiques permettent de gérer les arbres étiquetés.

La fonction Add permet d'ajouter des éléments à un arbre étiqueté.

Add( ArbEt, Chemin {, Valeur}): Arbet

Cette fonction rend un sous-arbre de l'arbre principale auquel on pourra rajouter d'autres sous-arbres.

Par exemple pour recréer l'exemple précédent:

Var MyTree Ltree;
MySubTree;
...
MySubTree = Add( MyTree, " Measure ");
Add( MySubTree, " Offset ", " 12.45 ");
Add( MySubTree, " Strength ", " 37.2 ");

La fonction find [3] permet de tester l'existence d'un chemin dans un arbre étiqueté.

Find( ArbEt, Chemin): Booléen

Par exemple

if Find( MyTree, " Measure ") then ...

La fonction SubTree permet d'accéder à un sous-arbre d'un arbre, si le sous-arbre n'existe pas la fonction rend indéfinie.

SubTree( ArbEt, Chemin): Arbet

Le sous-arbre [4] n'est pas une copie du sous-arbre de l'arbre initial, mais référence bien une partie de l'arbre initial. Toute modification du sous-arbre entraînera une modification de l'arbre initial.

Les fonctions Up, Next et First permettent de passer d'un sous-arbre à l'autre. La fonction Up renvoie au sous-arbre père, la fonction Next renvoie au sous-arbre frère et la fonction First renvoie au premier sous-arbre.

Up( Arbet) : Arbet

Next( Arbet): Arbet

First( Arbet): Arbet

Toutes ces fonctions rendent un sous-arbre lorsque cela est possible et indéfini dans le cas contraire.

Par exemple pour accéder à tous les éléments d'un sous-arbre

Var MyXml Ltree; MySub;
...
MySub = First( SubTree( MyXml, " Measure "));
while MySub Do begin
Message( Path( MySub):" = ":Value(MySub));
MySub = Next( MySub);
end

La fonction Count permet de compter le nombre d'élément d'un arbre étiqueté c'est à dire le nombre de sous-arbres ou de feuilles définis au niveau de cet arbre.

Count( Arbet): nombre

Par exemple

if Count( MySub) != 2 then Message( "Is no good");

Lorsqu'un chemin est transmis en paramètre, la fonction rend le nombre d'élément ayant le même chemin; par exemple pour connaître le nombre de points de notre courbe, on peut faire

Nb = Count( MyTree, "Curve.Point");
if Nb then
For i = 0 to Nb do
Message( Value( MyTree, "Curve.Point[":i:"]"));

La fonction ParseArray permet de répartir les valeurs multiples d'un arbre étiqueté dans les cellules d ’un tableau.

ParseArray( Arbet, Chemin {, souschemin}, tableau) : Nombre

Le premier paramètre est l'arbre étiqueté contenant les valeurs multiples, le deuxième la chaîne contenant le chemin définissant ces valeurs multiples, le troisième optionnel la suite du chemin permettant d'acéder aux valeurs terminales et le dernier le tableau qui contiendra chacun des sous-champs. La fonction rend le nombre de valeurs qui ont été rangées dans le tableau.

Si le tableau est trop petit les derniers sous-champs ne sont pas écrits dans le tableau. Si le tableau contient plus de cellules que de sous champs, les derniers éléments du tableau sont indéfinis.

Exemple :

Var i, Nb, Tab[ 10];
Begin
Nb = ParseArray( MyTree, "Curve.Point", "x",  Tab);
for i = 0 to nb do Message( Tab[i]);
end

Rangera successivement dans le tableau Curve.Point[0].x,

Curve.Point[1].x, ...

La fonction Delete permet de supprimer un enregistrement d'un arbre étiqueté ou de le vider.

Delete( ArbEt {, chemin}): Booléen

La fonction GetXml permet de charger un arbre étiqueté à partir d'une chaine de caractère; la fonction rend vrai si l'analyse s'est bien passée, faux s'il y a eu au moins une erreur.

GetXml( ArbEt, Chaine): booléen

Si la chaine contient des valeurs vides , par exemple " " ou "", les éléments correspondants seront créés mais leurs valeurs sera indéfinie.

Attention le chargement n'efface pas le contenu précédent de l'arbre, on rajoute des branches et des feuilles à l'arbre existant; pour n'avoir que le contenu de défini dans la chaine, il faut vider l'arbre.

Par exemple

Delete( MyXml);
GetXml( MyXml, " Bravo ");

La fonction PutXml permet de former une chaine XML à partir du contenu de l'arbre étiqueté.

PutXml( ArbEt): Chaine

Si l'arbre contient des éléments indéfinis, la chaine contiendra des attributs vides du genre "".

La fonction ReadXml permet de charger un arbre étiqueté à partir d'un fichier texte.

ReadXml( arbet, fichier): booléen

La fonction attend en paramètre un arbre étiqueté et un chemin d'accés à un fichier; elle retourne vrai si cela s'est bien passé.

Par exemple

if ReadXml( MyXml, "C:Test.xml")
then Message( "Measure ":Value( MyXml,  "Measure.Offset"));

La fonction WriteXml permet d'enregistrer dans un fichier le contenu d'un arbre étiqueté.

WriteXml( arbet, fichier {, entete}) : booléen

La fonction attend en paramètre un arbre étiqueté, un chemin d'accés à un fichier et optionnellement une chaine de caractère qui sera écrite en tête de fichier (cette option permet de construire des fichiers conforme au standard Xml en définissant le niveau de standard (

Par exemple

WriteXml( MyXml,
"C:\Test.xml",
"");

La fonction Label permet de connaître l'étiquette associé au chemin sélectionné; cela est plus particulièrement utile pour les itérateurs d'arbre étiqueté.

Label( ArbEt[ chemin]) : Chaine

De même la fonction Path permet de connaître le chemin de l'élément sélectionné; cela est plus particulièrement utile pour les itérateurs d'arbre étiqueté.

Path( ArbEt[ chemin]) : Chaine

Par exemple

Label( MyXml[" Measure.Offset "]) ->  " Offset "
Path( MyXml[" Measure.Offset "]) ->  " Measure.Offset "

Les fonctions Value et SetValue permettent respectivement de lire et de modifier la valeur associée à une feuille ou une branche de l'arbre.

Value( Arbet {, chemin}): valeur

SetValue( Arbet, chemin, valeur): status

Les fonctions attendent en paramètre une arbre ou un sous-arbre ou un itérateur d'arbre, et si requis un chemin complémentaire qui peut être la chaîne vide. La fonction Value retourne la valeur enregistrée dans cet élément de l'arbre si elle existe, indéfinie si elle existe pas. La fonction SetValue attend en troisième paramètre la valeur à affecter; si l'élément n'existe pas il est créé et la fonction retourne 1, si l'élément existe la fonction retourne 0, dans les autres cas la fonction rend indéfini. Par exemple:

X = Value( MyXml, « X »);
if X then SetValue( MyXml, « X », X+1);

Et la boucle For permet de balayer tous les éléments définis dans un arbre étiqueté.

For Variable In ArbEt do INSTRUCTION

Par exemple, recherchons toutes les mesures.

For mesure In Subtree( MyXml, “Measure”) do
If Label( mesure) == “Strength” then ...

La fonction EachNode permet de définir un itérateur permettant d'accéder à chacun des sous-arbres et des feuilles d'un sous-arbre.

For Variable In EachNode( Arbet {, chemin}) do INSTRUCTION

Par exemple pour afficher tous les noeuds d'un arbre

For MyNode in EachNode( MyXml) do
Message( Name( MyNode): " = " :MyNode);

[1] A partir de la version 2.8

[2] " labelled tree " en anglais, d'où " LTree "

[3] La fonction find est nécessaire car des valeurs indéfinies peuvent être rangées dans un arbre étiqueté; dans ce cas la fonction find rend vrai alors que la comparaison de l'élément (if MyTree[" MyPath "] then ..) rend null donc comme si l'élément n'existait pas.

[4] En fait il s'agit d'un itérateur d'arbre étiqueté qui permet de se promener sur chaque branche et feuille.