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