je retombe par hasard sur ce vieux sujet...
j'avais complètement oublié que j'avais posté cette question ici, et j'étais très surpris de découvrir que quelqu'un avait adopté la même solution que moi avant de réaliser que c'était mon bout de code
Voilà la version aboutie du code, qui fait à peu près ce que j'attendais de lui, à savoir une simple vérification qu'un fichier XML est bien formé (selon la définition stricte : une seule racine, une bonne correspondance de balises à balises), dans le cadre très limité d'une saisie dans un formulaire d'un fichier XML... Toute amélioration sera la bienvenue.
Si par ailleurs quelqu'un a développé des outils permettant l'édition à la volée de XML en javascript, je suis interessé ; j'ai développé un wrapper de textarea permettant de "controler" la saisie (indentation, vérification, menu de balises, ...), mais j'aimerais bien trouver d'autres approches à ce problème.
function checkXML( xml ) {
regExp = /(<(\/?)(?:\w+:)?([^>^ ]*)(?: [^>]*[^\/])?( *\/?)>)/gi;
// dans le cas des balises ouvrante
openingTag = function( tag ) {
return tag.match( new RegExp("< *(?!/)[^>]*[^/] *>","gi") )?true:false;
}
// dans le cas des balises strictement fermante
closingTag = function( tag ) {
return tag.match( new RegExp("< */[^>]+>","gi") )?true:false;
}
// vérifie que deux balises ouvrantes et fermantes strictes correspondent
matchingTags = function( openingTag, closingTag ) {
var expression = new RegExp("< */ *([^>]+) *>","gi");
var tags = expression.exec( closingTag );
return openingTag.match( new RegExp("< *"+tags[1]+"( +[^>]*)? *>","gi") );
}
// on supprime l'en-tête - A FAIRE : ne devrait pas être reconnu par regExp
xml = xml.replace( /<\?xml [^<>]*?>/i , "" );
var stack = new Array();
// récupération des balises
var tags = xml.match( regExp );
/* null si pas de résultats */
if ( tags!==null ) {
for (var i = 0; i < tags.length; i++) {
if ( openingTag(tags[i]) ) {
// on met la balise ouvrante sur la pile
stack.push(tags[i]);
} else if ( closingTag(tags[i]) ) {
// on verifie que le sommet de la pile contient la balise ouvrante correspondante
if ( stack.length==0 ) {
alert( tags[i]+' not open' );
return false;
}
var tag = stack.pop();
if ( !matchingTags( tag, tags[i] ) ) {
alert(tag+' and '+tags[i]+' mismatch');
return false;
}
}
}
}
// s'il reste quelque chose sur la pile, alors il manque des balises (si c'est une balise ouvrante) ou qu'il y en a trop (balise fermante)
if ( stack.length!==0 ) {
while ( tag = stack.pop() )
alert( tag+' has no match' );
return false;
}
else return true;
}
[/i][/i][/i][/i][/i][/i]
Modifié par lex (21 Dec 2008 - 11:20)