Question

Je suis en train de récupérer des balises spécifiques avec leur contenu sur un document xhtml, mais il est correspondant aux mauvaises balises de fin.

Dans le contenu suivant:

<cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>

La fin d'une balise pour content_block id = « bienvenue » en fait apparié de se que la balise de fin de la première balise content_block d'ouverture.

Le regex J'utilise est:

/<content_block id="(.*)">([\w\W]*?)<\/content_block>/i

Les pointeurs sur l'endroit où je ne?

Était-ce utile?

La solution

... et la réponse est toujours la même: HTML + regex ne peut pas être fait . Pardon. Utilisez une bibliothèque pour votre analyse syntaxique HTML cadre particulier. Ou, si votre document est garanti pour ne contenir que XHTML, prendre l'approche XPath proposée par la gigue dans un commentaire.

Autres conseils

cela pourrait aider je l'ai trouvé tutoriel sur http://www.regular-expressions.info/examples.html qui mentionne la capture paire de chaîne récurrente dans le texte donné. suggestion est d'utiliser? après. * pour le faire arrêter après la première apparition de la fin de chaîne de la paire dans le texte

Ceci est un problème connu avec regex - vous ne pouvez pas correspondre à des paires. Matching est soit avide, où elle correspond à la dernière qu'il trouve, ou non gourmand, dans lequel elle correspond à la première. Vous ne pouvez pas convaincre un regex compter entre parenthèses d'ouverture et de fermeture.

Je recommande de le charger dans un DOM et en utilisant cela. Si vous essayez de mettre en œuvre un analyseur HTML, je vous conseille d'utiliser regex pour ce LEX puis un analyseur de gauche à droite pour analyser la sortie de votre lexer.

@Jan Zankowski et @ Ikegami, leur réponse m'a donné inpiration

Permettez-moi d'utiliser PHP pour démontrer le code

<?php
$xml = <<<EOT
<cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>
EOT;

preg_match('/<cache_namespace[^>]+>((?:(?!(<\/?div>)).)*)<\/cache_namespace>/s', $xml, $matches);
print_r($matches);

note regex

  • option s: un . dans le motif correspond à tous les caractères, y compris les nouvelles lignes
  • La clé ici est que (?:(?!STRING).)* est à cordes comme [^CHAR]* est de caractères

Résultat

Array
(
    [0] => <cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>
    [1] => 
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>

)

Parsing XHTML ou XML est pas difficile. Je suppose que vous avez un code valide ou bien formé.

#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
my $xml = <<"EOF";
<cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>
EOF

while ($xml =~ m!
<(content_block)\sid="welcome"> # Start tag definition.
 (\s*                           # It may consists of
   (?: <\!--.*?-->              # - comment
   |  [^<]*                     # - text
   |  <[^>]+/>                  # - another closed tag
   |  <\s*(\w+)[^>]*>           # - another tag with some content
       (?2)+                    # (recursive definition of possible tag content)
      </\3>
   )
 )*
</\1>
!sxgc) {
    print "==> $&\n\n";
}

S'il vous plaît modifier la définition de la balise de départ pour un autre contenu (comme <\s*(\w+)[^>]*+>). Quoi qu'il en soit, il est un bon point de départ.

Si vous n'utilisez récursion (ligne avec (?2)+) vous coincé sur ces exemples . Ce code peut traiter tous (s'il vous plaît regarder avant) ou peut facilement adapter à des situations nouvelles.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top