xmltree — u_pbt_xmltree #
← Référence des composants · Sommaire du guide
xmltree affiche une valeur XML comme un arbre repliable, coloré : un écran de configuration, une réponse d'API, un débogage d'intégration. Vous posez le texte XML dans
is_xml, le composant le montre ; un clic sur un nœud rapporte son chemin (ue_node_clicked), un XML invalide lèveue_error. Il ne modifie rien : c'est un VISUALISEUR.
▶ Le voir en vrai — Application de démonstration, tuile XML tree, avec le code et cette page côte à côte.
En bref #
| Userobject | u_pbt_xmltree |
| Entrée | Le texte XML, dans is_xml (une chaîne) |
| Plier / déplier | Chaque élément par son marqueur + / − dans la marge des numéros, par son chemin (of_expand_path, of_collapse_path), ou tout d'un coup (of_expand_all, of_collapse_all) |
| Retour | Un clic sur un nœud donne son chemin (ue_node_clicked), un XPath que n_pbt_xml lit tel quel : /order/lines/line[2], /order/@id pour un attribut, /order/comment()[1] pour un commentaire — chaque ligne a le sien ; un XML invalide lève ue_error et montre la source, la ligne fautive marquée |
| Fidélité | Chaque nœud à sa place, dans l'ordre du document : le texte entre deux enfants, les sections CDATA, les commentaires, les instructions de traitement, la déclaration XML |
Démarrage rapide #
// Show an XML response as a tree
uo_xml.is_xml = inv_rest.of_response_text()
// Fold everything, then let the user open what interests them
uo_xml.of_collapse_all()
// ue_node_clicked : the path of the node clicked, an XPath ("/order/lines/line[2]",
// "/order/@id" for an attribute) -> n_pbt_xml.of_get_value(as_path) reads its value
Propriétés #
| Propriété | Type | Défaut | Description |
|---|---|---|---|
is_xml | string | "" | Le texte XML à montrer, lu et affiché comme un arbre : chaque nœud à sa place. Vide efface l'arbre, sans erreur ; un XML invalide lève ue_error et montre la source autour de la ligne fautive. Se relit tel qu'il a été posé, un texte invalide compris. Un nouveau document repart sans sélection, tout ouvert : of_get_layout avant et of_set_layout après gardent ce que l'utilisateur avait ouvert |
ib_wrap | boolean | true | Les lignes longues reviennent à la ligne (true, par défaut) ou restent sur une ligne avec une barre horizontale (false) — un rendu d'éditeur de code |
ib_search_enabled | boolean | true | Ctrl+F dans l'arbre ouvre une zone de recherche — la même recherche que of_search : taper surligne, Entrée ou F3 suivant, Maj+Entrée ou Maj+F3 précédent, Échap ferme. false laisse le raccourci à une application qui cherche depuis sa propre zone. La zone porte trois bascules avant le compteur, Aa (ib_find_match_case), ab (ib_find_whole_word) et & (ib_find_decoded) ; changer une option relance la recherche en cours depuis sa première occurrence |
ib_find_match_case | boolean | false | Option de recherche : ne trouve que le texte de même casse. La bascule Aa de la zone de recherche (Ctrl+F) est le même interrupteur ; vaut pour of_search et pour ce que l'utilisateur tape. Lue en direct ; of_reset la remet à false |
ib_find_whole_word | boolean | false | Option de recherche : ne trouve le texte que comme mot entier (une lettre, un chiffre ou un _ à côté fait partie du mot : id n'est trouvé ni dans user_id ni dans ids). La bascule ab de la zone de recherche est le même interrupteur. Lue en direct ; of_reset la remet à false |
ib_find_decoded | boolean | false | Option de recherche : cherche dans les VALEURS décodées — un texte et une valeur d'attribut lus comme n_pbt_xml les lit (Durand & Co trouve Durand & Co, x < y trouve x < y) ; le surlignage couvre l'échappement entier. false cherche le texte tel qu'il est affiché. La bascule & de la zone de recherche est le même interrupteur. Lue en direct ; of_reset la remet à false |
is_theme_style | string | "" | Style visuel du composant (constantes THEME_STYLE_*) ; vide = celui de l'application, suivi à chaque changement |
is_theme_mode | string | "" | Variante claire ou sombre (constantes THEME_MODE_*) ; vide = celle de l'application, suivie à chaque changement |
il_theme_accent | long | -1 | Couleur d'accent de ce composant (-1 = l'accent de l'application, ou celui du thème) |
is_tooltip | string | "" | Info-bulle simple affichée au survol du composant |
is_super_tooltip_title | string | "" | Titre de l'info-bulle enrichie (prend le pas sur is_tooltip) |
is_super_tooltip_text | string | "" | Texte de l'info-bulle enrichie (balisage riche accepté) |
is_super_tooltip_image | string | "" | Image de l'info-bulle enrichie |
Méthodes #
| Méthode | Description |
|---|---|
of_expand_all ( ) → long | Déplie tous les éléments. Aucun ue_node_toggled : aucun geste n'ouvre l'arbre entier d'un coup. Rend 0, -2 si le composant n'est pas créé |
of_collapse_all ( ) → long | Replie tous les éléments imbriqués (la racine reste visible). Une sélection cachée par un pli passe sur l'élément replié, et ue_selection_changed le dit. Aucun ue_node_toggled : aucun geste ne replie l'arbre entier d'un coup. Rend 0, -2 si le composant n'est pas créé |
of_clear ( ) → long | Vide l'arbre (comme is_xml = "") ; ib_wrap, ib_search_enabled, ib_find_match_case et ib_find_whole_word gardent leur valeur (c'est of_reset qui remet chaque propriété). Rend 0, -2 si le composant n'est pas créé |
of_expand_to_level ( long al_level ) → long | Montre l'arbre jusqu'à al_level : les éléments à cette profondeur ou plus se replient (1 = les enfants directs de la racine, 0 replie la racine). Aucun ue_node_toggled ; une sélection qu'il déplace sur un élément replié lève ue_selection_changed. Rend 0, -2 si le composant n'est pas créé |
of_expand_path ( string as_path ) → long | Ouvre UN élément par son chemin — n'importe quel XPath, comme of_select_path — et les éléments au-dessus de lui pour qu'il se voie. Comme son marqueur +, lève ue_node_toggled pour l'élément et pour chaque élément replié au-dessus ouvert en chemin (rien pour un élément déjà ouvert). Rend 0, -5 si aucun élément à enfants ne correspond, -2 si le composant n'est pas créé |
of_collapse_path ( string as_path ) → long | Replie UN élément par son chemin (n'importe quel XPath). Comme son marqueur −, lève ue_node_toggled si l'élément était ouvert, et ue_selection_changed quand la sélection doit passer sur lui. Rend 0, -5 si aucun élément à enfants ne correspond, -2 si le composant n'est pas créé |
of_is_expanded ( string as_path ) → boolean | true si l'élément de ce chemin (n'importe quel XPath) est ouvert, lu EN DIRECT ; false s'il est replié, et pour un nœud sans enfants ou un chemin qui ne trouve rien. De quoi enregistrer ce que l'utilisateur a ouvert et le rétablir |
of_get_layout ( ) → string | La disposition de l'arbre, lue EN DIRECT, en un texte JSON à enregistrer : les éléments repliés (collapsed, ou expanded quand cette liste est plus courte — tout élément qu'elle ne nomme pas est alors replié), le chemin sélectionné (selected, null sans sélection) et la ligne en haut de la vue (top, un chemin, jamais des pixels). À rendre à of_set_layout, après un nouveau document aussi |
of_set_layout ( string as_layout_json ) → long | Rend à l'arbre une disposition donnée par of_get_layout : les plis (un chemin que le document n'a plus est ignoré, un élément nouveau garde son défaut), la sélection (ue_selection_changed, comme of_select_path) et la ligne du haut. ue_layout_changed suit une fois si les plis ont changé. Rend 0, -5 si le texte n'est pas un objet JSON, -2 si le composant n'est pas créé |
of_search ( string as_query ) → long | Surligne chaque occurrence (sans casse par défaut — voir ib_find_match_case —, en mot entier avec ib_find_whole_word) et saute à la première ; seuls les éléments qui cachent l'occurrence COURANTE s'ouvrent, et of_clear_search les replie. ue_search_result dit combien. La recherche porte sur le texte tel qu'il est AFFICHÉ : dans un texte, Durand & Co s'écrit Durand & Co et se cherche ainsi (une section CDATA le montre tel quel) — avec ib_find_decoded, sur les valeurs décodées, où Durand & Co trouve les deux. Une requête vide est of_clear_search ; une recherche met fin à un of_find_xpath. La zone de recherche s'ouvre avec la requête dedans et le focus dessus (la même que Ctrl+F) : Entrée passe à la suivante ; avec ib_search_enabled à false, l'arbre surligne seulement. Rend 0, ou un code négatif |
of_search_next ( ) → long | Passe à la correspondance SUIVANTE (revient à la première après la dernière) ; pendant un of_find_xpath, au nœud suivant, qui est sélectionné. ue_search_result donne la nouvelle position. Rend 0, ou un code négatif |
of_search_prev ( ) → long | Passe à la correspondance PRÉCÉDENTE (revient à la dernière avant la première) ; pendant un of_find_xpath, au nœud précédent, qui est sélectionné. ue_search_result donne la nouvelle position. Rend 0, ou un code négatif |
of_clear_search ( ) → long | Efface la recherche, ou l'of_find_xpath : plus de surlignage ni de correspondance courante (of_match_count rend 0), la zone de recherche se vide et se ferme, et les éléments que la recherche avait ouverts se replient comme avant elle. Rend 0, ou un code négatif |
of_find_xpath ( string as_xpath ) → long | Surligne CHAQUE nœud de l'arbre qu'un XPath désigne (//line, //line[@qty > 1], //@sku) et sélectionne le premier ; of_search_next / of_search_prev (et F3) les parcourent, chacun sélectionné, et ue_search_result les compte. Une recherche de texte, of_clear_search, Ctrl+F ou un nouveau document y mettent fin. Rend le nombre de nœuds trouvés (0 si aucun), -5 si le texte n'est pas un XPath de nœuds (une erreur de syntaxe, un nombre comme count(…), un préfixe inconnu), -2 si le composant n'est pas créé. Un texte vide vaut of_clear_search |
of_select_path ( string as_path ) → long | Sélectionne et défile jusqu'au nœud à as_path ; comme le clavier, lève ue_selection_changed (rien si le nœud est déjà sélectionné) ; les éléments repliés qui le cachent s'ouvrent. as_path est N'IMPORTE QUEL XPath 1.0 qui désigne un nœud de l'arbre : un chemin tel que l'arbre le donne (/order/@id), //line[@sku='A'], /order/lines/line[1], un autre préfixe lié au même espace de noms ; le premier nœud trouvé que l'arbre MONTRE est sélectionné (un blanc de mise en page n'a pas de ligne), et of_selected_path rend ensuite le chemin de l'arbre. Rend 0, -5 si aucun nœud de l'arbre ne correspond (la sélection ne bouge pas), -2 si le composant n'est pas créé |
of_selected_path ( ) → string | Le chemin du nœud sélectionné, lu EN DIRECT : un chemin XPath 1.0 à donner tel quel à n_pbt_xml.of_get_value sur le même document. CHAQUE ligne a le sien : /order/lines/line[2] quand un nom se répète, /order/@id pour un attribut, /p/text()[2] pour un texte, /order/comment()[1], /order/processing-instruction('x')[1], /comment()[1] avant la racine. Un élément d'un espace de noms PAR DÉFAUT s'écrit *[local-name()='Body'] — un nom nu ne trouve rien en XPath ; un nom préfixé (soap:Body) est gardé quand son préfixe désigne le même espace de noms, sinon le pas nomme aussi l'espace (namespace-uri()). Une balise fermante donne son élément. Vide si rien n'est sélectionné, et pour la déclaration XML ou le DOCTYPE (qui ne sont pas des nœuds) |
of_selected_value ( ) → string | La valeur de la sélection, lue EN DIRECT et décodée — ce que n_pbt_xml.of_get_value lit à of_selected_path : la valeur d'un attribut, le texte d'un élément FEUILLE (CDATA compris, blancs gardés), le texte d'une ligne de texte, d'un commentaire ou d'une instruction de traitement ; un élément montré <x/> qui ne contient que des retours à la ligne les rend, comme n_pbt_xml. Vide pour un élément qui a des enfants, ou sans sélection |
of_selected_xml ( ) → string | Le XML du nœud sélectionné, lu EN DIRECT : un élément avec tout ce qu'il contient, un attribut sous la forme name="value", un texte échappé, un commentaire, un CDATA ou une instruction de traitement tels qu'écrits — ce qu'on copie d'un éditeur XML. Vide sans sélection |
of_selected_kind ( ) → string | Ce qu'est le nœud sélectionné, lu EN DIRECT : KIND_ELEMENT, KIND_ATTRIBUTE, KIND_TEXT, KIND_CDATA, KIND_COMMENT, KIND_PI (une instruction de traitement), KIND_DECLARATION (la déclaration XML) ou KIND_DOCTYPE. Vide sans sélection |
of_selected_name ( ) → string | Le nom qualifié du nœud sélectionné, lu EN DIRECT : un élément ou un attribut tel qu'écrit (soap:Body, id), la cible d'une instruction de traitement. Vide pour un texte, un CDATA, un commentaire, la déclaration, le DOCTYPE, ou sans sélection |
of_selected_namespace ( ) → string | L'URI de l'espace de noms de l'élément ou de l'attribut sélectionné, lu EN DIRECT (http://schemas.xmlsoap.org/soap/envelope/). Vide s'il n'en a pas (un attribut sans préfixe n'en a pas), pour tout autre nœud, ou sans sélection |
of_copy ( ) → long | Met le XML de la sélection dans le presse-papiers, comme Ctrl+C dans l'arbre (le texte de of_selected_xml) ; un morceau de texte surligné à la souris est copié tel quel par Ctrl+C. Rend 0, -4 si rien n'est sélectionné, -2 si le composant n'est pas créé |
of_copy_path ( ) → long | Met le CHEMIN du nœud sélectionné dans le presse-papiers (/order/lines/line[2], /order/@id), un XPath prêt pour n_pbt_xml. Rend 0, -4 si rien n'est sélectionné ou si le nœud n'a pas de chemin (la déclaration XML, le DOCTYPE), -2 si le composant n'est pas créé |
of_match_count ( ) → long | Rend le nombre d'OCCURRENCES de la recherche courante (deux sur une ligne comptent deux), lu EN DIRECT — le 12 d'une barre d'état 3 / 12. 0 sans recherche |
of_match_index ( ) → long | Rend la position (1-basée) de la correspondance courante, lue EN DIRECT — le 3 d'une barre d'état 3 / 12. 0 sans correspondance |
Événements #
| Événement | Quand |
|---|---|
ue_node_clicked (string as_path) | L'utilisateur a cliqué un nœud, ou pressé Entrée sur une feuille sélectionnée : son chemin XPath (/order/lines/line[2]) ; un attribut, un texte, un commentaire ou une instruction de traitement donnent le leur (/order/@id, /order/comment()[1]), une balise fermante son élément. À donner à n_pbt_xml.of_get_value sur le même document |
ue_node_toggled (string as_path, boolean ab_expanded) | Un élément a été replié (ab_expanded à false) ou ouvert (true) : par l'utilisateur (son marqueur + / −, les flèches, Entrée ou Espace) ou par of_expand_path / of_collapse_path. of_expand_all, of_collapse_all et of_expand_to_level ne le lèvent pas : aucun geste ne replie l'arbre entier |
ue_node_rclicked (string as_path, long al_x, long al_y) | Clic droit sur un nœud, ou touche Menu (Maj+F10) dans l'arbre : le nœud est d'abord sélectionné (ue_selection_changed si la sélection a bougé), as_path est son chemin, al_x / al_y le point à l'ÉCRAN, en pixels. Ouvrez-y votre propre menu (un u_pbt_contextmenu) : l'arbre n'en a pas |
ue_layout_changed (string as_layout_json) | Les plis ont changé — un geste, un ordre de votre code (of_collapse_all compris), un nouveau document, of_set_layout : as_layout_json est la disposition entière, comme of_get_layout la donne, à enregistrer. Un changement de sélection ou de défilement ne le lève pas |
ue_selection_changed (string as_path) | La sélection a bougé sans clic, par l'utilisateur ou par votre code : flèches, Début/Fin, Pg préc/Pg suiv, of_select_path, un pas d'of_find_xpath, ou un pli qui cache la ligne sélectionnée (la sélection passe sur l'élément replié). Levé seulement quand la sélection change vraiment ; un nouveau document repart sans sélection et ne le lève pas — un clic souris rapporte ue_node_clicked |
ue_search_result (long al_count, long al_index) | Une recherche a démarré ou avancé : al_count occurrences en tout, la courante est al_index (1-basé, 0 si aucune) — de quoi afficher « 3 / 12 » ; of_find_xpath le lève aussi (al_count = les nœuds trouvés), et (0, 0) quand il prend fin ; quand une recherche se ferme (Échap dans la zone, of_clear_search, of_reset, ib_search_enabled = false), (0, 0) une fois |
ue_error (string as_message) | Le texte de is_xml n'est pas un XML valide : le message dit où, dans la langue d'affichage (« XML invalide : ligne 3, colonne 16 (…) », le détail du moteur entre parenthèses), et l'arbre montre la source autour de cette ligne, la ligne fautive marquée. Levé aussi quand le document est trop grand pour être affiché |
Exemple #
Explorer la réponse d'une API #
// Show the XML an API answered, or nothing if the call failed
if inv_rest.of_get(/*url*/ "https://api.example.com/orders/4152") = 200 then
uo_xml.is_xml = inv_rest.of_response_text()
uo_xml.of_collapse_all() // the reader opens what interests them
else
uo_xml.of_clear()
end if
Lire la valeur d'un nœud cliqué #
// Instance variable of the window : the answer, loaded ONCE by n_pbt_xml
n_pbt_xml inv_xml
// open event of the window : n_pbt_xml is created once, owned by the window
inv_xml = create n_pbt_xml
inv_xml.ipo_owner = this
// When the answer arrives : the tree shows it, n_pbt_xml loads the same text once
uo_xml.is_xml = inv_rest.of_response_text()
inv_xml.of_load(/*xml*/ inv_rest.of_response_text())
// ue_node_clicked of uo_xml : the value at the clicked path, nothing loaded again
st_value.text = inv_xml.of_get_value(/*xpath*/ as_path)
// or, without a second parser : the value of the selection, decoded
st_value.text = uo_xml.of_selected_value()
Chercher des mots entiers, casse comprise #
// Whole words only, with the same case : "id" is not found inside "user_id"
uo_xml.ib_find_match_case = true
uo_xml.ib_find_whole_word = true
uo_xml.of_search(/*query*/ "id")
Garder les plis quand la réponse est rafraîchie #
// Local variables
string ls_layout
// The folds, the selected node and the line at the top, kept before the new text
ls_layout = uo_xml.of_get_layout()
uo_xml.is_xml = inv_rest.of_response_text()
// The same elements fold again ; a path the new text no longer has is ignored
uo_xml.of_set_layout(/*layout_json*/ ls_layout)
Trouver chaque nœud d'un XPath #
// Local variables
long ll_found
// Every order line of more than one item : highlighted, the first one selected
ll_found = uo_xml.of_find_xpath(/*xpath*/ "//line[@qty > 1]")
// A Next button walks them, like F3 ; ue_search_result feeds a "2 / 5" status line
if ll_found > 1 then uo_xml.of_search_next()
// What is selected, without a second parser
st_kind.text = uo_xml.of_selected_kind() + " " + uo_xml.of_selected_name()
Un menu sur un nœud #
// ue_node_rclicked of uo_xml : the node is selected, open YOUR menu at that point of the screen
uo_menu.of_show(/*x*/ al_x, /*y*/ al_y)
// ue_item_selected of uo_menu : copy the XML of the node, or its path for n_pbt_xml
choose case as_keys
case "copy"
uo_xml.of_copy()
case "copypath"
uo_xml.of_copy_path()
end choose
Bonnes pratiques #
- C'est un visualiseur, pas un éditeur : il montre le XML, il ne le change pas. Pour lire une valeur, donnez le chemin de
ue_node_clickedàn_pbt_xml.of_get_valuesur le même texte, ou lisezof_selected_value. - Un gros XML reste fluide : seules les lignes à l'écran sont dessinées, un export de plusieurs milliers de lignes se parcourt au clavier sans attente.
of_collapse_alld'abord reste le plus lisible. - Un XML invalide ne casse rien :
ue_errorle dit (avec la ligne et la colonne de la faute, dans la langue d'affichage), et l'arbre montre la source autour de la ligne fautive. C'est le retour à montrer, pas un plantage. - Un espace de noms par défaut (
xmlns="urn:…", une réponse SOAP) : le chemin s'écrit*[local-name()='Body'], la seule forme qu'un XPath sans préfixe enregistré sait lire ; un préfixe redéclaré avec un autre URI, ou un frère de même nom dans un autre espace, s'écrit*[local-name()='x' and namespace-uri()='urn:…'].@xml:langse lit tel quel. Une déclarationxmlnss'affiche mais n'a pas de chemin : XPath ne la voit pas comme un attribut. - Ce qui s'affiche est du XML : une valeur d'attribut garde ses guillemets et ses retours à la ligne codés (
), un texte ses&et<, ses blancs significatifs ; seuls les retours à la ligne de mise en page autour d'un texte disparaissent. Un blanc entre deux enfants (l'espace de<b>x</b> <i>y</i>) a sa propre ligne, montrée ␠ : il fait partie du texte. - Au clavier : les flèches passent de ligne en ligne, Flèche droite parcourt les attributs d'une balise avant de descendre, Page bas avance d'un écran (une section CDATA de trois cents lignes compte pour sa hauteur), Ctrl+C copie le XML de la sélection.
- De droite à gauche : un document XML est un texte de gauche à droite, l'arbre le reste dans une application en RTL (seule la zone de recherche suit le sens de l'application).
Hérité du socle commun #
Ces membres existent sur tous les composants visuels — ils ne sont pas propres à celui-ci. Ils sont détaillés une seule fois, dans les chapitres transverses ; cette table dit seulement où les lire.
| Membres | Rôle | Détaillé dans |
|---|---|---|
of_reset | Remettre le composant à zéro | 3.6 Remettre un composant à zéro : of_reset() |
of_register_shortcut · of_clear_shortcuts | Raccourcis clavier du composant | 3.5 Les raccourcis clavier |
of_is_created · of_is_ready · of_get_last_error | S'il est né, s'il est prêt, ce qui a échoué | 3.7 Diagnostic |
of_save_as_png · of_save_as_jpg | Exporter le rendu en image | 3.8 Exporter le rendu en image |
of_set_redraw | Grouper les modifications en un seul repaint | 3.10 Bonnes pratiques |
of_preload_icons | Icônes affichées sans délai | Affichage instantané : of_icon |
of_set_translation | Traduire un libellé du composant | 5.2 Adapter un libellé : of_set_translation |
of_focus_webview | Donner le focus au composant | 6.4 Clavier et focus |
of_print · of_print_to_pdf | Imprimer, ou écrire un PDF | 6.9 Imprimer |
of_set_property · of_get_property · of_component_name | Piloter une propriété par son nom | 3.1 Le moteur de propriétés |
is_accessible_name · is_accessible_description | Le nom et la description que dit un lecteur d'écran | 3.4 Propriétés et events optionnels |