Sujet : Hoa_Xyl vient d'apparaître dans le tronc

Hey smile,

Une bonne nouvelle, Hoa_Xyl vient d'apparaître dans le tronc de Hoa.
Qu'est-ce que ça signifie ? Bah que j'ai passé 3 semaines à me casser les dents à pondre la théorie, que j'ai passé 2 semaines à me casser celles qui restaient pour passer à la pratique avec beaucoup de difficulté. Au final, le principe de XYL est déjà fonctionnel. Il reste beaucoup à faire, c'est évident, mais le plus dur est fait, j'ai le squelette !

XYL sans injection de données : une face XSLT

XYL peut s'utiliser sans injection de données, c'est à dire sans donner provenant de PHP, on écrit notre bazar en brut, comme si on écrivait de l'HTML, du XML, du Docbook peu importe. Dans ce cas, tout fonctionne bien, on est capable de transformer XYL vers ce qu'on veut : HTML, PDF, texte etc. Pour l'instant, j'ai créé deux balises : <page> et <p>, et elles savent se transformer en HTML5. Hyper simple, pas de soucis, c'est juste pour tester le mécanisme.

XYL avec injection de données : ça devient magique …

Je vulgarise le principe de XYL : on a un gros seau de données, des tableaux de tableaux de tableaux dans tous les sens. On le manipule comme on veut, on y ajoute des données etc. XYL va traiter ça en plusieurs phases. Je dirais en fait en 2 phases.
Phase 1 : on lie toutes les données aux éléments. Lier = faire une référence ici, donc légèreté et rapidité. Pas de copie. Et modification des données propagées, donc si ajout, ajout partout. Je ne sais pas si ça vous cause mais j'ai beaucoup galéré à faire ça … Exemple :

% Data bucket
array(
    'main' => array(
        'foo' => 'bar'
    )
)

% Test.xyl
<page value="?main">
  <p value="?foo" />
</page>

% Après rendu HTML5
<!DOCTYPE html>

<html>
<body>
<p>bar</p>
</body>
</html>

Ça peut paraître bidon pour l'instant, mais ça montre que l'ensemble du mécanisme est en place. <p> travaille sur un sous-ensemble de données hérité de son plus proche parent (parent, grand-parent ou n-grand-parent). Je n'explique pas toute la théorie maintenant car je serai sûrement brouillon et je ne veux pas vous affoler. Vous savez, dans ma tête c'est jamais hyper clair, il me faut du temps pour formuler les choses smile.

Phase 2 : maintenant que toutes les données sont liées et qu'on a fini dans ajouter ou d'en modifier, alors on passe au rendu. On choisit son format de sortie et on passe le tout à la moulinette.

Pourquoi est-ce important de lier les données aux éléments ? Imaginer qu'un élément en fin de document veuille ajouter un lien vers un fichier Javascript dans le cas d'un document HTML ? Et bin on sélectionne notre sceau de données, on ajoute le nom du fichier là où il faut et c'est fini. Comme tout est lié avec des références, la donnée sera immédiatement ajoutée sur notre bon élément qui lit la liste des fichiers par exemple (imaginons un élément <head>). Vous me suivez ? Pas vraiment hyper clair mon histoire …

Conclusion

Une petite conclusion allé.
XYL a déjà le mécanisme en place. Le plus dur est fait : répartir les tâches, les objets, le mécanisme, les charges, les performances, bref faire un squelette.
Techniquement ce n'était pas simple, vraiment pas. Hoa_Xml a dû subir quelques modifications pour être plus facilement extensible.

XYL sans données fonctionne comme XSLT, il sait transformer un document XML (XYL en fait, mais on peut créer tous les éléments XML que l'on souhaite) vers n'importe quelle sortie.

XYL avec données est en cours de construction. Encore beauucoup de chemin, mais on a une base très solide, croyez-moi smile.

Pour les curieux, regarder les sources de Framework/Library/Xyl/, vous allez les trouver ridiculement petites, mais incroyablement compliquées …

« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

2

Re : Hoa_Xyl vient d'apparaître dans le tronc

L'idée a l'air sympa.
Cependant, et hormis qu'il s'agisse d'une implémentation spécifique php, je ne vois pas de différence fondamentale par rapport à xslt.
A moins que je ne me trompe. Ton paragraphe "XYL avec injection de données"  reste proche de xslt dans le principe.

Ce que j'ai compris:
Le doc XYL est déclaratif plutôt que impératif/fonctionnel (ce que serait xsl). On le modifie "de l'extérieur" via l'api de Hoa_Xml (du dom-like à ne pas confondre avec doom-like).
Les data buckets sont construits via des merges successifs (l'api des array)
Le tout est lié avec les selecteurs "value" dans le XYL, et donc, comme tu dis, par référence (une sous-branche partage les data par référence).
Un renderer parcours le XYL et "paint" les données selon la nature des elements.

En regardant rapidos le code, voilà ce qu'il m'est passé par la tête (du vrac) :

- Utiliser spl_object_hash et/ou SplObjectStorage plutôt que array_search + un custom store indexé ?
- N'y a-t-il pas des problèmes de merge des data? utiliser array_merge_recursive?
- Beaucoup de références sur éléments d'array. Il doit se produire des séparations (duplications de données) lorsque celles-ci sont manipulées par copie (genre getData()) car elles sont par ailleurs liées par ref.
- Membres static de Hoa_Xml_Element_Basic? 2 instances de documents distincts partageront le même $root?

N'hésite pas à balayer d'un revert de main ce que je viens de dire si je suis hors-sujet big_smile

3

Re : Hoa_Xyl vient d'apparaître dans le tronc

XYL sans données, c'est du XSLT. La suite va être plus surprenante. Le Y de XYL renferme toutes les astuces.

J'ai dit depuis le début que XYL était un mélange de XSLT, XBL et XUL. On a déjà la première étape qui est XSLT (transformation d'un arbre XML vers autre chose). La suite c'est XBL grâce au Y de XYL, le yielding. Ça va permettre de créer des composants « à la volée » et les réutiliser. Pas encore sûr de la syntaxe, mais on aurait un truc du genre (je dévoile une partie de mes secrets hein wink) :

<yield name="article" source="?">
  <section value="?title" />
  <paragraph value="?description" />
</yield>

<article value="?foo/bar/" />

<yield name="articles" source="?*">
  <article value="??" />
  <separator />
</yield>

<articles value="?gna/gna" />

L'idée c'est quoi ? <yield> permettrait de créer un composant qui se fixe une racine virtuelle en fonction des données qu'on lui donne. <article> est appelé en donnant les données ?foo/bar/, et <article> va filtrer (grâce à @source) sa racine, ici ? donc la racine normale (on oublie cette notion pour l'instant). Il faut juste comprendre qu'on sélectionne un sous-ensemble parmi les données qu'on nous donne.
Du coup, pas de problème de vues, de sous-vues ou de truc à la c*n comme ça smile. On a des composants, on les nomme, on les utilise. On aura aussi les composants anonymes et la récursivité (<this />) si le brouillon de ma spéc ne change pas (encore). On aurait moyen aussi d'avoir comme source de données une base SQL par exemple. J'imagine facilement un truc du genre :

<articles value="database://SELECT * FROM book" />

Pareil avec une lecture de fichier :

<articles value="xml://Foobar.xml?/books/book[type=article]" />

Ça ne reste que des suppositions, mais l'idée est celle-ci.

Ensuite on aurait la balise <overlap /> qui permettrait de modifier l'intérieur d'un composant à la volée. Par exemple :

<articles value="…">
  <overlap element="xpath expression">
    <!-- on remplace par autre chose -->
  </overlap>
</articles>

C'est l'idée, mais encore très brouillon.

J'ai encore d'autres trucs mais ça risque de changer pas mal, je ne veux pas tout bousculer smile.

Et enfin, j'ai parlé de XUL, le langage d'interface graphique de Mozilla, qui permet une interopérabilité de l'apparence et du comportement des éléments d'interface sur plusieurs plateformes. Ce sera pareil avec XYL qui aura un comportement adapté à chaque plateforme : gros écran, petit écran, téléphone etc. Et toujours en essayant de mettre en avant l'accessibilité et l'interopérabilité ainsi que les performances. Car XYL devrait gérer toutes les performances : HTTP, ccache etc.

Voilà l'idée smile.


Tu as bien compris le fonctionnement de XYL pour l'instant.
Oui pour SplObjectStorage, je pensais l'utiliser car mon système était un peu rudimendaire, quoi que très rapide. À tester sur d'énormes objets …
Oui j'ai corrigé le array_merge par array_merge_recursive, je l'ai vu après coup wink.
getData() retourne maintenant une référence, plus de copie donc.
Enfin, oui, Hoa_Xml_Element_Basic a une racine static, ce qui permet à tous les éléments — quelque soit leur profondeur — de retrouver leur racine avec selectRoot() smile.

« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

4

Re : Hoa_Xyl vient d'apparaître dans le tronc

OK pour le yielding et les histoires de racines. Je pense que j'ai pigé.
A ce propos, par rapport à ton premier post, je m'étais demandé comment tu pensais gérer les "racines" et leur caractères relatif ou absolu et si tu avais envisagé des short-cuts syntaxiques. Apparemment, tu as songé à ça wink

Juste par rapport à Hoa_Xml_Element_Basic et le $root static: comment vas-tu gérer le cas où deux documents distincts sont manipulés en même temps ? Il va y avoir un clash au niveau des $root.

5

Re : Hoa_Xyl vient d'apparaître dans le tronc

Exact. C'est une erreur de ma part.
Le problème est qu'on ne peut ajouter d'attribut à une classe qui étend SimpleXMLElement. J'ai pensé au static mais j'ai réfléchis trop vite … Honte sur moi. Je vais changer ça.

Merci !

« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

6

Re : Hoa_Xyl vient d'apparaître dans le tronc

lut,

J'ai regardé le code suite à la dernière video.

A mon avis, le point faible du "dispositif" est le data bucket/store.
Faire intervenir et maintenir à la fois des arrays de références sur éléments d'array et les (internal) array pointers risque d'être source d'ennuis! En vrac:

Par exemple, si un merge (addData) se produit ultérieurement au linkData, le store va devoir être reconstruit entièrement car il risque d'être, au mieux dans un état obsolète, au pire complètement corrompu.

Modifier le XYL impose un rebuild complet du store? (modif au runtime via l'api xml)

Avec le foreach, tu as vu que les array pointers peuvent être délicats à manier. Ca risque d'être compliqué de s'assurer qu'on les maitrise en toutes circonstances. Par exemple, 2 renders successifs.

Imaginons 3 sous branches 'b1' ... 'b3' des data:

'b1'
  'b2'
    'b3'

Actuellement les stores construits à partir de 'b3' n'ont pas accès aux data de 'b1' (parce que ces stores sont construits sur la branche intermédiaire 'b2' courante).
Je pense qu'on peut imaginer un mécanisme de "fallback" pour remonter dans la hiérarchie, mais cela illustre en fait cette dernière remarque: modéliser les données sous la forme d'arrays imbriqués risque d'être limitant et surtout fastidieux à écrire/générer. Si le XYL est plutôt déclaratif, une bonne partie du boulot "logique" sera reporté sur la génération des data et leur selection. Est-ce que cela va nécessiter la création d'une nouvelle api? Par analogie, du xpath pour les arrays php...

7

Re : Hoa_Xyl vient d'apparaître dans le tronc

Hey smile,

Le array_merge va peut-être casser les références. Si c'est le cas, je me ferai mon propre merge pour ne pas casser les array pointers et les références. Sachant que les array pointers se mettent en place lors du rendu, et le traitement des données (le liage des données) se sera déjà fait en amont.
En fait, tu donnes des données, tu en ajoutes etc. XYL va faire un premier passage pour voir si des composants veulent modifier/ajouter/supprimer des données. Deuxième passage : le liage des données. Enfin, troisième et dernier passage : le rendu.
Je vais tenter de confondre le premier et le second passage en un seul (merci la récursivité). Ça va être une technique un peu particulière, mais ça s'utilise souvent dans le parcours d'arbre recouvrant de poids minimal. Je ne vais pas m'étaler, les algos sont en ligne j'imagine.

Donc je pense qu'il n'y aura pas de problèmes avec les array pointers, sauf si on les utilise depuis l'extérieur. Va falloir protéger ça.

Je n'ai pas compris quand tu parles de modifier XYL. Je ne touche pas à XYL. On donne un ou plusieurs fichiers, on travaille dessus. Il n'y a pas de modification dynamique de XYL justement, c'est là tout l'enjeu. Quand on a plusieurs données … exemple : pour mon dernier exemple en date, une liste avec plusieurs <li>, on ne créé pas plusieurs éléments <li>, on en a qu'un seul, mais il va consommer une pile de données. Tant qu'il peut consommer, il se paint(). Pas d'opération DOM, c'est là tout l'enjeu. C'est donc beaucoup plus rapide !

Ah, attends, tu parles du store. Bah ma réponse reste la même. On ne touche pas XYL, donc pas le store. Store que je pense d'ailleurs faire remonter dans Hoa_Xml. Et spl_hash_object et SplObjectStorage me donne des résultats étranges. Je vais continuer à explorer mais je pense avoir trouver des comportements étranges (je n'irai pas jusqu'à dire bug).

Je n'utilise plus les foreach, trop d'effet de bords non désirés. En temps normal, ça ne me dérange pas, mais comme je récupère les array pointers à plusieurs endroits, dont hors de l'itération, c'est gênant …

L'écriture des données sera facilité. Pour l'instant j'ai écris les données en brut mais tu verras que je vais les transformer à la volée pour faciliter les entrées.
J'ai choisi les array parce que c'est natif à PHP. Si on a énormément de données, je ne veux pas perdre de temps à le transformer en StdClass, Hoa_StdClass, en Hoa_Tree, en Hoa_Graph ou je ne sais quoi. Ça fonctionne bien comme ça, c'est natif, c'est rapide.

L'idée c'est de faire une bibliothèque aussi, donc avec le moins de dépendances possibles pour pouvoir être réutilisée à part dans un autre projet. Uè, les problématiques sont pas toujours simples wink.

J'ai pensé à faire un xpath sur des array. Ce sera fait. Regarde la valeur des attributs value : value="?main", mais imagine value="?main/foo/", ce serait possible à la fin du projet. Surtout qu'on aura aussi value="database://…" ou ce genre de chose. Les données pourront venir d'un peu partout. Ça va être marrant à gérer big_smile.

« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

8

Re : Hoa_Xyl vient d'apparaître dans le tronc

Prochaine étape, je vais améliorer la forme des dates pour qu'elle soit plus user-friendly. Ce sera facile et rapide.
Ensuite, je vais un peu améliorer le code.
Puis, je m'attaque à la balise <yield>, l'avantage majeur de XYL smile.

« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

9

Re : Hoa_Xyl vient d'apparaître dans le tronc

Hywan a écrit:

Le array_merge va peut-être casser les références. Si c'est le cas, je me ferai mon propre merge pour ne pas casser les array pointers et les références. Sachant que les array pointers se mettent en place lors du rendu, et le traitement des données (le liage des données) se sera déjà fait en amont.

Hywan a écrit:

Donc je pense qu'il n'y aura pas de problèmes avec les array pointers, sauf si on les utilise depuis l'extérieur. Va falloir protéger ça.

J'aurai plutôt pensé conserver les funcs de merge natives mais reporter au dernier moment le mécanisme de liaison. En fait, déclencher cette étape  uniquement lors d'un rendu (et si rien n'a changé depuis un précédent rendu). C'est probablement ce à quoi tu as pensé.
Ceci + les array pointers qu'il faut contrôler finement devra être pris en compte pour l'api utilisateur. Cela fait un certain nombre d'états à maintenir. Si le souhait est que les choses se fassent de manière optimale, l'interface utilisateur devra être "blindée" big_smile


Hywan a écrit:

Je n'ai pas compris quand tu parles de modifier XYL. Je ne touche pas à XYL. On donne un ou plusieurs fichiers, on travaille dessus. Il n'y a pas de modification dynamique de XYL justement, c'est là tout l'enjeu.

Oui, je vois où tu veux en venir. Je me plaçais dans le cas d'un utilisateur souhaitant générer (ou modifier) dynamiquement un doc XYL.

Hywan a écrit:

L'écriture des données sera facilité. Pour l'instant j'ai écris les données en brut mais tu verras que je vais les transformer à la volée pour faciliter les entrées.
J'ai choisi les array parce que c'est natif à PHP. Si on a énormément de données, je ne veux pas perdre de temps à le transformer en StdClass, Hoa_StdClass, en Hoa_Tree, en Hoa_Graph ou je ne sais quoi. Ça fonctionne bien comme ça, c'est natif, c'est rapide.

Oui pour les arrays natifs. La contre partie sera d'implémenter les mécanismes de selections et modifications. Et pour le coup, est-ce ça sera au final plus performant (et plus simple, mieux quoi) que SimpleXML par exemple.

10

Re : Hoa_Xyl vient d'apparaître dans le tronc

Oui pour la première partie de ton message. Je vais cacher le déclenchement du mécanisme. Je ne suis qu'à une étape brouillon pour l'instant wink.

Pour la seconde partie de ton message, il faut comprendre une autre chose. Les données sont construites par l'utilisateur. Il ne devrait pas avoir à manipuler des données très compliquées. Les données vont provenir essentiellement des contrôleurs dans le cas d'une architecture n-tiers (MVC par exemple), et donc l'utilisateur devra les présenter facilement pour les exploiter facilement. C'est le rôle de la couche modèle ou contrôleur. La vue ne devrait pas trop travailler. Je fais un parallèle volontaire avec le MVC car ce sera un cas concrêt d'utilisation. Il y en aura d'autres : je pense écrire la documentation de Hoa avec XYL et la générer en ligne de commande, mais ça peut paraître plus abstrait pour illustrer mon discours wink.

Tes réflexions sont intéressantes et m'évitent de taper bêtement dans des murs. Je devrais plus communiquer sur ce que je fais tiens smile.
Merci smile.

« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »