Bonjour,
Comme promis, quelques éléments de réflexion sur votre projet...
Le jeudi 13 octobre 2005 à 17:07 +0200, Matthieu Ricaud a écrit :
> Bonjour,
>
> Dans le cadre d'un projet d'éditeur xml "générique" se basant sur un
> schéma relaxNG, j'ai besoin de déterminer pour chaque élément, quels
> élément-fils on peut ajouter.
>
> Ce "calcul" dépend à la fois du schéma relaxNG et du document qui est
> édité (nombre d'occurence des éléments).
>
> Le Schéma RelaxNG est restreint aux éléments suivants : start,
> element, attribute, text, group, interleave, oneOrMore, et ZeroOrMore.
> par exemple :
>
> <start name="A" >
> <group>
> <interleave>
> <zeroOrMore>
> <element name="B">
> <attribute name="id"/>
> </element>
> </zeroOrMore>
> <oneOrMore>
> <element name="C">
> <attribute name="id"/>
> </element>
> </oneOrMore>
> </interleave>
> </group>
> <element name="Z" >
> <attribute name="id"/>
> </element>
> </start>
Tout d'abord sur ce sous ensemble du langage RELAX NG.
Une première remarque de forme : <start name="A" > devrait être remplacé
par <start><element name="A">...
Vous excluez essentiellement le pattern choice, le pattern optional
(pourquoi?) les classes de noms, les patterns nommés (define/ref) et
tout ce qui concerne les types de données (et listes).
Le fait d'exclure les patterns nommés conduit à exclure les modèles de
contenus récursifs (tels que l'élément (X)HTML div qui peut contenir un
autre élément div).
C'est pour cette raison que la simplification décrite dans la
spécification RELAX NG impose au contraire d'utiliser des patterns
nommés mais de manière très encadrée (chaque élément doit être définit
dans un pattern nommé mais chaque pattern nommé ne doit contenir qu'une
seule définition d'élément et toute autre utilisation de pattern nommé
est interdite).
Cela reviendrait à remplacer voter grammaire actuelle qui peut
s'écrire :
start =
element a {
(element B {
attribute id { text }
}*
& element C {
attribute id { text }
}+),
element Z {
attribute id { text }
}
}
en :
start = A
A = element A { (B* & C+), Z }
B =
element B {
attribute id { text }
}
C =
element C {
attribute id { text }
}
Z =
element Z {
attribute id { text }
}
ou si vous préférez en syntaxe XML :
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<start>
<ref name="A"/>
</start>
<define name="A">
<element name="A">
<interleave>
<zeroOrMore>
<ref name="B"/>
</zeroOrMore>
<oneOrMore>
<ref name="C"/>
</oneOrMore>
</interleave>
<ref name="Z"/>
</element>
</define>
<define name="B">
<element name="B">
<attribute name="id"/>
</element>
</define>
<define name="C">
<element name="C">
<attribute name="id"/>
</element>
</define>
<define name="Z">
<element name="Z">
<attribute name="id"/>
</element>
</define>
</grammar>
Vous perdez le fait d'avoir une structure de schéma qui est directement
celle su document XML mais vous gagnez le support des contenus récursifs
et je ne pense pas que ce soit beaucoup plus difficile à traiter en
XSLT.
Autre remarque, vous conservez la possibilité de mélanger des patterns
group et interleave.
Dans votre exemple, cela n'a pas beaucoup d'incidence mais vous semblez
autoriser des contenus du type (B1, C1) & (B2, C2) ou en XML :
<interleave>
<group>
<ref name="B1"/>
<ref name="C1"/>
</group>
<group>
<ref name="B2"/>
<ref name="C2"/>
</group>
</interleave>
Ce pattern impose un ordre relatif à B1 et C1 d'un côté et B2 et C2 d'un
autre mais permet de les imbriquer comme on veut (cf
http://books.xmlschemata.org/relaxng/relax-CHP-6-SECT-7.html).
Il peut s'avérer complexe à implémenter si vous n'utilisez pas une
méthode générique telle que la méthode dérivative (voir plus bas).
.../...
> C'est ces template mode="AddSubNodeButtons" qui me posent problème.
> J'ai l'impression que je ne peux pas travailler de manière délarative
> à 100% au risque de multiplier les traitements spécifiques... le
> template qui match element n'est pas le même selon qu'il y a un
> zeroOrMore juste avant l'élément par exemple.
> Je devrait peut être faire un seul template qui traite tous les cas de
> figure avec des xsl:choose.
> Mais les cas de figures sont innombrables : toutes les combinaisons
> possibles (du moins autorisé en RelaxNG) des éléments element,
> attribute, text, group, interleave, oneOrMore, et ZeroOrMore...
> Comment prévoir tous les cas même les plus absurdes tel un ZeroOrMore
> dans un ZeroOrMore, traité comme un seul ZeroOrMore en fait.
> J'aimerai rester générique dans la mesure du possible, c'est-à dire
> que n'importe quel schéma utilisant les éléments indiqués puisse être
> correctement interprétés.
J'ai du mal à "entrer" dans votre transformation et vais plutôt vous
donner des conseils un peu plus génériques...
Ce que j'ai l'habitude de faire dans ce cas de figure où les choix
portent en général sur des aspects relativement indépendants du document
à générer, c'est que j'exécute en chaîne une série de templates dans des
modes différents, par exemple :
<xsl:template match="rng:element">
<xsl:apply-templates select="." mode="aspect1"/>
<xsl:apply-templates select="." mode="aspect2"/>
...
</xsl:template>
<xsl:template match="rng:oneMore/rng:element" mode="aspect1">
.../...
<xsl:apply-templates select="." mode="aspect1.1"/>
...
</xsl:template>
Ce n'est pas toujours facile à suivre mais cela permet de rester
déclaratif en dégageant des traitements relativement indépendants pour
éviter de gérer toutes les combinaisons.
Vous trouverez un exemple de cette façon de faire dans mon compilateur
Examplotron : http://examplotron.org/compile.xsl .
> On en revient peut être au problème du sujet précèdent "RelaxNG, outil
> xsl ?", la réponse serait elle de simplifier le schéma ("[...]
> encouragent les implémentations RELAX NG à simplifier les grammaires
> RELAX NG avant de les utiliser") ?
> A défaut de simplifier un schéma complexe existant je pourrais
> éventuellement donner des régles pour écrire le schéma dans sa version
> simplifiée directement, mais quelle règles au juste ?
> Faut-il que je prévoie tous les cas de figure d'imbrication (ayant du
> sens) des éléments indiqués, jusqu'à quel profondeur ?
>
> Si vous avez une idées, une démarche à suivre... merci d'avance,
Je pense qu'il s'agit d'un projet très intéressant qui, de toute
manière, sera complexe et très technique.
J'adore XSLT, mais c'est un projet qui est un peu en dehors de ses
objectifs et si vous avez la possibilité d'utiliser un langage de
programmation au lieu de XSLT, vous vous simplifiez la vie.
Personnellement, je pense que, quelque soit le langage de programmation,
je travaillerais sur un schéma RELAX NG simplifié et chercherais à
m'inspirer de la méthode déclarative décrite par James Clark :
http://www.thaiopensource.com/relaxng/derivative.html.
En gros, cela revient à calculer la "dérivée du schéma par le document",
c'est à dire à enlever de manière récursive du schéma tout ce qui figure
dans le document.
Si au cours de cette dérivation on tombe sur des impossibilités, c'est
que le document est invalide.
A la fin de la dérivation on a deux possibilités :
* si le schéma ne contient que des choses optionnelles (James
Clark dit alors qu'il est "nullable"), le document est valide.
* sinon, il n'est pas valide mais pourrait être complété pour le
devenir. C'est la notion de "feasible" suggérée par Rick
Jelliffe qui en avait besoin pour son éditeur Topologi et
ajoutée par James Clark à Jing.
Pour votre projet, je pense que vous pourriez essayer de calculer la
dérivée du schéma par le document actuel et vous appuyer sur cette
dérivée pour déterminer ce qui peut être ajouté au document.
Pour faire cela en XSLT, vous pourriez vous appuyer sur la bibiothèque
FXSL (http://fxsl.sourceforge.net/) ou, si cela vous fait peut (il y a
de quoi) faire une série de passes successives en utilisant une fonction
node-set (personnellement je préfère cela à dyn:evaluate().
Tout cela est sans doute plus facile à dire qu'à faire. J'espère tout de
même que ces quelques conseils pourront vous aider.
Bon courage pour ce projet passionnant!
Cordialement,
Eric van der Vlist
--
Weblog:
http://eric.van-der-vlist.com/blog?t=category&a=English
------------------------------------------------------------------------
Eric van der Vlist http://xmlfr.org http://dyomedea.com
(ISO) RELAX NG ISBN:0-596-00421-4 http://oreilly.com/catalog/relax
(W3C) XML Schema ISBN:0-596-00252-1 http://oreilly.com/catalog/xmlschema
------------------------------------------------------------------------
--
Devenez redacteur <XML>fr et contribuez au developpement du
xml francophone (http://xmlfr.org/infos/redacteurs/) !
Liste de diffusion "xml-tech@xmlfr.org" (http://xmlfr.org).
Cette liste est a votre disposition pour discuter en francais de
tout sujet technique lie a XML.
Pour resilier votre abonnement, envoyez un message contenant
la commande "unsubscribe" a xml-tech-request@xmlfr.org
(mailto:xml-tech-request@xmlfr.org?Subject=unsubscribe)
Received on Fri Oct 14 10:34:20 2005