11548 sujets

JavaScript, DOM et API Web HTML5

Bjour à tous,

Voici en quelques mots mon problème : j'aimerais construire une regexp dynamique capable de capturer ce genre de string

...
<!--
<param for="various_element_id">
  <field ... />
  <field ... />
  ...
</param>
-->
...


Pour capturer ce qui se situe entre <parm ...> et </param>
J'ai pensé à ce genre de pattern pour ma regexp :
myreg = new RegExp('<param\\s*for=["\']\\s*' + myvar + '\\s*["\']\\s*>(.*|\\s*)</param>', 'im')


Que je test sur le contenu de body en fin de document avec
myreg.test(document.body.innerHTML)


Pour info voici la regexp après construction :
/<param\s*for=["']\s*various_element_id\s*["']\s*>(.*|\s*)<\/param>/im


Seulement voilà cette regexp est de toute évidence fausse en multiligne alors qu'elle est tout à fait correcte sur une seule ligne.

Savez-vous pourquoi ?
Auriez-vous une piste à m'indiquer pour la capture multilignes ?

Merci.
Modifié par Ze Nenex (14 Mar 2007 - 11:31)
Ah, moi aussi j'ai déjà galéré avec les regexp multilignes en js.
Le seul moyen que j'ai trouvé, c'est de remplacer temporairement les \r\n par des autres caractères, par exemple des caractères non imprimables ou une séquence spéciale qui n'a pratiquement aucun risque d'apparaître par hasard.
Je sais, c'est pas très propre...
Si quelqqu'un trouve, franchement ça m'intéresse aussi.

Par contre tu peux peut-être déjà essayer en ajoutant le flag g à ta regexp actuelle.
Dernièrement j'ai testé cette regexp :
/<balise>(?:\s)*(.*)(?:\s)*<\/balise>/im


Elle a fonctionné pour cet exemple seulement, adaptée à mon cas (ie construite avec le constructor RegExp) elle foire... Bref, je sens qu'il va y avoir sérieuse prise de tête.

QuentinC : je n'ai besoin de capturer qu'une chaine par RegExp dynamique, d'où le fait de ne pas mettre le flag g.

Et là google n'est vraiment pas mon pote.

Smiley fache
Petite solution qui rejoint celle de QuentinC mais qui n'est effectivement pas très recommandée, même si elle a le mérite de fonctionner.

Pour capturer une chaine multiligne, sans même avoir besoin d'un flag "m" (dont je doute de l'utilité du coup...), il suffit de demander à la regexp de cibler tous les caractères exceptés ceux qui n'ont, à priori, aucune chance d'apparaitre dans la chaine, de cette façon :


// Je capture tous les caractères entre <balise> et </balise>
// Attention, le catactère þ créera l'exception
/<balise>([^þ]*)<\/balise>/i


Donc, adaptez le caractère exceptionnel à vos besoins spécifiques.
Je suis évidement toujours à la recherche d'une solution plus propre.

Voilà voilà.
@plouche
Pour info si quelqu'un tombe sur ce post, exemple d'application :


...
<body>
		
  <!--
  <param for="un_test">
    <field id="1" />
    <field id="2" />
    <field id="3" />
  </param>
  -->
		
  <script type="text/javascript">
		
    var mytest = 'un_test';
    var myreg = new RegExp('<param +for=["\'] *' + mytest + ' *["\'] *>([^¶]*)</param>', 'i');	
    var mymatch = myreg.exec(document.body.innerHTML);
    var myparm = mymatch[1].split(/[\t\r\n]/g);
			
    alert(myparm);
    // Affiche <field id="1" />,<field id="2" />,<field id="3" />
			
  </script>
  ...


Bien sur tout peut-être optimisé, arrangé à sa sauce etc...
@plouche.
Modifié par Ze Nenex (14 Mar 2007 - 12:30)
Hello,

Pourquoi utilises-tu le tag multiline ? Il ne sert à rien dans ton cas.

A mon avis, ton problème vient de ceci :
(.*|\\s*)
qu'il faudrait remplacer par
(.|\\s)*
Julien Royer a écrit :

Pourquoi utilises-tu le tag multiline ? Il ne sert à rien dans ton cas.

Je sais que cette question ne m'est pas destinée, mais ça m'intéresserait de savoir une fois pour toute à quoi sert le tag m.
Jusqu'à maintenant, pour moi, ça signifie pour le point qu'il prendra aussi les sauts de ligne, ce qu'il ne fait pas habituellement.
Mais apparament, d'après ce que tu dis, ça ne serait pas ça...

Ze Nenex > Ta combine rejoint le mine, en quelque sorte, effectivement. Mon truc à moi, c'était celui-là :

str = str.split(/\r\n|\n|\r/g).join("÷");
// ... mon traitement ...
str = str.split("÷").join("\r\n");
QuentinC a écrit :
Je sais que cette question ne m'est pas destinée, mais ça m'intéresserait de savoir une fois pour toute à quoi sert le tag m.
Il permet que ^ et $ fonctionnent également pour les débuts et fins de lignes. Par exemple :
alert((/^a/).test("b\na")); // false
alert((/^a/m).test("b\na")); // true
Quant au métacaractère ".", il correspond dans tous les cas à n'importe quel caractère sauf à un saut de ligne (line feed, carriage return, line separator, paragraph separator).
Pourtant, je ne sais pas où, mais il me semble avoir lu qu'en multiligne, le . capturait également les line feed. A moins que ce ne soit qu'en perl (flag s).

Julien Royer > après un petit test avec (.|\s)* et bha... plantage (IE/FF). Recommencement sur une page vierge : idem, ça tourne en boucle. Enfin bon j'ai eu ma solution bancale et je vais pour l'instant m'en contenter.

Merci à vous 2.
@plouche.
Modifié par Ze Nenex (14 Mar 2007 - 22:37)
Ze Nenex a écrit :
Pourtant, je ne sais pas où, mais il me semble avoir lu qu'en multiligne, le . capturait également les line feed. A moins que ce ne soit qu'en perl (flag s).
Possible. En tout cas, en JavaScript c'est sûr que non :
alert((/./).test("\n")); // false
alert((/./m).test("\n")); // false

En tout cas, je pense qu'il serait plus propre d'utiliser "[^]" plutôt que "[^¶]". Smiley smile
Modifié par Julien Royer (14 Mar 2007 - 23:34)
Julien Royer a écrit :
En tout cas, je pense qu'il serait plus propre d'utiliser "[^]" plutôt que "[^¶]". Smiley smile
Ca n'a pas l'air de marcher sous IE...

Sinon
([^p]|p)
ou
(.|\s)