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 :

Imbrication de balises [FAQ] [RegEx]


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 7
    Par défaut Imbrication de balises
    Bonjour.
    Je suis en train de créer un parseur de BBCode avec des balises imbriquées.
    J'ai vu dans la documentation PHP pour la fonction preg_replace_callback une regex particulière qui permet de gérer l'imbrication.Ccependant j'ai du mal à l'adapter pour une utilisation légèrement plus complexe.

    Citation Envoyé par manuel php
    Exemple 1813. Exemple avec preg_replace_callback() en utilisant une structure récursive pour gérer du BB code
    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
    <?php
    $input = "plain<div style="margin-left:40px"> deep<div style="margin-left:40px"> deeper</div>deep</div>plain";
     
    function parseTagsRecursive($input)
    {
     
      $regex = '#\<div style="margin-left:40px">((?:[^[]|\[(?!/?indent])|(?R))+)\</div>#';
     
      if (is_array($input)) {
        $input = '<div style="margin-left: 10px">'.$input[1].'</div>';
      }
     
      return preg_replace_callback($regex, 'parseTagsRecursive', $input);
    }
     
    $output = parseTagsRecursive($input);
     
    echo $output;
    ?>
    J'ai trouvé dans le manuel PHP la signification de (?R), il s'agit apparemment d'une option pour effectuer une recherche récursive.

    Je ne maîtrise pas cette recherche récursive et j'ai un problème car je veux parser une balise BBCode avec un argument (par exemple je veux capturer aussi bien [indent=10] que [indent]), et en laissant la même regex il me capture seulement les tags sans argument.

    Merci de m'éclairer.

  2. #2
    Membre émérite Avatar de Korko Fain
    Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    632
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2005
    Messages : 632
    Par défaut
    [indent(?:=\d+)?]
    te capture
    [indent=10] mais aussi [indent]

    Et merci pour le ?R je ne connaissait pas.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 7
    Par défaut
    Justement non, j'avais essayé et ça ne marche pas, l'imbrication n'est plus supportée.
    En gros je veux faire une balise pour créer un tableau. J'ai besoin de pouvoir y ajouter un style éventuellement, pour cela je dois aussi bien capturer que [table style="margin:auto;"]...[/table] par exemple...
    Voilà ma regex telle qu'elle est maintenant, je précise qu'elle ne supporte pas l'imbrication quand je met l'argument style mais qu'elle supporte l'imbrication lorsque je met simplement (elle capture mais pas de façon récursive en fait).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <?php
    $regex = '`(\[table(?: style="(?:[ ()a-zA-Z0-9:;#/\'-]+)")?\](?:[^[]|\[(?!/?table(?: style="(?:[ ()a-zA-Z0-9:;#/\'-]+)")?\])|(?R))+\[/table\])`';
    ?>
    Je pense que je n'arrive pas à régler mon problème parce que je n'ai pas vraiment compris le fonctionnement de ?R mais je n'ai pas trouvé davantage d'explications que sur la page syntaxe des masques du manuel php.

    Merci d'avance.

  4. #4
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Par défaut
    Je viens d'essayer :
    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
    function recursive($input)
    {
        $nbMatches = preg_match_all('#\[([^\]]+)(?:="[^"]*")?\] ((?: (?:[^\[\]]) | ((?R)) )*) \[/\1\]#x', $input, $matches, PREG_SET_ORDER);
        if($nbMatches)
        {
            foreach($matches as $match)
            {
                if(!empty($match[2]))
                {
                    recursive($match[2]);
                }
            }
            print_r($matches);
        }
    }
     
    recursive('some [it]italics [bd]bolded [un]underlined [address="uri"]link[/address][/un][/bd] italics[/it], [bd]bold[/bd] raw');
    Sortie :
    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    Array
    (
        [0] => Array
            (
                [0] => [address="uri"]link[/address]
                [1] => address
                [2] => link
            )
     
    )
    Array
    (
        [0] => Array
            (
                [0] => [un]underlined [address="uri"]link[/address][/un]
                [1] => un
                [2] => underlined [address="uri"]link[/address]
                [3] => [address="uri"]link[/address]
            )
     
    )
    Array
    (
        [0] => Array
            (
                [0] => [bd]bolded [un]underlined [address="uri"]link[/address][/un][/bd]
                [1] => bd
                [2] => bolded [un]underlined [address="uri"]link[/address][/un]
                [3] => [un]underlined [address="uri"]link[/address][/un]
            )
     
    )
    Array
    (
        [0] => Array
            (
                [0] => [it]italics [bd]bolded [un]underlined [address="uri"]link[/address][/un][/bd] italics[/it]
                [1] => it
                [2] => italics [bd]bolded [un]underlined [address="uri"]link[/address][/un][/bd] italics
                [3] => [bd]bolded [un]underlined [address="uri"]link[/address][/un][/bd]
            )
     
        [1] => Array
            (
                [0] => [bd]bold[/bd]
                [1] => bd
                [2] => bold
            )
     
    )

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 7
    Par défaut
    En fait j'utilise une preg_split pour décomposer un texte en séparant les tableaux et le texte entre les tableaux.

    La regex que j'avais, à savoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <?php
    $contents = preg_split('`\[table\]((?:[^[]|\[(?!/?table\])|(?R))+)\[/table\]`', $contents, -1, PREG_SPLIT_DELIM_CAPTURE);
    ?>
    me traite seulement les tableaux de niveau 1 et en l'appelant récursivement j'arrive à faire ce que je veux, par exemple avec le code suivant : Mais si je prends en compte l'argument style, la récursivité ne fonctionne plus, il s'arrête à la première occurrence trouvée.
    J'ai mis cette regex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <?php
    $contents = preg_split('`\[table(?: style="(?:[ ()a-zA-Z0-9:;#/\'-]+)")?\]((?:[^[]|\[(?!/?table\])|(?R))+)\[/table\]`', $contents, -1, PREG_SPLIT_DELIM_CAPTURE);
    ?>
    et la récursivité ne fonctionne pas lorsque je rajoute un argument, par exemple :
    [table style="margin:auto;"]contenu du tableau[/table]
    Je ne comprends pas pourquoi la récursivité ne fonctionne pas dans cette regex, si quelqu'un pouvait m'expliquer le fonctionnement exact de l'option ?R je pense que j'arriverais à régler le problème tout seul par la suite.

    Merci à ceux qui me liront.

  6. #6
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Par défaut
    Ta regex est trop complexe

    Tel que je te l'ai proposé ci-dessus, ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    style="(?:[ ()a-zA-Z0-9:;#/\'-]+)"
    Peut être abrégé en :
    Bon, c'est pas exactement ça mais l'idée est là : ta regex est trop complexe. Tu gagnerais beaucoup à utiliser des classes négatives [^...] plutôt qu'énumératives [azdv;,è_çà876], et en plus c'est + flexible. Par exemple entre des guillemets, le seul caractère interdit est... Le guillemet
    C'est plus simple de dire "tout sauf un guillemet" que d'énumérer toutes les solutions possibles.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 26/09/2009, 16h25
  2. Imbrication de balises
    Par solorac dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 12/08/2009, 08h59
  3. CSS imbrication sur la balise BODY
    Par bouliz dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 17/02/2008, 12h59
  4. probleme d'imbrications de balises PHP/html
    Par rapanui dans le forum Langage
    Réponses: 6
    Dernier message: 08/12/2006, 19h06
  5. [XML] Imbrication balises/texte
    Par bourbaki2003 dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 10/11/2004, 18h00

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