3 votes

Exclusion et inclusion d'un modèle de correspondance JavaScript Regex

J'utilise JavaScript RegExp pour mettre en évidence les recherches dans le contenu HTML.

Pour ce faire, j'utilise :

data.replace( new RegExp("("+search+")", 'g'), "<b id='searchHighlight'>$1</b>" );

donde data est l'ensemble du contenu HTML et search est la chaîne de recherche.

Lorsque l'on cherche, par exemple, h il mettrait en évidence les h dans les mots (the, there, etc...) ainsi que les occurrences dans les balises telles que "<h1 id="title"> Something </h1>" etc.

Je ne peux pas opter pour une autre approche puisque je dois mettre en évidence le même contenu HTML avec le même style.

J'ai lu des solutions comme :

var input = "a dog <span class='something'> had a  </span> and a cat";
// Remove anything tag-like
var temp = input.replace(/<.+?>/g, "");
// Perform the search
var matches = new RegExp(exp, "g").exec(temp);

Mais comme je dois mettre en évidence le texte de la recherche dans le même contenu HTML, je ne peux pas simplement supprimer les balises existantes. Existe-t-il un moyen de faire une recherche par inclusion et exclusion dans RegExp, de sorte que je puisse, par exemple, mettre en évidence h en "le" con "t<b id='searchHighlight'>h</b>e"
et ne pas permettre "<h1 id="title">Test</h1>" pour être corrompu ainsi : "<<b id='searchHighlight'>h</b>1 id="title">Test</<b id='searchHighlight'>h</b>1>" ?

Le contenu HTML est statique et ressemble à ceci :

    <h1 id="title">Samples</h1>
        <div id="content">
            <div  class="principle">
        <h2 id="heading">           
            PRINCIPLE</h2>

        <p>
            FDA recognizes that samples are an important part of ensuring that the right drugs are provided to the right patients. Under the Prescription Drug Marketing Act (PDMA), a sales representative is permitted to provide prescription drug samples to eligible healthcare professionals (HCPs). In order for BMS to provide this service, representatives must strictly abide by all applicable compliance standards pertaining to the distribution of samples.</p></div>
<h2 id="heading">           
            WHY DOES IT MATTER?</h2>
        <p>
            The Office of Inspector General (OIG) recognizes that samples can have monetary value to HCPs and, when used improperly, may have implications under the Federal False Claims Act and the Federal Anti-kickback Act. To minimize risk of such liability, the OIG requires the clear and conspicuous labeling of individual samples as units that cannot be sold.&nbsp; BMS and its business partners label every sample package to meet this requirement.&nbsp; Additionally, the HCP signature statement acknowledges that the samples will not be sold, billed or provided to family members or friends.</p>
        <h2 id="heading">

            WHO IS YOUR SMaRT PARTNER?</h2>
        <p>
            SMaRT is an acronym for &ldquo;Samples Management and Representatives Together&rdquo;.&nbsp; A SMaRT Partner has a thorough understanding of BMS sample requirements and is available to assist the field with any day-to-day policy or procedure questions related to sample activity. A SMaRT Partner will also:</p>

        <ul>
            <li style="margin-left:22pt;"> Monitor your adherence to BMS&rsquo;s sample requirements.</li>
            <li style="margin-left:22pt;"> Act as a conduit for sharing sample compliance issues and best practices.</li>
            <li style="margin-left:22pt;"> Respond to day-to-day sample accountability questions within two business days of receipt.</li>
        </ul>
        <p>

            Your SMaRT Partner can be reached at 888-475-2328, Option 3.</p>
        <h2 id="heading">

            BMS SAMPLE ACCOUNTABILITY POLICIES &amp; PROCEDURES</h2>
        <p>
            It is the responsibility of each sales representative to read, understand and follow the BMS Field Sample Accountability Procedures, USPSM-SOP-101. The basic expectations are:</p>
        <ul>
            <li style="margin-left:22pt;"> Transmit all sample activity by communicating your tablet to the host server on a <strong>daily</strong> basis.</li>
            <li style="margin-left:22pt;"> Maintain a four to six week inventory of samples rather than excessive, larger inventories that are more difficult to manage and increase your risk of non-compliance.</li>
            <li style="margin-left:22pt;"> Witness all HCP&rsquo;s signatures to confirm request and receipt of samples.</li>
        </ul>
</div>

Les contenus sont tous dispersés et ne se trouvent pas dans une seule étiquette. La manipulation du DOM n'est donc pas une solution pour moi.

4voto

MikeM Points 5873

Si vous pouvez être sûr qu'il n'y a pas < o > dans les attributs d'une balise, vous pourriez simplement utiliser

data = data.replace( 
    new RegExp( "(" + search + "(?![^<>]*>))", 'g' ),
        "<b id='searchHighlight'>$1</b>" );

L'anticipation négative (?![^<>]*>) empêche le remplacement si > apparaît avant < en avant dans la chaîne, comme à l'intérieur d'une balise.

Cette méthode est loin d'être infaillible, mais elle peut être suffisante.

Par ailleurs, comme vous effectuez une correspondance globale, c'est-à-dire que vous effectuez plus d'un remplacement, id='searchHighlight' devrait probablement être class='searchHighlight' .

Et vous devez faire attention à ce que search ne contient pas de caractères spéciaux de regex.

1voto

collapsar Points 4968

Vous êtes probablement conscient du fait que vous essayez d'utiliser le mauvais outil pour le travail, donc ceci est juste pour le compte rendu (au cas où vous ne le seriez pas, vous pouvez trouvez ceci perspicace ).

vous pourriez (et vous allez certainement ?) rencontrer un problème fondamental sur les attributs html avec un contenu textuel fondamentalement arbitraire, à savoir title (l'attribut de l'info-bulle) et data-... (attributs génériques définis par l'utilisateur pour contenir des données arbitraires par conception) - tout ce que vous trouvez dans la partie textuelle de votre code html, vous pourriez le trouver là aussi, dont le remplacement défigurera l'aide au ballon et/ou détruira une partie de la logique de l'application. notez également que tout caractère du contenu textuel peut être codé comme une entité nommée ou numérique (par ex. & -> &amp; , &#x26; , &#38; ), ce qui peut être géré en principe mais compliquera la regex dynamique (énormément dans le cas où votre variable search tiendra le texte droit).

Ayant dit tout cela, vous PEUT-ÊTRE s'entendre avec data.replace( new RegExp("([>]?)[^><]*("+search+")[^><]*([<]?)", 'g'), "<b id='searchHighlight'>$1$2$3</b>" ); à moins que les résultats de la recherche à mettre en évidence ne contiennent des caractères ayant une sémantique dans les spécifications regex, tels que .+*|([{}])\ peut-être - il faudrait que tu t'échappes correctement.

en résumé : réviser votre conception pour vous éviter des tas d'ennuis .

en fait, pourquoi ne pas opter pour le dom traversal ? il n'est pas nécessaire de connaître les balises html présentes pour le faire.

0voto

guypursey Points 1052

Ce n'est pas une solution purement RegExp mais, si vous ne pouvez pas traverser le DOM, la manipulation de chaînes de caractères avec des remplacements fonctionnels et des boucles comme celle-ci pourrait vous convenir.

  1. Déclarez les variables dont vous avez besoin et récupérez le innerHTML du corps de votre document.
  2. Examinez les données en extrayant toutes les balises et en les sauvegardant dans un tableau pour le moment. Laissez un emplacement pour savoir où les remettre plus tard.
  3. Une fois que toutes les balises ont été remplacées par des espaces temporaires dans votre chaîne de caractères, vous pouvez alors remplacer les caractères dont vous avez besoin, en utilisant votre code d'origine, mais en réaffectant le résultat à l'option data .
  4. Vous devrez ensuite restaurer les étiquettes en inversant le processus précédent.
  5. Attribuez le nouveau data comme innerHTML du corps de votre document.

C'est le le processus en action .

Voici le code :

var data = document.body.innerHTML, // get the DOM as a string
    tagarray = [], // a place to temporarily store all your tags
    tagmatch = /<[^>]+>/g, // for matching tags
    tagplaceholder = '<>', // could be anything but should not match the RegExp above, and not be the same as the search string below
    search = 'h'; // for example; but this could be set dynamically

while (tagmatch.test(data)) {
    data = data.replace(tagmatch, function (str) {
        tagarray.push(str); // store each matched tag in your array
        return tagplaceholder; // whatever your placeholder should be
    });
}

data = data.replace( new RegExp("("+search+")", 'g'), "<b id='searchHighlight'>$1</b>" ); // now search and replace the string of your choice

while (new RegExp(tagplaceholder, 'g').test(data)) {
    data = data.replace(tagplaceholder, function (str) {
        return tagarray.shift(str); // replace the placeholders with the tags you saved earlier to restore them
    });
}

document.body.innerHTML = data; // assign the changed `data` string to the body

Évidemment, si vous pouvez mettre tout cela dans une fonction à part entière, c'est encore mieux, car vous ne voulez pas vraiment que des variables globales comme celles mentionnées ci-dessus traînent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X