J’ai pondu la fonction ci-dessous sur vos conseils. Je parcours la chaîne (qui n’est jamais bien longue, c’est l’équivalent d’un paragraphe), je détecte si j’ai une balise ouvrante, dans ce cas, je l’empile. Si c’est une balise fermante, je vérifie qu’elle correspond à la dernière balise empilée. Si c’est le cas, je la dépile. Comme j’ai besoin de connaître la position de la balise dans la chaîne, j’ai ajouté une autre variable qui me permet de stocker la position de la balise et son nom.
Après plusieurs tests, j’ai bien le résultat attendu.
Voici ma solution (n’hésitez pas à la critiquer)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 | function searchTagNotClosed(string) {
var arrTagNotClosed = new Object();
var pile = [];
for (var i in string) {
var c = string[i];
//Détection d'une balise
if (c === '<') {
var isTagStart = false;
var isTagEnd = false;
var j; //position à partir de laquelle récupérer le nom de la balise
//type de la balise (fermante ou ouvrante)
var p = parseInt(i) + parseInt(1);
if (string[p] === '/') {
//balise fermante
isTagEnd = true;
j = parseInt(i) + parseInt(2);
} else {
//balise ouvrante
isTagStart = true;
j = parseInt(i) + parseInt(1);
}
//on récupère le nom de la balise et on commence à partir de la
// position courante (qui est < plus 1)
if (isTagStart || isTagEnd) {
//on récupère la chaîne à partir de la position courante J
var stringWithTagName = string.substring(j);
//le nom s'arrête à > (ce qui inclus alors les éventuels attributs)
var pos = stringWithTagName.indexOf('>');
var stringTagNameWithAttr = stringWithTagName.substr(0, pos);
pos = stringTagNameWithAttr.indexOf(' ');
if (pos !== -1) {
//il y avait bien des attributs, donc on récupère seulement
//le nom du tag
var tagName = stringWithTagName.substr(0, pos);
} else {
//il n'y a pas d'attribut
tagName = stringTagNameWithAttr;
}
//si c'est une balise ouvrante, il faut l'empiler et mettre à jour
// le tableau qui contient le tag et sa position (i) dans la chaîne
if (isTagStart) {
//on empile (en début de tableau)
pile.unshift(tagName);
arrTagNotClosed[i] = tagName;
}
//si c'est une balise fermante, il faut regarder si le nom est
// le même que le premier élément du tableau. Si c'est le cas,
// cela signifie que la balise est fermée, il faut retirer
// l'élément de la pile
if (isTagEnd) {
if (tagName === pile[0]) {
//on dépile en début de tableau
pile.shift();
//on supprime également l'élément dépilé du tableau
// contenant les tags ouverts avec leur position
Object.deleteLast(arrTagNotClosed);
} else {
arrTagNotClosed[i] = tagName;
}
}
}
}
}
return arrTagNotClosed;
}
|
Je marque le sujet comme résolu, mais s’il y a moyen d’optimiser, n’hésitez pas à le dire. De plus, pour l’instant, ma fonction ne gère pas la possibilité de rencontrer des balises orphelines.
Merci à tous les participants de ce sujet.