PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2024 → Parcours d'un XML et comportemens incohérents sur XMLTrouve, XMLEnDehors et XMLRetourPosition
Parcours d'un XML et comportemens incohérents sur XMLTrouve, XMLEnDehors et XMLRetourPosition
Débuté par VincentRG, 09 juil. 2020 17:23 - Aucune réponse
Membre enregistré
12 messages
Posté le 09 juillet 2020 - 17:23
Bonjour,

Je suis sur un projet dont la base de code existe déjà, et qui comprend pas mal de parcours de fichiers XML. Ces parcours sont effectués avec les fonctions XML...(). Les variables xmlDocument, xmlNoeud, etc ne sont pas utilisées.
Cherchant à améliorer un peu les algorithmes, j'ai fait quelques tests sur ces fonctions pour comprendre leur fonctionnement (la doc est assez évasive).
J'ai noté plusieurs incohérences, que je vous livre un peu sous la forme d'un test unitaire:

sSourceXml est une chaîne = [
   <?xml version="1.0" encoding="UTF8"?>
   <LISTE>
      <PRODUIT>
         <IDProduit>Produit1</IDProduit>
         <IDProduit>Produit2</IDProduit>
      </PRODUIT>
   </LISTE>
   ]

sNomDocXml est une chaîne = "DocXml"
bRes est un booléen = XMLDocument(sNomDocXml, sSourceXml)
dbgAssertion(bRes = Vrai)

bRetour est un booléen = Faux
// Se positionne sur Liste
bRetour = XMLRacine(sNomDocXml)
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "LISTE")

// Se positionne sur Produit
bRetour = XMLFils(sNomDocXml)
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "PRODUIT")

// se positionne sur le premier id produit
bRetour = XMLFils(sNomDocXml)
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "IDProduit")
dbgAssertion(XMLDonnée(sNomDocXml) = "Produit1")

// se positionne sur le 2e id produit
bRetour = XMLSuivant(sNomDocXml)
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "IDProduit")
dbgAssertion(XMLDonnée(sNomDocXml) = "Produit2")

// sauvegarde la position du 2e id de produit
iPositionProduit2 est un entier = XMLSauvePosition(sNomDocXml)
dbgAssertion(iPositionProduit2 <> -1)

// se positionne sur un noeud inexistant
bRetour = XMLSuivant(sNomDocXml)
dbgAssertion(bRetour = Faux)
dbgAssertion(XMLTrouve(sNomDocXml) = Faux)
dbgAssertion(XMLEnDehors(sNomDocXml) = Vrai)

// sauvegarde la position de ce noeud invalide
iPositionInvalide est un entier = XMLSauvePosition(sNomDocXml)
// aucune info dans la doc sur le comportement de cette fonction
// quand on sauvegarde une position invalide
// seulement que ça retourne -1 en cas d'erreur, ce qui devrait
// être le cas!
//============================
// >>> COMPORTEMENT INCOHERENT
//============================
dbgAssertion(iPositionInvalide <> -1)

// retourne sur le 2e id produit
bRetour = XMLRetourPosition(sNomDocXml, iPositionProduit2, XMLRPConserve)
// XMLRetour retourne faux et XMLEnDehors retourne vrai
// à cause du XMLSuivant qui a échoué, alors qu'on est sur le bon noeud
//============================
// >>> COMPORTEMENT INCOHERENT
//============================
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Faux)
dbgAssertion(XMLEnDehors(sNomDocXml) = Vrai)
dbgAssertion(XMLNomElément(sNomDocXml) = "IDProduit")
dbgAssertion(XMLDonnée(sNomDocXml) = "Produit2")

// on se remet à la racine
bRetour = XMLRacine(sNomDocXml)
// XMLTrouve retourne vrai et XMLEnDehors qui retourne faux
// tout va bien
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "LISTE")

// on se remet sur le 2e id produit
bRetour = XMLRetourPosition(sNomDocXml, iPositionProduit2, XMLRPConserve)
// ce coup-ci XMLTrouve renvoie vrai et XMLEnDehors renvoie faux,
// puisque qu'on s'est mis sur un noeud valide juste avant (racine)
// et non pas parce que le noeud du 2e id de produit est valide
//============================
// >>> COMPORTEMENT INCOHERENT
//============================
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "IDProduit")
dbgAssertion(XMLDonnée(sNomDocXml) = "Produit2")

// supprime le 2e id produit
bRetour = XMLSupprime(sNomDocXml)
// la suppression positionne sur le noeud parent
// XMLTrouve renvoie toujours vrai et XMLEnDehors faux
// mais ces retours sont en fonction de la position valide
// ou non juste avant la suppression (cf test plus bas)
// et non pas parce qu'on se retrouve sur le parent
//============================
// >>> COMPORTEMENT INCOHERENT
//============================
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "PRODUIT")

// retourne sur ce 2e id produit qu'on vient de supprimer.
bRetour = XMLRetourPosition(sNomDocXml, iPositionProduit2, XMLRPConserve)
// la valeur de retour de XMLRetourPosition est à vrai et
// XMLTrouve renvoie vrai et XMLEnDehors renvoie faux,
// alors que ce noeud a été supprimé ! XMLRetourPosition ne
// devrait d'ailleurs pas renvoyer vrai, car on cherche à
// retourner sur un noeud supprimé.
//============================
// >>> COMPORTEMENT INCOHERENT
//============================
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)

// Se positionne à la racine
bRetour = XMLRacine(sNomDocXml)
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "LISTE")

// Se positionne sur Produit
bRetour = XMLFils(sNomDocXml)
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "PRODUIT")

// se positionne sur le premier id produit
bRetour = XMLFils(sNomDocXml)
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Vrai)
dbgAssertion(XMLEnDehors(sNomDocXml) = Faux)
dbgAssertion(XMLNomElément(sNomDocXml) = "IDProduit")
dbgAssertion(XMLDonnée(sNomDocXml) = "Produit1")

// sauvegarde la position du produit 1
iPositionProduit1 est un entier = XMLSauvePosition(sNomDocXml)
dbgAssertion(iPositionProduit1 <> -1)

// se positionne sur suivant, qui n'existe plus
bRetour = XMLSuivant(sNomDocXml)
dbgAssertion(bRetour = Faux)
dbgAssertion(XMLTrouve(sNomDocXml) = Faux)
dbgAssertion(XMLEnDehors(sNomDocXml) = Vrai)

// retourne sur la position de l'id produit 1
bRetour = XMLRetourPosition(sNomDocXml, iPositionProduit1, XMLRPConserve)
// XMLTrouve retourne faux et XMLEnDehors Vrai,
// car on était sur une position invalide juste avant
//============================
// >>> COMPORTEMENT INCOHERENT
//============================
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Faux)
dbgAssertion(XMLEnDehors(sNomDocXml) = Vrai)
dbgAssertion(XMLNomElément(sNomDocXml) = "IDProduit")
dbgAssertion(XMLDonnée(sNomDocXml) = "Produit1")

// supprime le produit 1
bRetour = XMLSupprime(sNomDocXml)
// la suppression positionne sur le noeud parent, donc valide
// mais XMLTrouve retourne faux et XMLEnDehors vrai car
// on était sur un noeud invalide avant la suppression
//============================
// >>> COMPORTEMENT INCOHERENT
//============================
dbgAssertion(bRetour = Vrai)
dbgAssertion(XMLTrouve(sNomDocXml) = Faux)
dbgAssertion(XMLEnDehors(sNomDocXml) = Vrai)
dbgAssertion(XMLNomElément(sNomDocXml) = "PRODUIT")

XMLTermine(sNomDocXml)


Tous les comportements "incohérents" sont indiqués.

Pour les résumer:
- on peut sauvegarder une position invalide dans le XML, sans avoir de retour d'erreur
- on peut faire un XMLRetourPosition (renvoie Vrai) sur un noeud qui a été supprimé
- XMLTrouve et XMLEnDehors ne prennent pas en compte le changement de position suite à un XMLSupprime (qui positionne sur le parent) ou à un XMLRetourPosition

C'est pas très jojo quand même, et ça manque de logique. Y-a-t'il une raison à tout ça?


J'ai fait quelques tests avec les variables xmlDocument, etc pour manipuler les fichiers XML. Ca semble bien fonctionner (malgré 2 ou 3 détails pas très pratique), mais je n'ai pas trouvé comment faire de recherche à la façon de XMLRecherche. Et je ne peux pas malheureusement pas modifier tout le code de parcours dans le projet.