IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Regex suppression des balises html avec attribut


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club Avatar de jerome14000
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2018
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2018
    Messages : 6
    Par défaut Regex suppression des balises html avec attribut
    Bonjour à tous,

    Depuis quelques jours je n'arrive pas à formaliser une expression régulière permettant de supprimer toutes les balises html d'une chaîne (et leurs contenus) qui possèdent un attribut spécifique.

    Ci-dessous un exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $string='<th>col 1</th><th>col 2</th><th id="col3" my_attribute="true">col 3</th>
    <tr><td>x1y1</td><td>x1y2</td><td id="x1y3" my_attribute="true">x1y3</td></tr>
    <tr><td>x2y1</td><td>x2y2</td><td id="x2y3" my_attribute="true">x2y3</td></tr>
    <tr><td>x3y1</td><td>x3y2</td><td id="x3y3" my_attribute="true">x3y3</td></tr>
    <tr><td>x4y1</td><td>x4y2</td><td id="x4y3" my_attribute="true">x4y3</td></tr>';
    
    $pattern='#<t[d|h].(my_attribute)^>.*?</t[d|h]>#s';
    $result=preg_replace($pattern, '', $string);
    Ci-dessous le résultat attendu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $result='<th>col 1</th><th>col 2</th>
    <tr><td>x1y1</td><td>x1y2</td></tr>
    <tr><td>x2y1</td><td>x2y2</td></tr>
    <tr><td>x3y1</td><td>x3y2</td></tr>
    <tr><td>x4y1</td><td>x4y2</td></tr>';
    Par avance merci pour votre aide

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    $pattern='#(<t[d|h](.|\n|\r)*my_attribute=(.|\n|\r)*<\/t[d|h]>)#Um';
    • U : Ungreedy
    • m : multiline

  3. #3
    Nouveau membre du Club Avatar de jerome14000
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2018
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2018
    Messages : 6
    Par défaut
    Citation Envoyé par jreaux62 Voir le message
    Bonjour,

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    $pattern='#(<t[d|h](.|\n|\r)*my_attribute=(.|\n|\r)*<\/t[d|h]>)#Um';
    • U : Ungreedy
    • m : multiline
    Bonjour jreaux62,

    Déjà merci pour ton aide
    J'ai testé ton expression et elle supprime l'ensemble des balises td et th. La condition(détection) de l'attribut ne fonctionne pas. As-tu une idée ?

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Citation Envoyé par jerome14000 Voir le message
    J'ai testé ton expression et elle supprime l'ensemble des balises td et th.
    C'est normal, car <t[d|h] (qui s'écrit <t[dh], le pipe perd sa signification spéciale dans une classe de caractères) chope le premier <td ou <tr qu'il rencontre, puis (.|\n|\r)*, bien que muni d'un quantificateur non-gourmand avec l'option U, continue sa course jusqu'à trouver une éventuelle sous-chaîne my_attribute=. Le problème vient du . qui peut matcher n'importe quel caractère et notamment < ou >, ce qui autorise (.|\n|\r)* à "sortir d'une balise" et à rentrer dans une autre, jusqu'à ce que l'attribut (ou une chaîne qui lui ressemble) soit trouvé.

    Il faut remplacer le point par une classe de caractère qui exclut >. On peut par exemple écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $pattern = '~<t([dh])\s+(?>[^\s>]+\s+)*?my_attribute=[^<]++(?:<(?!/t\1>)[^<]+)*+</t\1>~i';
    Mais même si cette pattern prend la précaution de ne pas sortir de la balise avant de rencontrer l'attribut et vérifie que les balises ouvrante et fermante correspondent, ça reste très hasardeux d'attaquer du code html avec des regex. Je pourrais te sortir mille et un exemples où cette pattern serait prise en défaut, voire causerait des catastrophes. Le html est un langage très flexible et sa syntaxe est bien plus complexe qu'il n'y parait. Donc la solution, c'est le DOM.

  5. #5
    Nouveau membre du Club Avatar de jerome14000
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2018
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2018
    Messages : 6
    Par défaut
    Bonjour CosmoKnacki.
    Merci pour tes réponses, les deux solutions fonctionnent
    Tu as raison sur la faillibilité du regex, autant tout de suite partir sur une solution blindé avec DOMDocument()

    PS : Le th sans tr c'est un oubli, l'exemple ne nécessitait pas de rigueur dans le code, finalement peu importe le type de balise.

  6. #6
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 694
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 694
    Par défaut
    les expressions régulières ne sont pas très pratiques pour travailler avec de l'HTML.
    je vous conseille plutôt d'utiliser des fonctions d'analyse comme DOM par exemple : https://secure.php.net/DOM

  7. #7
    Nouveau membre du Club Avatar de jerome14000
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2018
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2018
    Messages : 6
    Par défaut
    Citation Envoyé par mathieu Voir le message
    les expressions régulières ne sont pas très pratiques pour travailler avec de l'HTML.
    je vous conseille plutôt d'utiliser des fonctions d'analyse comme DOM par exemple : https://secure.php.net/DOM
    Bonjour mathieu,

    merci aussi pour ta réponse
    Pour mon exemple c'était plus rapide (mais pas facile ^^) de mettre en oeuvre un regex. Je m'y résoudrai s'il n'y a pas de solution.

  8. #8
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Voilà comment procéder avec DOMDocument:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    $string='<th>col 1</th><th>col 2</th><th id="col3" my_attribute="true">col 3</th>
    <tr><td>x1y1</td><td>x1y2</td><td id="x1y3" my_attribute="true">x1y3</td></tr>
    <tr><td>x2y1</td><td>x2y2</td><td id="x2y3" my_attribute="true">x2y3</td></tr>
    <tr><td>x3y1</td><td>x3y2</td><td id="x3y3" my_attribute="true">x3y3</td></tr>
    <tr><td>x4y1</td><td>x4y2</td><td id="x4y3" my_attribute="true">x4y3</td></tr>';
     
    $dom = new DOMDocument;
    // on évite l'affichage d'erreurs html en les redirigeant vers le gestionnaire d'erreurs
    // de libxml. On sauvegarde l'ancien état dans $state.
    $state = libxml_use_internal_errors(true);
     
    // on charge le document en ayant pris soin de lui ajouter un élément racine pour que l'arbre DOM
    // soit construit correctement.
    $dom->loadHTML('<div>' . $string . '</div>', LIBXML_HTML_NOIMPLIED);
     
    // on restitue l'ancien état du gestionnaire d'erreurs de libxml
    libxml_use_internal_errors($state);
     
    // on crée un objet DOMXPath pour pouvoir faire des requètes XPath sur l'arbre DOM.
    $xp = new DOMXPath($dom);
     
    // n'importe où dans l'arbre DOM '//', tout élément '*' dont le nom est "td" ou "th", et ayant un attribut "my_attribute"'
    $nodeList = $xp->query('//*[name()="td" or name()="th"][@my_attribute]');
     
    // on les enlève.
    foreach ($nodeList as $node) {
        $node->parentNode->removeChild($node);
    }
     
    // on reconstitue la chaîne html en concaténant les noeuds enfant de l'élément racine.
    $result = '';
     
    foreach ($dom->documentElement->childNodes as $node) {
        $result .= $dom->saveHTML($node);
    }
     
    echo $result;
    Attention, si un élément tr contient plus d'un élément th ou td à enlever, il faudra modifier le script (juste la partie qui enlève). Je te laisse le soin de trouver comment faire.

    Au passage, pourquoi les éléments th ne sont pas dans un élément tr (éléments tr qui ne sont d'ailleurs pas dans un élément table)?

Discussions similaires

  1. Suppression des balises Html dans mon flux rss
    Par Guispeed4262 dans le forum Windows Phone
    Réponses: 12
    Dernier message: 24/10/2012, 13h47
  2. Problème avec XSLT et du XML contenant des balises HTML
    Par xamber dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 02/11/2011, 11h45
  3. Réponses: 22
    Dernier message: 28/08/2011, 23h12
  4. Obtenir des balises html+texte avec xpath ?
    Par apt dans le forum Langage
    Réponses: 1
    Dernier message: 23/07/2011, 12h07
  5. REGEX avec exclusion des balises HTML
    Par Tchupacabra dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 15/10/2008, 09h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo