Salut,
Je cherche, donné un arbre XML et un schéma RELAX NG, à suggérer un noeud enfant de l’arbre, en garantissant que celui-ci est valide selon le schéma.
Imagions la situation suivante:
schema.rng
:
<?xml version="1.0" encoding="utf-8"?>
<grammar>
<start>
<ref name="node.zds" />
</start>
<define name="node.zds">
<element name="zds">
<interleave>
<ref name="node.a" />
<ref name="node.b" />
</interleave>
</element>
</define>
<define name="node.a">
<element name="a">
<text />
</element>
</define>
<define name="node.b">
<element name="b">
<text />
</element>
</define>
</grammar>
zds.xml
:
<?xml version="1.0" encoding="utf-8"?>
<zds>
<b>hello world</b>
</zds>
Je souhaite donc obtenir une fonction suggest(node: Node): string[]
fournissant les suggestions pour le noeud node
. Par exemple, ici, j’aimerais obtenir ['a']
en sortie de suggest(zds)
.
Et je galère.
Mon idée est d’avoir une fonction récursive suggest(rngPointer: Node, xmlPointer: Node)
qui me retourne un objet { suggestions: string[], consume: { rng: { type: "jump", to: Node } | { type: "boolean", value: boolean }, xml: boolean }
, qui me permet d’avoir une boucle infinie, qui avance selon les valeurs de consume
.
Mais les problèmes arrivent dès qu’il ne s’agit plus d’avancer de façon linéaire. Je gère assez bien les ref
/define
avec le jump
, mais les choses se corsent avec les choice
, interleave
, et autres.
(À noter que je simplifie le RNG à l’avance pour garantir de n’avoir que deux enfants à chacun des choice
, interleave
, group
, etc., et que je remplace les optional
, zeroOrMore
par leurs équivalences à l’aide de choice
).
Pour l’instant, pour gérer un interleave
, je lance deux suggest
, un pour chaque enfant, et je regarde celui qui consume un noeud xml
. Sauf que bien sûr, ça a ses limites: ça ne fonctionne pas du moment que l’enfant direct du interleave
n’est pas un element
. Et je crois que c’est plutôt une limite de la façon dont j’encode le problème.
Est-ce que vous connaissez des problèmes analogues avec des façons <<classiques>> de les résoudre, ou avez une idée de comment <<bien>> résoudre ce problème?
Le vrai code se trouve sur Github https://github.com/dvbmgr/robin4.
Merci d’avance !