xml — n_pbt_xml #
← Référence des composants · Sommaire du guide
Écrire un XML élément par élément — ouvertures, attributs, texte, fermetures — avec l'échappement fait pour vous, puis en relire un avec du vrai XPath :
of_load,of_get_value,of_get_attr,of_count. PowerBuilder 10 n'a aucun analyseur XML ; celui-ci s'appuie sur le DOMParser et document.evaluate du moteur WebView2, appelés synchronement.
▶ Le voir en vrai — Application de démonstration, tuile XML : les résultats, le code qui les produit et cette page, côte à côte.
En bref #
Le build est du PowerScript pur (assembler une chaîne ne demande aucun moteur). La lecture ouvre une page cachée à la première requête. Le XPath est la version 1.0, telle que le navigateur l'évalue. Il n'y a qu'un document à la fois : une lecture sur un document bâti le charge d'abord dans la page, il devient le document chargé, et le of_start_element suivant en commence un nouveau. Une lecture est refusée tant qu'un élément du document bâti est encore ouvert (-4, vide ou false, et is_last_error) : fermez d'abord vos éléments — rien n'est perdu. of_xml et of_pretty, qui travaillent sur une copie, restent permis.
Démarrage rapide #
// Local variables
n_pbt_xml lnv_xml
// Create the object once, free it when done
lnv_xml = create n_pbt_xml
// Read : load, then query with XPath
lnv_xml.of_load(/*xml*/ '<order id="4152"><customer>Ada</customer></order>')
IF lnv_xml.of_is_valid() THEN
MessageBox("Customer", lnv_xml.of_get_value(/*xpath*/ "/order/customer")) // Ada
MessageBox("Id", lnv_xml.of_get_attr(/*xpath*/ "/order", /*name*/ "id")) // 4152
END IF
// Build : element by element, escaping done for you
lnv_xml.of_clear()
lnv_xml.of_start_element(/*name*/ "order")
lnv_xml.of_element_attr(/*name*/ "id", /*value*/ "4152")
lnv_xml.of_leaf(/*name*/ "customer", /*text*/ "Ada & Co")
lnv_xml.of_end_element()
// lnv_xml.of_xml() -><order id="4152"><customer>Ada & Co</customer></order>
// Free the object
destroy lnv_xml
Propriétés #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_last_error | string | "" | Pourquoi la dernière lecture a rendu vide, false, 0 ou un code négatif : document mal formé, XPath refusé par le moteur, XPath sans correspondance, rien de chargé, plafond démo, page qui n'a pas répondu. Vide après une lecture réussie. Le builder y écrit aussi quand il refuse un nom d'élément ou d'attribut invalide |
ipo_owner | powerobject | null | L'objet visuel pour lequel cet utilitaire travaille : la licence se vérifie sur sa classe. À poser avant la première lecture ; posé plus tard, il est transmis à la lecture suivante. Nécessaire seulement dans l'application de démonstration ; une clé de développement ou d'exécution débride la lecture sans lui. Non débridée, la lecture est en mode démo — documents de 64 Ko au plus, modifications comprises. La construction n'en a pas besoin : elle est en PowerScript pur |
Construire un document #
| Membre | Rôle |
|---|---|
of_start_element (string as_name) | Ouvre un élément (les éléments s'imbriquent : un tag ouvert est fermé d'abord). Un nom invalide (vide, avec une espace, un caractère interdit, plus d'un :, un : en tête ou en fin) est refusé : is_last_error dit pourquoi, et l'élément est laissé hors du document avec tout ce qu'il contient |
of_element_attr (string as_name, string as_value) | Ajoute un attribut à l'élément ouvert, valeur échappée — sauts de ligne et tabulations compris, pour qu'ils se relisent tels quels (avant tout enfant ou texte). Un nom invalide est refusé (is_last_error) ; le même nom donné deux fois garde UN seul attribut, avec la seconde valeur |
of_element_text (string as_text) | Le contenu texte de l'élément courant, échappé ; les caractères de contrôle que XML interdit sont retirés (un seul rendait tout le document mal formé) |
of_end_element ( ) | Ferme l'élément courant (vide, il est auto-fermant <name/>) |
of_leaf (string as_name, string as_text) | Un élément feuille en un appel — <name>texte</name>, échappé |
of_clear ( ) → long | Vide le document — bâti ou chargé — pour en commencer un autre ; un document chargé quitte aussi la page. Rend 0 |
of_xml ( ) → string | Le document tel quel : ce que vous avez bâti ou chargé (of_load), après toute modification — la sortie unique, à envoyer, stocker ou réécrire. Un document bâti n'a pas besoin de page (tout élément resté ouvert y est fermé) ; un document chargé est sérialisé par le moteur. of_pretty en donne la forme indentée |
Lire un document (XPath) #
| Membre | Rôle |
|---|---|
of_load (string as_xml) → long | Charge un texte XML (analysé par le DOMParser du moteur). Rend 0 si bien formé, -5 si vide, -4 si XML invalide (ou, en mode démo, trop long une fois ses entités développées), -2 si la page cachée n'a pas répondu. Sur un code négatif RIEN ne reste : ni un document chargé avant, ni un document à moitié bâti |
of_is_valid ( ) → boolean | Vrai quand un document bien formé est tenu — chargé par of_load, ou bâti (il est alors chargé dans la page, comme par toute lecture). Faux s'il n'y a rien, ou si le document bâti est mal formé ou a encore un élément ouvert |
of_exists (string as_xpath) → boolean | Vrai quand l'XPath correspond à au moins un nœud. Une expression qui rend une VALEUR (count(//line)) n'est pas un nœud : lisez-la par of_get_value |
of_get_value (string as_xpath) → string | Le contenu texte du PREMIER nœud correspondant. Vide si aucun (is_last_error le dit). Un XPath qui rend une VALEUR la rend en texte : count(//line) → 3, sum(//@qty), boolean(//paid) → true |
of_get_attr (string as_xpath, string as_name) → string | La valeur de l'attribut as_name du premier nœud correspondant. Vide si absent |
of_count (string as_xpath) → long | Combien de nœuds l'XPath sélectionne. 0 si aucun (un compte XPath n'est jamais négatif) ; is_last_error dit quand l'XPath lui-même a été refusé |
of_name (string as_xpath) → string | Le nom de balise du premier nœud correspondant. Vide si aucun |
of_pretty ( ) → string | Le document tel quel — bâti ou chargé, ce que rend of_xml — ré-indenté pour la lecture. Rien n'est perdu : CDATA, commentaires, instructions de traitement et déclaration XML sont gardés, et un élément qui contient du texte s'écrit sur une ligne, tel quel. Vide s'il n'y a rien, ou si un document bâti n'est pas bien formé |
Plusieurs nœuds, et le document #
| Membre | Rôle |
|---|---|
of_get_values (string as_xpath, ref string as_values[]) → long | Le contenu texte de CHAQUE nœud correspondant, dans as_values ; rend le compte. Là où of_get_value ne rend que le premier |
of_get_attrs (string as_xpath, string as_name, ref string as_values[]) → long | La valeur de l'attribut as_name sur CHAQUE nœud correspondant (l'id de chaque ligne) ; rend le compte |
of_get_attr_names (string as_xpath, ref string as_names[]) → long | Les noms de tous les attributs du premier nœud correspondant (énumération) ; rend le compte |
Modifier un document #
Le côté écriture change l'arbre chargé sur place ; of_xml en rend le résultat. Chacune vise le PREMIER nœud correspondant (sauf of_remove, qui les prend tous), rend 0 au succès, -4 si rien ne correspond ou si le changement est refusé (is_last_error dit pourquoi), -5 sur un argument vide, -2 si la page n'a pas répondu.
| Membre | Rôle |
|---|---|
of_set_value (string as_xpath, string as_text) → long | Fixe le texte du premier nœud correspondant (ses enfants sont remplacés) |
of_set_attr (string as_xpath, string as_name, string as_value) → long | Fixe (ou ajoute) un attribut sur le premier nœud correspondant. Un nom préfixé (xsi:type) va dans l'espace de noms de son préfixe à ce nœud (ou lié par of_register_namespace) ; un préfixe lié nulle part est refusé (-4, is_last_error) |
of_remove_attr (string as_xpath, string as_name) → long | Retire un attribut du premier nœud correspondant |
of_add_child (string as_xpath, string as_tag, string as_text) → long | Ajoute un élément enfant <as_tag>as_text</as_tag> sous le premier nœud correspondant (l'enfant hérite de l'espace de noms et du préfixe du parent ; une balise préfixée p:item prend l'espace de noms de son préfixe, ou -4 s'il n'est lié nulle part). -4 aussi quand le nœud ne peut pas avoir d'enfant (un attribut, un texte) ou que la balise n'est pas un nom valide |
of_add_xml (string as_xpath, string as_fragment) → long | Greffe un fragment XML déjà formé (un ou plusieurs éléments frères) sous le premier nœud correspondant — ce que of_add_child ne fait pas, ne prenant qu'une balise et un texte. Le fragment doit être bien formé ; il hérite des espaces de noms en vigueur à sa cible, comme of_add_child (<line> sous <order xmlns='urn:acme'> est dans urn:acme, <s:Item/> sous un s:Body SOAP n'a rien à déclarer) |
of_remove (string as_xpath) → long | Retire TOUS les nœuds correspondants (une ligne, une branche périmée, un attribut). Rend combien ont été réellement retirés (>= 0 ; sur 0, is_last_error dit pourquoi), -4 si rien n'est chargé, -5 sur un XPath vide, -2 si la page n'a pas répondu. L'élément racine reste : of_clear vide un document |
Espaces de noms #
Un XPath préfixé (SOAP, une API d'entreprise) résout tout seul un préfixe que le document déclare (xmlns:s="…", sur n'importe quel élément). ⚠️ Le piège le plus fréquent : l'espace de noms PAR DÉFAUT. <order xmlns="urn:acme"><customer>… n'a aucun préfixe, et pourtant /order/customer ne correspond à RIEN : XPath 1.0 n'a pas d'espace de noms par défaut. Liez un préfixe de votre choix par of_register_namespace("a", "urn:acme") et écrivez /a:order/a:customer. of_clear_namespaces oublie les liaisons. Il n'y a pas de XSLT : Chromium le retire du moteur (transformez côté serveur ou en PowerScript). Il n'y a pas de validation par schéma XSD : le moteur n'en a pas.
| Membre | Rôle |
|---|---|
of_register_namespace (string as_prefix, string as_uri) → long | Lie un préfixe à l'URI de son espace de noms, pour qu'un XPath préfixé résolve. Rend 0, -5 sur un préfixe ou une URI vide, -2 si la page n'a pas répondu. Les liaisons durent jusqu'à of_clear_namespaces ou of_reset |
of_clear_namespaces ( ) → long | Oublie tous les préfixes enregistrés : un préfixe que le document ne déclare pas ne correspond plus à rien tant qu'il n'est pas relié. Rend 0, -2 si la page n'a pas répondu |
// A SOAP response : the prefix declared by the document resolves on its own
lnv_xml.of_load(/*xml*/ ls_soap)
ls_ok = lnv_xml.of_get_value(/*xpath*/ "//s:Body/result/status")
// A DEFAULT namespace (xmlns="urn:acme") : bind a prefix of your choice
lnv_xml.of_load(/*xml*/ '<order xmlns="urn:acme"><customer>Ada</customer></order>')
lnv_xml.of_register_namespace(/*prefix*/ "a", /*uri*/ "urn:acme")
ls_name = lnv_xml.of_get_value(/*xpath*/ "/a:order/a:customer") // Ada
// Mutate, then read the result back
lnv_xml.of_set_value(/*xpath*/ "/a:order/a:customer", /*text*/ "Grace")
lnv_xml.of_add_child(/*xpath*/ "/a:order", /*tag*/ "total", /*text*/ "690.50")
// Graft a whole fragment at once (of_add_child adds only one tag)
lnv_xml.of_add_xml(/*xpath*/ "/a:order", /*fragment*/ '<lines xmlns="urn:acme"><line sku="1">A</line><line sku="2">B</line></lines>')
ls_out = lnv_xml.of_xml()
La page cachée #
| Membre | Rôle |
|---|---|
of_open ( ) → long | Crée la page cachée (côté lecture). Facultatif — la première lecture le fait. Rend le handle (> 0) ou -2 si elle n'a pas pu être créée (is_last_error dit pourquoi) |
of_is_open ( ) → boolean | Vrai dès que la page cachée existe |
of_close ( ) | Libère la page cachée. Le build continue sans elle, et un document chargé n'est pas perdu : il est gardé en texte, et la lecture suivante le recharge. Fait pour vous à la destruction |
of_reset ( ) | Retour aux valeurs par défaut : le builder est vidé, l'état de lecture effacé |
Portée. Le XML se lit par le moteur (DOMParser, XPath) :
n_pbt_xmlouvre une page cachée à la première lecture, contrairement à json, qui s'analyse en PowerScript pur. Pour afficher un XML en arbre repliable, voyez xmltree.