Le composant XML_Utilities Résumé 4D Notes techniques

Transcription

Le composant XML_Utilities Résumé 4D Notes techniques
Le composant XML_Utilities
Par
David ADAMS
Note technique 4D-200407-20-FR
Version 1
Date 1 Juillet 2004
Résumé
Les commandes XML de 4ème Dimension 2003 permettent d’analyser et valider de l’XML, de naviguer dans
les arbres XML et d’extraire les valeurs des éléments XML et de leurs attributs. Cette note technique décrit un
composant qui ajoute quelques utilitaires pratiques aux commandes natives de 4D 2003.
4D Notes techniques
Copyright © 1985-2004 4D SA - Tous droits réservés
Tous les efforts ont été faits pour que le contenu de cette note technique présente le maximum de fiabilité possible.
Néanmoins, les différents éléments composant cette note technique, et le cas échéant, le code, sont fournis sans garantie d'aucune sorte.
L'auteur et 4D S.A. déclinent donc toute responsabilité quant à l'utilisation qui pourrait être faite de ces éléments, tant à l'égard de leurs
utilisateurs que des tiers.
Les informations contenues dans ce document peuvent faire l'objet de modifications sans préavis et ne sauraient en aucune manière engager
4D SA. La fourniture d u logiciel décrit dans ce document est régie par u n octroi de licence dont les termes sont précisés par ailleurs dans la
licence électronique figurant sur le support d u Logiciel et de la Documentation afférente. Le logiciel et sa documentation ne peuvent être
utilisés, copiés o u reproduits sur quelque support que ce soit et de quelque manière que ce soit, que conformément aux termes de cette
licence.
Aucune partie de ce document ne peut être reproduite o u recopiée de quelque manière que ce soit, électronique o u mécanique, y compris par
photocopie, enregistrement, archivage o u tout autre procédé de stockage, de traitement et de récupération d'informations, pour d'autres buts
que l'usage personnel de l'acheteur, et ce exclusivement aux conditions contractuelles, sans la permission explicite de 4D SA.
4D, 4D Calc, 4D Draw, 4D Write, 4D Insider, 4ème Dimension ®, 4D Server, 4D Compiler ainsi que les logos 4e Dimension, sont des marques
enregistrées de 4D SA.
Windows,Windows NT,Win 32s et Microsoft sont des marques enregistrées de Microsoft Corporation.
Apple, Macintosh, Power Macintosh, LaserWriter, ImageWriter, QuickTime sont des marques enregistrées o u des noms commerciaux de
Apple Computer,Inc.
Mac2Win Software Copyright © 1990-2002 est un produit de Altura Software,Inc.
4D Write contient des éléments de "MacLink Plus file translation", un produit de DataViz, Inc,55 Corporate drive,Trumbull,CT,USA.
XTND Copyright 1992-2002 © 4D SA. Tous droits réservés.
XTND Technology Copyright 1989-2002 © Claris Corporation.. Tous droits réservés ACROBAT © Copyright 1987-2002, Secret
Commercial Adobe Systems Inc.Tous droits réservés. ACROBAT est une marque enregistrée d'Adobe Systems Inc.
Tous les autres noms de produits ou appellations sont des marques déposées ou des noms commerciaux appartenant à leurs propriétaires
respectifs.
1 / 12
Le composant XML_Utilities
Résumé
Les commandes XML de 4ème Dimension 2003 permettent d’analyser et valider de l’XML, de naviguer dans les
arbres XML et d’extraire les valeurs des éléments XML et de leurs attributs. Cette note technique décrit un
composant qui ajoute quelques utilitaires pratiques aux commandes natives de 4D 2003 :
Description de la méthode
•
•
•
•
xutil_CountOccurrences compte combien de fois est présent un élément ;
xutil_ElementExists retourne Vrai si un élément existe ;
xutil_GetValue retourne la valeur d’un élément simple en texte ;
xutil_StripWhitespace Retire les caractères blancs, comme défini par XML, d’un bloc de texte.
Outre la fourniture de fonctionnalités utiles, le code du composant XML Utilities procure des exemples sur la
manière de travailler avec les commandes XML de 4ème Dimension 2003. Les méthodes sont incluses à la fois
dans une base de données en code source ouvert pour une lecture directe et sous forme de composant installable
avec 4D Insider. Cette note technique explique d’abord l’approche utilisée par le code et fournit ensuite des
exemples et une documentation de chaque fonction.
Les paramètres attendus
La plupart des fonctions du composant XML_Utilities attendent des références et des noms d’éléments en
paramètres. Voici quelques régles et rappels sur ces types d’arguments :
• Les références d’éléments XML sont des chaînes de 16 caractères retournées par le parseur XML de 4ème
Dimension et les commandes de navigation. Appelez Analyser source XML ou Analyser variable XML
pour analyser l’XML et passez la référence retournée par 4ème Dimension aux fonctions d’XML_Utilities.
• Afin de libérer la mémoire, chaque appel à Analyser source XML ou Analyser variable XML devrait se
terminer par un appel à la commande FERMER XML une fois que l’arbre XML construit n’est plus
nécessaire. Les fonctions du composant XML_Utilities n’appellent pas FERMER XML.
• A la différence des noms 4ème Dimension, le noms XML sont sensibles à la casse. En conséquence, les
noms suivants sont différents : Nom_famille et Nom_Famille. Le composant XML_Utilities effectue des
comparaisons sur les noms en tenant compte de la casse.
• Les fonctions du composant XML_Utilities ne supportent pas les jokers dans les noms XML. En
conséquence, les deux noms suivants ne sont pas identiques : nom_famille et nom_fam@.
Echantillon XML
L’échantillon XML listé ci-dessous est utilisé dans les exemples présentés dans cette note technique :
2 / 12
<?xml version="1.0" encoding="ISO-8859-1"?>
<Root>W
<Descendant_1>A
<Descendant_2>L</Descendant_2>
<Descendant_2>K</Descendant_2>
<Descendant_2>I
<Descendant_3>N</Descendant_3>
</Descendant_2>
</Descendant_1>
<Descendant_1>G</Descendant_1>
</Root>
La table ci-dessous résume les résultats de l’application des fonctions du composant XML_Utilities à la
structure XML précédente :
Element
Nombre
d'occurences
Numéro de Existe
l'occurence
Valeur nettoyée de la
première occurence
Root
1
1
Vrai
W
Descendant_1
2
1
Vrai
A
Descendant_1
2
2
Vrai
G
Descendant_2
3
1
Vrai
L
Descendant_2
3
2
Vrai
K
Descendant_2
3
3
Vrai
I
Descendant_3
1
1
Vrai
N
Descendant_4
0
1
Faux
Chaîne vide
A propos des arbres XML et de l’ordre des éléments
Les commandes XML de 4D 2003 analysent l’XML sous forme d’arbres. Il existe plusieurs chemins et
directions pour se déplacer dans les arbres XML : haut-vers-le-bas, bas-vers-le-haut, et par niveau, ou bien de
gauche à droite ou de droite à gauche.
3 / 12
Les méthodes du composant XML_Utilities, comme presque tous les exemples de 4ème Dimension, parcourent
l’arbre XML du haut vers le bas, en utilisant la direction de gauche à droite. Ce style de parcours d’arbre est
habituellement appelé "preorder traversal" dans les livres d’algorithme. Cette stratégie est plus facile à
visualiser en utilisant une illustration simplifiée de l’arbre XML produit par l’analyse de l’échantillon XML
présenté plus haut :
Le code du composant XML_Utilities visite les neuds suivant la séquence décrite dans la table ci-dessous :
Nom du noeud
Valeur nettoyée
Numéro d'occurence
Root
W
1
Descendant_1
A
1
Descendant_2
L
1
Descendant_2
K
2
Descendant_2
I
3
Descendant_3
N
1
Descendant_1
G
2
xutil_CountOccurrences
xutil_CountOccurrences (elementRef;nomCible{;premierAppel}) -> Entier long
Paramètre
Type
Description
elementRef
nomCible
premierAppel
nombre
Alpha (16)
Texte
Booléen
Entier Long
-> référence d’un élément XML à utiliser comme point de départ
-> Nom de l’élément à retrouver.
-> Est-ce le premier appel à la méthode ?
<- Nombre d’éléments correspondants
4 / 12
La fonction xutil_CountOccurrences compte combien de fois un élément du nom spécifié apparaît dans un
arbre XML. Le résultat de l’exemple d’appel ci-dessous appliqué à la structure XML listée plus haut est 3 :
C_ALPHA(16;$xmlref)
$xmlref:=Analyser variable XML($sample_xml)
C_ENTIER LONG($count)
$count:=xutil_CountOccurrences ($xmlref;"Descendant_2")
FERMER XML($xmlref)
L’argument premierAppel est utilisé automatiquement en interne pour gérer le code récursif. Normalement, il
n’y a aucune raison de passer ce paramètre lors d’un appel à xutil_CountOccurrences.
C_ENTIER LONG($0;$count)
C_ALPHA(16;$1;$xmlref)
C_TEXTE($2;$targetName_t)
C_BOOLEEN($3;$isFirstCallInChain_b)
$xmlref:=$1
$targetName_t:=$2
$isFirstCallInChain_b:=Vrai
Si (Nombre de parametres>2)
$isFirstCallInChain_b:=$3
Fin de si
$count:=0
Si ($isFirstCallInChain_b)
C_ENTIER LONG(OK)
OK:=1 ` fixe la valeur de la variable de contôle avant d’entrer
`dans la boucle pour la première fois
Sinon
$xmlref:= Lire premier element XML ($xmlref)
Fin de si
Repeter
Tant que (OK=1)
C_TEXTE($currentName_t)
$currentName_t:=""
LIRE NOM ELEMENT XML ($xmlref;$currentName_t)
Si (xutilStringsAreEqual ($currentName_t;$targetName_t))
$count:=$count+1
$xmlref:= Lire element XML suivant ($xmlref)
Sinon
$count:=$count+xutil_CountOccurrences ($xmlref;$targetName_t;Faux)
$xmlref:= Lire element XML suivant ($xmlref)
Fin de si
Fin tant que
Jusque (OK=0)
$0:=$count
Une note sur la récursivité
La fonction xutil_CountOccurrences s’appelle elle-même de manière récursive pour inspecter chaque branche
de l’arbre XML parcouru. Si la récursivité est l’approche la plus répandue dans ce type de navigation, elle n’est
pas la seule possibilité. En interne, la récursivité fonctionne en créant une pile des appels de méthode, chacune
avec ses arguments distincts (valeurs de paramètres). Le même jeu de noeuds peut être visité à l’aide de boucles
et d’une pile maintenue à la main, typiquement en recourant à un tableau 4ème Dimension.
5 / 12
xutil_ElementExists
Description
xutil_ElementExists (elementRef ;nomCible) -> Booleen
Paramètre
elementRef
nomCible
siExiste
Type
Alpha (16)
Texte
Booleen
Description
-> référence de l’élément XML à utiliser comme point de départ
-> nom de d’élément à rechercher
Vrai si l’élément existe, Faux sinon
La fonction xutil_ElementExists teste si un élément du nom spécifié apparaît dans un arbre XML. Le résultat du
code exemple ci-dessous est Faux si on l’applique à l’extrait XML cité plus haut :
C_ALPHA(16;$xmlref)
$xmlref:=Analyser variable XML($sample_xml)
C_ENTIER LONG($count)
$count:=xutil_ElementExists ($xmlref;"first_name")
FERMER XML($xmlref)
Code source :
C_BOOLEEN($0;$elementExists_b)
C_ALPHA(16;$1;$xmlref)
C_TEXTE($2;$targetName_t)
$xmlref:=$1
$targetName_t:=$2
$elementExists_b:=Faux
C_ENTIER LONG$count)
$count:=xutil_CountOccurrences ($xmlref;$targetName_t)
Si ($count>0)
$elementExists_b:=Vrai
Sinon
$elementExists_b:=Faux
Fin de si
$0:=$elementExists_b
xutil_GetValue
Description
xutil_GetValue (elementRef;nomCible{;index{;nettoyer{;premierAppel}}}) -> Texte
Paramètre
ElementRef
nomCible
index
nettoyer
premierAppel
valeur
Type
Alpha (16)
Texte
Entier Long
Booleen
Booleen
Texte
Description
-> référence de l’élément XML à utiliser comme point de départ
-> Nom de l’élément à rechercher
-> ordre de l’occurrence de laquelle lire la valeur
-> nettoyer les espaces blancs de la valeur de l’élément ?
-> s’agit-il du premier appel à la méthode ?
<- valeur de l’élément correspondant ou chaîne vide
6 / 12
La fonction xutil_GetValue retourne la valeur de l’élément dont le nom est spécifié ou une chaîne vide si
l’élément n’est pas présent.
Le paramètre optionnel index permet de demander à lire une occurrence précise d’un élément. Une valeur par
défaut de 1 est utilisée lorsque l’argument optionnel n’est pas passé. Le résultat de l’exemple de code cidessous est la valeur "K" pour l’extrait XML cité plus haut :
C_ALPHA(16;$xmlref)
$xmlref:=Analyser variable XML ($sample_xml)
C_ENTIER LONG($count)
$count:=xutil_GetValue ($xmlref;"Descendant_2";2)
FERMER XML($xmlref)
Le paramètre optionnel nettoyer contrôle l’élimination des espaces blancs encadrant la valeur de l’élément. Une
valeur par défaut à Faux est utilisée si ce paramêtre optionnel n’est pas précisé. Lorsque nettoyer est fixé à
Vrai, les espaces blancs encadrant la valeur sont supprimés avant le retour de résultat ; lorsque nettoyer est fixé
à Faux, les espaces blancs sont préservés. Reportez-vous xutil_StripWhitespace dans les pages suivantes pour
plus d’information. L’argument premierAppel est utilisé automatiquement en interne pour gérer le code
récursif. Normalement, il n’y a aucune raison de passer ce paramètre lors d’un appel à xutil_GetValue.
Code source :
C_TEXTE($0;$resultValue_t)
C_ALPHA(16;$1;$xmlref)
C_TEXTE($2;$targetName_t)
C_ENTIER LONG($elementToFind_index)
C_BOOLEEN($4;$cleanValue_b)
C_BOOLEEN($5;$isFirstCallInChain_b)
$xmlref:=$1
$targetName_t:=$2
C_ENTIER LONG($parameters_count)
$parameters_count:=Nombre de parametres
Au cas ou ` Remplit les paramètres optionnels avec les valeurs passées ou celles par défaut
: ($parameters_count<3)
$elementToFind_index:=1
$cleanValue_b:=Faux
$isFirstCallInChain_b:=Vrai
: ($parameters_count<4)
$elementToFind_index:=$3
$cleanValue_b:=Faux
$isFirstCallInChain_b:=Vrai
: ($parameters_count<5)
$elementToFind_index:=$3
$cleanValue_b:=$4
$isFirstCallInChain_b:=Vrai
: ($parameters_count<6)
$elementToFind_index:=$3
$cleanValue_b:=$4
$isFirstCallInChain_b:=$5
Fin de cas
$resultValue_t:=""
Si ($isFirstCallInChain_b)
C_BOOLEEN(xutil_GetValue_stop)
xutil_GetValue_stop:=Faux
C_ENTIER LONG(xutil_GetValueMatches_count)
7 / 12
xutil_GetValueMatches_count:=0
C_ENTIER LONG(OK)
OK:=1 ` fixe la valeur de la variable de contrôle avant d’entrer dans la boucle pour la première fois
Sinon
$xmlref:= Lire premier element XML ($xmlref)
Fin de si
Repeter
Tant que ((OK=1) & (xutil_GetValue_stop=Faux))
C_TEXTE($currentValue_t)
$currentName_t:=""
$currentValue_t:=""
LIRE NOM ELEMENT XML ($xmlref;$currentName_t)
LIRE VALEUR ELEMENT XML ($xmlref;$currentValue_t)
Si (xutilStringsAreEqual ($currentName_t;$targetName_t))
xutil_GetValueMatches_count:=xutil_GetValueMatches_count+1
Si (xutil_GetValueMatches_count=$elementToFind_index)
$resultValue_t:=$currentValue_t
xutil_GetValue_stop:=Vrai
OK:=0
Fin de si
$xmlref:= Lire element XML suivant ($xmlref)
Sinon
$resultValue_t:=xutil_GetValue
($xmlref;$targetName_t;$elementToFind_index;$cleanValue_b;False)
$xmlref:= Lire element XML suivant ($xmlref)
Fin de si
Fin tant que
Jusque ((OK=0) | xutil_GetValue_stop)
Si ($cleanValue_b)
$resultValue_t:=xutil_StripWhitespace ($resultValue_t)
Fin de si
$0:=$resultValue_t
xutil_StripWhitespace
xutil_StripWhitespace (source) -> Texte
Paramètre
source
Résultat
Type
Texte
Texte
Description
-> texte dont les espaces blancs doivent être retirés
<- le texte initial dont les espaces blancs ont été retirés
XML définit quatre caractères comme espaces blancs, listés dans le tableau ci-dessous :
Nom
Tab
Line feed (retour à la ligne)
Carriage return (retour chariot)
Espace
Code ascii
9
10
13
32
Hexa
09
0A
0D
20
8 / 12
Les espaces blancs améliorent grandement la lisibilité des documents XML, mais sont souvent indésirables lors
du travail avec les valeurs des éléments XML. Par exemple, la valeur de la première instance du Descendant_1
dans l’extrait XML cité plus haut est longue de 16 caractères. La voici avec les noms des espaces blancs
mentionnés explicitement :
A<retour_chariot>
<retour_chariot >
<tab> <tab> <retour_chariot >
<retour_chariot >
<tab> <tab> <retour_chariot >
<retour_chariot >
<tab> <tab> <retour_chariot >
<retour_chariot >
<tab>
La valeur nettoyée de cet élément est le seul caractère "A".
C_TEXTE($0;$result_t)
C_TEXTE($1;$source_t)
$source_t:=$1
$result_t:=""
` ------------------------------------------------------------------------------------------------` Prépare un tableau de tous les caractères définis comme espaces blancs
` ------------------------------------------------------------------------------------------------TABLEAU ENTIER LONG($whitespace_al;4)
$whitespace_al{1}:=Tabulation
$whitespace_al{2}:=Retour à la ligne
$whitespace_al{3}:=Retour chariot
$whitespace_al{4}:=Espacement
C_ENTIER LONG($firstCharacter_index)
C_ENTIER LONG($lastCharacter_index)
$firstCharacter_index:=0
$lastCharacter_index:=0
` --------------------------------------------------------` Trouver le premier caractère non espace blanc
` --------------------------------------------------------C_ENTIER LONG($length)
C_ ENTIER LONG($index)
C_ ENTIER LONG($element)
C_ ENTIER LONG($ascii)
$length:=Longueur($source_t)
$index:=0
$element:=0
$ascii:=0
C_BOOLEEN($done)
$done:=Faux
Repeter
$index:=$index+1
Si ($index>$length)
$done:=Vrai
Sinon
$ascii:=Code ascii($source_t=$index=)
$element:=Chercher dans tableau($whitespace_al;$ascii)
Si ($element<0)
` Le caractère testé n’est pas un espace blanc : c’est ce que nous cherchions
$firstCharacter_index:=$index
9 / 12
$done:=Vrai
Fin de si
Fin de si
Jusque ($done)
` --------------------------------------------------------` Trouver le dernier caractère non espace blanc
` --------------------------------------------------------C_ENTIER LONG($index)
C_ENTIER LONG($element)
$index:=Longueur($source_t)+1
$element:=0
C_BOOLEEN($done)
$done:=Faux
Repeter ` marche arrière à travers la chaîne à la recherche du dernier caractère non espace blanc
$index:=$index-1
Si ($index=0)
$done:=Vrai
Sinon
$ascii:=Ascii($source_t=$index=)
$element:=Chercher dans tableau($whitespace_al;$ascii)
Si ($element<0)
` Le caractère testé n’est pas un espace blanc : c’est ce que nous cherchions
$lastCharacter_index:=$index
$done:=True
Fin de si
Fin de si
Jusque ($done)
` --------------------------------------------------------` Nettoye la chaîne source.
` --------------------------------------------------------C_ENTIER LONG($result_length)
$result_length:=$lastCharacter_index-$firstCharacter_index+1
Au cas ou
: ($lastCharacter_index=0)
$result_t:=""
: ($firstCharacter_index=0)
$result_t:=""
: ($result_length<1)
$result_t:=""
Sinon
$result_t:=Sous chaine($source_t;$firstCharacter_index;$result_length)
Fin de cas
$0:=$result_t
xutilStringsAreEqual
Le composant inclut également une méthode privée qui compare l’égalité de deux chaînes. Ce code est nécessaire
car le système de comparaison de chaîne natif à 4ème Dimension, dépendant des réglages de langue, ignore les
différences de casse et les caractères diacritiques. Les chaînes XML sont toujours sensibles à la casse. Le
tableau ci-dessous compare la manière dont 4ème Dimension et XML considère l’équivalence de quelques
échantillons de chaînes :
10 / 12
Chaîne exemple
Chaîne de
comparaison
Egalité dans 4D
Egalité en XML
a-b-c-d-e
a-b-c-d-e
Oui
Oui
a-b-c-d-e
a-b-c-d-E
Oui
Non
a-b-c-d-e
a-b-c-d-é
Oui
Non
a-b-c-d-e
A-B-C-D-E
Oui
Non
La méthode xutilStringsAreEqual compare des chaînes caractère par caractère en se fondant sur le code ascii
pour retourner un résultat compatible avec les règles des noms XML.
C_BOOLEEN($0;$StringsAreEqual_b)
C_TEXTE($1;$baseString_t)
C_TEXTE($2;$comparisonString_t)
$baseString_t:=$1
$comparisonString_t:=$2
$StringsAreEqual_b:=Faux
Au cas ou
: ($baseString_t#$comparisonString_t)` Echec dans la comparaison native par 4D
$StringsAreEqual_b:=Faux
: ($baseString_t="") ` Les deux chaînes sont vides
$StringsAreEqual_b:=Vrai
Sinon
` Effectue une comparaison octet par octet
C_ENTIER LONG($length)
C_ENTIER LONG($index)
C_BOOLEEN($continue)
$length:=Longueur($baseString_t)
$index:=1 ` les chaines ne sont pas valides
C_ENTIER LONG($base_ascii)
C_ENTIER LONG($comparison_ascii)
$continue:=Vrai
$StringsAreEqual_b:=Vrai
Tant que ($continue)
$base_ascii:=Code ascii($baseString_t=$index=)
$comparison_ascii:=Code ascii($comparisonString_t=$index=)
Au cas ou
: ($base_ascii=$comparison_ascii)
$index:=$index+1
: ($base_ascii#$comparison_ascii)
$StringsAreEqual_b:=Faux
$continue:=Faux
Fin de cas
Si ($index>$length)
$continue:=Faux
Fin de si
11 / 12
Fin tant que
Fin de cas
$0:=$StringsAreEqual_b
12 / 12