Générer du XML avec 4D 2004 - 1re partie

Christophe KEROMEN,

La version 2004 nous a apporté deux jeux de commandes pour générer des structures XML, l’un préfixé par DOM, l’autre par SAX. Dans un premier temps, nous utiliserons l’approche DOM pour mettre à jour le code de la note technique « Exemple d’utilisation d’XML : stockage de profils ». ♪

- Titre : Générer du XML avec 4D 2004 - 1re partie

- Auteur : Christophe KEROMEN,

- Parution : 1 septembre 2004

- Licence : Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- I. Approche DOM

- Gestion de l’arbre DOM

- Remplissage de l’arbre

- II. Modification de l’enregistrement d’une structure XML

- Méthode XMLvalues_Record_Save

- Méthode XMLvalues_Values2XML_2004

- III. Génération d’un document XML pour une sélection d’enregistrements

- Appel depuis l’extérieur

- Présentation de l’exemple

- Traitement par DOM

- Méthode CD_ListeXML

- Méthode DOM_Liste_EnregistrementsVersXML

- Conversion des champs de l’enregistrement, DOM_EnregistrementVersXML

- Méthode DOM_set_ElementWithValue

- IV. Conclusion

- V. Base exemple

I - Approche DOM

Gestion de l’arbre DOM

Tout se passe en mémoire et le processus commence par la création d’un arbre DOM. Cela s’effectue en passant le nom de l’élément racine à la commande DOM Creer ref XML qui en échange nous renvoie une référence (alpha 16) sur l’élément créé.

La commande DOM ECRIRE OPTIONS XML permet de fixer certaines options de la structure XML.

Encodage

Ce paramètre se passe sous la forme d’une chaîne de caractère spécifiant un encodage (UTF-8, UTF-16, ISO-8859-1…). La liste des valeurs possibles se retrouve dans la liste déroulante « encodage » dans l’onglet XML du dialogue d’export en utilisation directe. Ce paramètre se retrouvera dans l’attribut encoding de la déclaration XML du document.
Ex. : en passant la valeur UTF-8, on obtiendra la déclaration :

<?xml version="1.0" encoding="UTF-8" ?>

La portée de ce paramètre ne se limite pas à fixer l’attribut de la déclaration XML, il s’agit d’une option active que 4D utilisera pour encoder automatiquement toutes les valeurs qui lui seront passées.

Autonome

Ce paramètre permet de préciser si la structure XML se réfère ou non à une DTD externe, sa valeur se retrouvera dans l’attribut standalone de la déclaration XML du document.
Ex. : en passant Vrai, on obtiendra la déclaration suivante :

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>

Indentation

Ce paramètre passé à Vrai entraîne une mise en forme de l’arbre XML à l’aide d’espaces et de retours chariot :

Figure 1 - Indentation automatique de l’arbre XML

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<valeursXML>

<Champ1>
<value1>liste1_choix1 </value>
<value1>liste1_choix3 </value>
<value1>liste1_choix2 </value>
</Champ1>

<Champ2>
<value1>liste2_choix2 </value>
<value1>liste2_choix4 </value>
</Champ2>

<Champ3>
<value1>liste3_choix2 </value>
</Champ3>

</valeursXML>

Passé à Faux, la structure se présente de la manière suivante :

Figure 2 - Sans indentation automatique de l’arbre XML

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<valeursXML><Champ1><value1>liste1_choix1</value><value1>liste1_choix3 </value><value1>
liste1_choix2</value></Champ1><Champ2><value1>liste2_choix2</value><value1>liste2_choix4</
value></Champ2><Champ3><value1>liste3_choix2</value></Champ3></valeursXML>

Certains parseurs XML n’apprécient que très moyennement les espaces blancs (whitespaces) de mise en forme. Il est donc important de pouvoir maîtriser ce paramètre. Contrairement aux deux premiers paramètres, la valeur passée ne se retrouve pas sous forme d’attributs dans le document XML cible.

DOM EXPORTER VERS VARIABLE permet de convertir l’arbre en mémoire en variable texte ou BLOB (opération de sérialisation). Son pendant pour écrire l’arbre dans un document est DOM EXPORTER VERS FICHIER. Notez que cette commande ne vérifie pas que votre document est bien formé ni valide. Si vous souhaitez le faire, il faut utiliser la commande DOM Analyser variable XML ou DOM Analyser source XML.

Une fois l’arbre construit et sérialisé dans une variable ou un document disque, il faut penser à le supprimer de la mémoire par l’instruction DOM FERMER XML.

Remplissage de l’arbre

Maintenant que nous avons vu comment créer l’arbre, le sérialiser et le libérer de la mémoire, il serait intéressant de savoir comment le remplir !

Pour cela une première série de commandes travaille sur les éléments :
· DOM Creer element XML ;
· DOM ECRIRE VALEUR ELEMENT XML ;
· DOM ECRIRE NOM ELEMENT XML ;
· DOM SUPPRIMER ELEMENT XML.

Tandis qu’une dernière commande s’intéresse aux attributs :
DOM ECRIRE ATTRIBUT XML.

4D se charge automatiquement :

· de l’encodage des valeurs passées ;

· de refermer les éléments :

La commande

1. $_vt_RefElement :=DOM Creer element XML($_vt_RefParent ; "toto")

produit en réalité directement <toto></toto>.

La commande

DOM ECRIRE VALEUR ELEMENT XML ($_vt_RefElement ;"maValeur")

se charge ensuite d’insérer la valeur de l’élément pour obtenir : <toto>maValeur</toto>.

Note

Dans la version 2004, les noms des commandes de construction et de parcours d’un arbre DOM ont été renommés pour plus de cohérence avec les commandes d’écriture. Toutes sont désormais préfixées par DOM, ainsi Analyser source XML devient DOM Analyser source XML.

II - Modification de l’enregistrement d’une structure XML

Méthode XMLvalues_Record_Save

L’enregistrement d’une structure XML s’effectuait dans la section « save » de notre méthode xmlvalues_Record . Pour mieux isoler nos modifications, nous allons créer une méthode XMLvalues_Record_Save qui sera appelée à partir de cette section. Cette méthode sera chargée de convertir les champs de notre interface de saisie de valeurs en XML via l’approche DOM.

1. ` ----------------------------------------------------

2. ` Nom utilisateur (OS) : Christophe Keromen

3. ` Date et heure : 13/05/04, 22:05:04

4. ` ----------------------------------------------------

5. ` Methode : XMLvalues_Record_Save

6. ` Description

7. ` Conversion des champs en XML

8. `

9. ` Parametres

10. `$0:TEXTE:structure XML à enregistrer

11. ` ----------------------------------------------------

13. C_TEXTE($0)

14. C_TEXTE($_s_XML)

15. $_s_XML:=""   `la structure XML à construire

16. `--- Création de l’arbre DOM et de l’élément racine

17. C_TEXTE($_s_root)

18. $_s_root:="valeursXML"

19. C_TEXTE($_vt_Ref_DOM_XML)

20. $_vt_Ref_DOM_XML:=DOM Creer ref XML($_s_root)

21. `--- Déclaration XML

22. C_TEXTE($_vt_Encoding)

23. $_vt_Encoding:="UTF-8"

24. C_BOOLEEN($_vb_StandAlone)

25. $_vb_StandAlone:=Vrai

26. C_BOOLEEN($_vb_siIndentation)

27. $_vb_siIndentation:=Vrai  `indentation pour la facilité de lecture de la structure

28. DOM ECRIRE OPTIONS XML ($_vt_Ref_DOM_XML;$_vt_Encoding;$_vb_StandAlone;$_vb_siIndentation)

29. $_s_radical:="xmlvalues_S_value"

31. Boucle ($i;1;Taille tableau(xmlvalues_T_fields))

32. `pour chaque champ de concaténation

33. $_Pt:=Pointeur vers($_s_radical+Chaine($i))

35. Si (Non(Nil($_Pt)))

36. ` transforme une liste de valeurs

37. `en série d’éléments XML <value> fils de l’élément passé

38. XMLvalues_Values2XML_2004 ($_vt_Ref_DOM_XML;xmlvalues_T_fields{$i};$_Pt)

39. Fin de si

41. Fin de boucle

43. `--- Sérialisons notre arbre DOM dans une variable de type texte

44. DOM EXPORTER VERS VARIABLE($_vt_Ref_DOM_XML;$_s_XML)

45. $0:=$_s_XML

46. `libération de la mémoire

47. DOM FERMER XML($_vt_Ref_DOM_XML)

Méthode XMLvalues_Values2XML_2004

La méthode XMLvalues_Record_Save appelle pour chaque champ XMLvalues_Values2XML_2004 qui se charge de convertir la liste des valeurs choisies en structure XML :

1. `----------------------------------------------------

2. `Nom utilisateur (OS) : CK

3. `Date et heure : 13-5-2004

4. `----------------------------------------------------

5. `Méthode : XMLvalues_Values2XML_2004

6. `Description

7. `transforme une liste de valeurs $3

8. `en série d’éléments XML <value> fils de l’élément $2

9. `Paramètres

10. `$1:TEXTE:Ref de l’arbre DOM

11. `$2:TEXTE:nom de l’élément père

12. `$3:POINTEUR:liste de valeurs à transformer

13. `----------------------------------------------------

15. C_TEXTE($1)

16. C_TEXTE($2)

17. C_POINTEUR($3)

18. C_TEXTE($_vt_Ref_DOM_XML)

20. $_vt_Ref_DOM_XML:=$1

22. C_TEXTE($_s_FieldElement;$_s_ChildElement)

23. $_s_FieldElement:=$2

24. $_s_ChildElement:="value"

25. C_POINTEUR($_Pt_valeurs)

26. $_Pt_valeurs:=$3

28. Si (Non(Nil($_Pt_valeurs)))

30. Si ($_Pt_valeurs->#"")

32. `--- Ouverture de l’élément <Champ{indice}>

33. C_TEXTE($_vt_RefElement)

34. $_vt_RefElement:=DOM Creer element XML($_vt_Ref_DOM_XML;$_s_FieldElement)

36. `--- Transformation de la liste de valeurs séparées par des CR en tableau

37. TABLEAU TEXTE(xmlvalues_T_temp;0)  `variable globale "locale"

38. zgen_TexteVersTableau ($_Pt_valeurs->;->xmlvalues_T_temp;Caractere(Retour chariot ))

40. `--- Parcours du tableau et transformation de chaque ligne en élément

41. Boucle($i;1;Taille tableau(xmlvalues_T_temp))

42. `ouverture de l’élément enfant <value>

43. C_TEXTE($_vt_RefValue)

44. $_vt_RefValue:=DOM Creer element XML ($_vt_RefElement;$_s_ChildElement)

45. `écriture de la valeur de l’élément <value>

46. $_s_value:=xmlvalues_T_temp{$i}

47. DOM ECRIRE VALEUR ELEMENT XML($_vt_RefValue;$_s_value)

48. Fin de boucle

50. TABLEAU TEXTE(xmlvalues_T_temp;0)

52. Fin de si

54. Fin de si

III - Génération d’un document XML pour une sélection d’enregistrements

Maintenant que nous maîtrisons l’exécution des commandes DOM dans un cadre particulier, nous allons réaliser une routine qui aura pour objectif de convertir une sélection d’enregistrements en XML de manière générique. Dans cette première note technique, nous utiliserons les commandes DOM et nous verrons dans une seconde partie trois autres moyens de parvenir à nos fins.

Appel depuis l’extérieur

Ce genre de routines sera très utile pour la publication de données vers des clients non 4D : formulaires dynamiques, clients SOAP…

Notre code est donc conçu de façon à ce qu’il puisse être appelé :

· depuis un client HTML par un simple 4DACTION ;
· depuis un client SOAP.

Présentation de l’exemple

Nous appliquerons ces routines à une structure volontairement très simple comprenant une seule table :

Figure 3 : la structure d’exemple

Notre dialogue d’interface, accessible par le menu Fichier/démo, nous permettra d’appeler les différents modes de génération et de visualiser le résultat présenté dans une zone texte :

Figure 4 : dialogue de test des différents modes de génération XML

Notez qu’en version 2004, les zones de texte sont désormais pourvues d’un ascenseur horizontal.

Traitement par DOM

Nous allons parcourir la sélection, et pour chaque enregistrement, parcourir l’ensemble des champs de la table et
les convertir en XML. Nous ne traitons pas les éléments binaires pour lesquels XML ne propose pas aujourd’hui
de solution simple et efficace.

Voici notre pseudocode :

DOM_ListeEnregistrementsVersXML : parcourt une sélection d’enregistrements et retourne une structure XML :

<root>
<nom_table>structure de l’enregistrement</nom_table>
<nom_table>structure de l’enregistrement</nom_table>
... (autant de fois que d’enregistrements dans la sélection)
</root>
Pour chaque enregistrement DOM_EnregistrementVersXML : convertit chaque champ en un élément
<nom_du_champ>valeur du champ</nom_du_champ>
Pour chaque champ DOM_set_ElementWithValue : écrit un élément avec sa valeur

Et le résultat dans Internet Explorer (nous retrouvons ici l’un des points forts de XML, si le document s’ouvre dans le navigateur c’est qu’il est bien formé, c’est-à-dire qu’il répond aux règles syntaxiques XML) :

Figure 5 : le résultat de la conversion en XML visualisé dans Internet Explorer

Notez l’adresse d’appel : http://localhost:8080/4DACTION/CD_ListeXML/DOM.
Ce qui signifie envoyer une requête Web (http://) au serveur Web sur la même machine (localhost ou 127.0.0.1) sur le port 8080, appeler le point d’entrée 4DACTION/CD_ListeXML/DOM. 4DACTION étant une URL particulière pour le serveur Web de 4D, celui-ci traduit la requête en « appeler la méthode CD_ListeXML en lui passant le paramètre /DOM ».

Méthode CD_ListeXML

Voici le code de la méthode CD_ListeXML

1. ` ----------------------------------------------------

2. ` Nom utilisateur (OS) : Christophe Keromen

3. ` Date et heure : 16/07/04, 09:55:08

4. ` ----------------------------------------------------

5. ` Methode : CD_Liste_XML

6. ` Description

7. ` Conversion d’une sélection d’utilisateur en XML et renvoie à un appel HTTP ou SOAP

8. ` cette méthode peut aussi être appelée par get "http://serveur:8080/4DACTION/CD_Liste_XML/mode"

9. `

10. ` Parametres

11. `$1:TEXTE:Mode (DOM-SAX-QR-Web)

12. ` ----------------------------------------------------

14. C_TEXTE($1)

15. C_TEXTE($_vt_Mode)

16. $_vt_Mode:=$1

18. `---Décodage du paramètre d’entrée

19. Si (Est une requete SOAP)

20. `en mode dynamique, 4D s’occupe de tout

21. DECLARATION SOAP($1;Est un texte ;SOAP entrée ;"modeConversionXML")

22. Sinon  `requête HTTP

23. $_vt_Mode:=Sous chaine($_vt_Mode;2)  `pour enlever le "/", ex. dans "/DOM"

24. Fin de si

26. `--- Constitution de la sélection

27. LECTURE SEULEMENT([CD])

28. TOUT SELECTIONNER([CD])

30. TRIER([CD];[CD]Titre;>)

32. `--- conversion en XML

33. C_TEXTE($_vt_Methode_CallBack)

34. $_vt_Methode_CallBack:=""

36. C_BLOB(soap_vx_Return)

37. FIXER TAILLE BLOB(soap_vx_Return;0)

39. C_TEXTE(soap_vt_Return)

40. soap_vt_Return:=""

42. Au cas ou

43. : ($_vt_Mode="DOM")

44. soap_vt_Return:=DOM_ListeEnregistrementsVersXML (->[CD];$_vt_Methode_CallBack;->soap_vx_Return)

45. : ($_vt_Mode="SAX")

46. soap_vt_Return:=SAX_ListeEnregistrementsVersXML (->[CD];$_vt_Methode_CallBack;->soap_vx_Return)

47. : ($_vt_Mode="QR")

48. soap_vt_Return:=QR_ListeEnregistrementsVersXML (->[CD];$_vt_Methode_CallBack;->soap_vx_Return)

49. : ($_vt_Mode="Web")

50. soap_vt_Return:=Web_ListeEnregistrementsVersXML (->[CD] ;$_vt_Methode_CallBack ;->soap_vx_Return)

51. Fin de cas

53. `--- Renvoi du résultat

54. Si (Est une requete SOAP)

55. DECLARATION SOAP(soap_vt_Return ;Est un texte ;SOAP sortie ; "CD_Liste_XML_texte")

56. DECLARATION SOAP(soap_vx_Return ;Est un BLOB ;SOAP sortie ; "CD_Liste_XML_BLOB")

57. `maintenant 4D s’occupe de l’encodage et de l’envoi

58. Sinon  `requête http

59. `précisons le type MIME "text/xml" pour que le navigateur reconnaisse le XML

60. ENVOYER BLOB HTML(soap_vx_Return ; "text/xml")

61. Fin de si

Commentaires

Remarquez la gestion des paramètres d’entrée-sortie suivant l’origine de l’appel, client SOAP ou requête http.

Avec SOAP, les paramètres sont nommés, décrits dans le WSDL et tout assistant du type de celui de 4D permet de générer facilement le code d’appel dit méthode proxy :

En revanche, dans le cas d’une requête http, il n’existe aucun moyen de savoir quelle URL appeler et quel paramètre passer et suivant quelle syntaxe. D’un strict point de vue de consommation de ressources, la requête http reste cependant plus performante.

Méthode DOM_Liste_EnregistrementsVersXML

1. ` ----------------------------------------------------

2. ` Nom utilisateur (OS) : christophe Keromen

3. ` Date et heure : 30/06/04, 23:02:34

4. ` ----------------------------------------------------

5. ` Methode : DOM_ListeEnregistrementsVersXML

6. ` Description

7. ` convertit une liste d’enregistrements en structure XML via écriture DOM

8. `

9. ` Notes :

10. `- 4D 2004 (utilise les commandes d’écriture DOM)

11. `- la sélection doit déjà exister

12. `- ici on retourne ds un BLOB, attention à la taille du XML généré

13. `

14. ` Parametres

15. `$1:POINTEUR:Table

16. `$2:TEXTE:Methode à appeler en callback pour chaque enregistrement

17. `$3:POINTEUR:BLOB:structure XML

18. `$0:TEXTE:structure XML

19. ` ----------------------------------------------------

21. C_POINTEUR($1)

22. C_POINTEUR($_vp_Table)

23. $_vp_Table:=$1

25. C_TEXTE($2)

26. C_TEXTE($_vt_Methode_CallBack)

27. $_vt_Methode_CallBack:=$2

29. C_POINTEUR($3)

31. C_TEXTE($0)

32. $0:=""

34. XML_AppelerSurErreur_set  `Installe une gestion d’erreurs

36. C_TEXTE($_vt_Last_xml_Error)

37. $_vt_Last_xml_Error:=""

39. `--- Création du document XML en lui passant la racine nommée arbitrairement "root"

40. C_TEXTE($_vt_root)

41. $_vt_root:="root"

43. C_TEXTE($_vt_Ref_XML)

44. $_vt_Ref_XML:=DOM Creer ref XML($_vt_root)

46. `--- Ecriture des options

47. C_TEXTE($_vt_Encodage)

48. $_vt_Encodage:="UTF-8"

49. `$_vt_Encodage:="ISO-8859-1"

51. C_BOOLEEN($_vb_SiAutonome)

52. $_vb_SiAutonome:=Vrai  `avec ou sans DTD externe

54. C_BOOLEEN($_vb_SiIndentation)

55. $_vb_SiIndentation:=Vrai  `avec whitespaces ou non de présentation

57. DOM ECRIRE OPTIONS XML($_vt_Ref_XML;$_vt_Encodage;$_vb_SiAutonome;$_vb_SiIndentation)

59. `--- Export des enregistrements par parcours de la sélection

60. C_ENTIER($i)

62. Boucle ($i;1;Enregistrements trouves($_vp_Table->))

64. `--- Création de l’élément complexe contenant les champs de l’enregistrement courant

65. C_ENTIER($_ve_SiEncodingISO)

66. $_ve_SiEncodingISO:=0  `sans encodage ISO (encodage effectué automatiquement par les commandes DOM)

68. C_TEXTE($_vt_ElementName)  `nom de l’élément, on pourrait églt prendre un nom générique , ex.<row>

69. $_vt_ElementName:=XMLw_Replace_Char (Nom de la table($_vp_Table);"tag";$_ve_SiEncodingISO)

71. C_TEXTE($_vt_RefElementRecord)

72. $_vt_RefElementRecord:=DOM Creer element XML($_vt_Ref_XML;$_vt_ElementName)

74. `--- Rétro-appel de la méthode convertissant l’enregistrement courant en XML

75. Si ($_vt_Methode_CallBack#"")

77. C_TEXTE($_vt_callback)

78. $_vt_callback:=$_vt_Methode_CallBack+"("+Caractere(Guillemets)+$_vt_RefElementRecord+Caractere(Guillemets )+")"

79. EXECUTER($_vt_callback)

81. Sinon  `Générique de conversion en XML

83. C_ENTIER($_ve_siEncodageIso)

84. $_ve_siEncodageIso:=0  `pas d’encodage ISO

85. DOM_EnregistrementVersXML ($_vt_RefElementRecord;$_vp_Table;$_vt_ElementName;$_ve_siEncodageIso)

87. Fin de si

89. $_vt_Last_xml_Error:=XML_AppelerSurErreur_getLastErr

91. Si ($_vt_Last_xml_Error#"") | (ok=0)  `une erreur est survenue on arrête

93. $i:=Enregistrements trouves($_vp_Table->)+1

95. Sinon

97. ENREGISTREMENT SUIVANT($_vp_Table->)

99. Fin de si

101. Fin de boucle

103. `--- Gestion des erreurs, validation et enregistrement

104. Si ($_vt_Last_xml_Error="")  `pas d’erreur

106. `--- Le doc est-il bien formé ? (on pourrait aussi le valider/DTD)

107. C_BLOB($_vx_XML)

108. DOM EXPORTER VERS VARIABLE($_vt_Ref_XML;$_vx_XML)

109. C_TEXTE($_vt_Ref_XML_Analyse)

110. $_vt_Ref_XML_Analyse:=DOM Analyser variable XML($_vx_XML)

112. `--- Conversion en texte

113. DOM EXPORTER VERS VARIABLE($_vt_Ref_XML;$_vt_XML)

114. `Bug 4D : DOM EXPORTER VERS VARIABLE devrait décoder en Mac Roman

115. $_vt_XML:=ISO vers Mac($_vt_XML)

117. ECRIRE TEXTE DANS PRESSE PAPIERS($_vt_XML)

119. Si (ok=1) & (DOM_ifNoError ($_vt_Ref_XML_Analyse))

121. `Retour des valeurs

122. $0:=$_vt_XML

123. $3->:=$_vx_XML

125. Sinon

127. FIXER TAILLE BLOB($3->;0)

128. ALERTE("Doc XML mal formé : l’arbre XML a été copié dans les presse-papiers")

130. Fin de si

132. DOM FERMER XML($_vt_Ref_XML_Analyse)  `l’arbre analysé

134. Sinon  `une erreur est survenue

136. ALERTE($_vt_Last_xml_Error)

138. Fin de si

140. DOM FERMER XML($_vt_Ref_XML)  `l’arbre DOM généré

141. DEBUT SELECTION($_vp_Table->)  `on remet le pointeur en début de sélection

Commentaires

Il est possible de passer un paramètre $2 désignant une méthode qui se chargera de convertir l’enregistrement courant en XML au lieu de la méthode générique DOM_EnregistrementVersXML. La routine XML_AppelerSurErreur_set appelle une simple gestion d’erreurs, la dernière erreur rencontrée peut être retrouvée en appelant la méthode accesseur XML_AppelerSurErreur_getLastErr.

DOM creer element XML se charge d’encoder les valeurs passées en accord avec l’option fixée dans DOM ECRIRE OPTIONS XML. Cependant, cela ne comprend pas la vérification des règles syntaxiques XML par exemple l’interdiction d’espace dans les noms d’éléments. C’est pourquoi nous traitons au préalable le nom de l’élément par la routine XMLw_Replace_Char déjà présentée dans la note technique 4D-200402-04- FR.

Une fois toute notre sélection d’enregistrements parcourue, nous utilisons la commande DOM EXPORTER VERS VARIABLE pour récupérer notre arbre DOM dans un BLOB que nous repassons immédiatement à DOM Analyser variable XML afin de vérifier si notre document est bien formé. Si tel est le cas, nous renvoyons à la méthode appelante la structure XML en BLOB et la structure XML convertie en texte. Cette dernière conversion souffre d’un bug de 4e Dimension dans la version à la date de rédaction.

En effet, DOM EXPORTER VERS VARIABLE($_vt_Ref_XML;$_vt_XML) devrait décoder notre arbre XML encodé en UTF-8 pour, d’après la documentation, nous le ranger dans une variable texte en codage Mac Roman. Le décodage n’est pourtant pas effectué. C’est pourquoi nous conseillons en attendant la correction de ce bug et pour récupérer une version texte, de passer plutôt par un encodage en ISO-8859-1 puis de décoder manuellement (ISO vers Mac) la version texte de la structure XML.

Conversion des champs de l’enregistrement, DOM_EnregistrementVersXML

1. ` ----------------------------------------------------

2. ` Nom utilisateur (OS) : christophe Keromen

3. ` Date et heure : 15/07/04, 09:35:02

4. ` ----------------------------------------------------

5. ` Methode : DOM_EnregistrementVersXML

6. ` Description

7. ` Convertit de manière générique un enregistrement en XML

8. `

9. ` Notes :

10. ` - ne traite pas les champs binaires

11. `

12. ` Parametres

13. ` $1:TEXTE:Ref de l’élément parent

14. ` $2:POINTEUR:Table

15. ` $3:TEXTE:Nom parent pour préfixer

16. ` $4:ENTIER:1 si encodage ISO à appliquer

17. ` ----------------------------------------------------

18. ` DOM_EnregistrementVersXML ($_vt_RefElementRecord;$_vp_Table;$_vt_ElementName;

19. ` $_ ve_siEncodageIso)

21. C_TEXTE($1)

22. C_TEXTE($_vt_RefElement)

23. $_vt_RefElement:=$1

25. C_POINTEUR($2)

26. C_POINTEUR($_vp_PtTable)

27. $_vp_PtTable:=$2

29. C_ENTIER LONG($_vl_TableNo)

30. $_vl_TableNo:=Table($_vp_PtTable)

32. C_TEXTE($_vt_prefixe)

33. $_vt_prefixe:=""  `pour garantir unicité entre tables

35. C_ENTIER($_ve_siEncodageIso)

36. $_ve_siEncodageIso:=0  `pas d’encodage ISO

38. Si (Nombre de parametres=2)

39. Sinon

40. $_vt_prefixe:=$3

41. $_ve_siEncodageIso:=$4

42. Fin de si

44. C_ENTIER($i)

45. Boucle ($i;1;Nombre de champs($_vl_TableNo))

47. C_POINTEUR($_vp_Champ)

48. $_vp_Champ:=Champ($_vl_TableNo;$i)

50. Si (xmlw_Si_ChampBinaire ($_vp_Champ))

51. `on ne traite pas ds cette version

53. Sinon

54. C_TEXTE($_vt_TagName)

55. $_vt_TagName:=XMLw_Replace_Char (Nom du champ($_vl_TableNo;$i);"tag";$_ve_SiEncodingISO)

57. Si ($_vt_prefixe#"")

58. $_vt_TagName:=$_vt_prefixe+"."+$_vt_TagName

59. Fin de si

61. C_ENTIER($_vl_TypeChamp)

62. LIRE PROPRIETES CHAMP($_vp_Champ;$_vl_TypeChamp)

63. C_TEXTE($_vt_Value)

64. $_vt_Value:=""

66. Au cas ou

68. : (($_vl_TypeChamp=Est un champ alpha ) | ($_vl_TypeChamp=Est un texte ))

69. $_vt_Value:=$_vp_Champ->

71. : (($_vl_TypeChamp=Est un numérique ) | ($_vl_TypeChamp=Est un entier ) | ($_vl_TypeChamp=Est un entier long ))

72. $_vt_Value:=Chaine($_vp_Champ->)

74. : (($_vl_TypeChamp=Est une date ))

75. $_vt_Value:=Chaine($_vp_Champ->;8)  `date Time

77. : (($_vl_TypeChamp=Est une heure ))

78. $_vt_Value:=Chaine($_vp_Champ->;h mn s )

80. : (($_vl_TypeChamp=Est un booléen ))

81. $_vt_Value:=Chaine(Num($_vp_Champ->))

83. : ($_vl_TypeChamp=Est un BLOB )  `conversion base64 ?

84. `-> il faut utiliser BASh, ça marche très bien

85. $_vt_Value:="N/A"

87. : ($_vl_TypeChamp=Est une image )  `conversion base 64 ?

88. $_vt_Value:="N/A"

90. Sinon

91. `$0:=("Internal Error";"Unkown Fieldtyp - cannot handle";$fieldname)

93. Fin de cas

95. DOM_set_ElementWithValue ($_vt_RefElement;$_vt_TagName;$_vt_Value)

97. Fin de si

99. Fin de boucle

Commentaires

La routine xmlw_Si_ChampBinaire nous sert à filtrer les champs binaires que nous ne pouvons pas facilement convertir en texte. Une solution consisterait à utiliser un encodage en base64 grâce à la nouvelle commande de la version 2004, ENCODER.

Comme pour les noms de tables, nous prétraitons les noms de champs dans la routine XMLw_Replace_Char. Par exemple, le nom du champ “[CD]Date Stock« devient “DateStock“. 4D n’effectue pas automatiquement ce traitement, or les espaces étant interdits en XML dans les noms de champs, cela se traduirait par un document XML mal-formé et donc inexploitable.

Nous rajoutons également un préfixe (le nom de la table) au nom du champ, ainsi “[CD]Date Stock« devient réellement “CD.DateStock« dans le document XML produit. Dans le cadre de cet exemple, cela n’a pas réellement d’intérêt. Dans une version plus évoluée pouvant mixer au sein d’un même document XML des champs provenant de plusieurs tables, il pourrait se produire des conflits entre des champs portant le même nom dans des tables différentes. Nous passons ici d’un nom local “ID« par exemple à un nom global “Table1.ID« qui ne peut être confondu avec un autre nom global possédant un nom local identique, “Table2.ID« par exemple. Une solution plus canonique par rapport à XML consisterait à utiliser des espaces de noms différents pour chacune des tables.

Cette routine n’est pas optimisée. Il serait plus efficace d’analyser une fois pour toutes la structure de la table, et construire un tableau en mémoire contenant les éléments nécessaires pour la génération de la structure XML correspondante et d’utiliser ce tableau pour chaque enregistrement. Ici, l’analyse de la table est répétée pour chaque enregistrement.

Méthode DOM_set_ElementWithValue

C’est la méthode qui se charge de créer un élément simple et sa valeur en un seul appel.

1. ` ----------------------------------------------------

2. ` Nom utilisateur (OS) : christophe Keromen

3. ` Date et heure : 30/06/04, 18:00:36

4. ` ----------------------------------------------------

5. ` Methode : DOM_set_ElementWithValue

6. ` Description

7. ` écrit un élément avec sa valeur

8. `

9. ` Parametres

10. `$1:TEXTE:Ref Element Parent

11. `$2:TEXTE:Nom element à créer

12. `$3:TEXTE:Valeur element à créer

13. `$0:TEXTE:Ref Element créé

14. ` ----------------------------------------------------

16. C_TEXTE($1)

17. C_TEXTE($_vt_RefParent)

18. $_vt_RefParent:=$1

20. C_TEXTE($2)

21. C_TEXTE($_vt_NomElement)

22. $_vt_NomElement:=$2

24. C_TEXTE($3)

25. C_TEXTE($_vt_ValeurElement)

26. $_vt_ValeurElement:=$3

28. C_TEXTE($0)

29. C_TEXTE($_vt_RefElement)

30. $_vt_RefElement:=""

31. $_vt_RefElement:=DOM Creer element XML($_vt_RefParent;$_vt_NomElement)

33. DOM ECRIRE VALEUR ELEMENT XML($_vt_RefElement;$_vt_ValeurElement)

35. $0:=$_vt_RefElement

IV - Conclusion

Cette note technique vous a présenté deux exemples d’application des nouvelles commandes de génération XML par DOM dans 4D 2004. Il est maintenant facile de publier vers l’extérieur vos données sous une forme standardisée même si l’automatisation de nombreuses tâches par 4D ne dispense pas d’un minimum de connaissance des règles XML.

Nous verrons dans la deuxième partie de cette note qu’il existe d’autres moyens de produire du XML dans la version 2004 de 4D.

V - Base exemple

Téléchargez la base exemple.