2009-04-17 8 views

Répondre

0

cela fonctionnerait-il?

\"(?!\s*\w*>) 
+1

Certainement pas. Avez-vous essayé des exemples concrets? – Tomalak

6

Il n'existe pas d'expression régulière de ce type.

<p> 
    <!-- <a href=" --> is this outside " a tag <!-- "> foo </a> --> or not? 
</p> 

Si vous voulez faire cela, vous devrez malheureusement utiliser un analyseur HTML. Puisque vous avez déjà validé le code HTML, vous avez probablement déjà un analyseur à utiliser.

+0

Oh maintenant, je suis sûr que l'expression existe. Que vous deviez cartographier-le réduire sur un cluster Beowulf pour réellement effectuer la chose, avant d'entrer dans la prochaine ère glaciaire, est une autre question: P – brianreavis

+1

@brianreavis: Je me rends compte que vous plaisantez, mais, en fait: http: // en.wikipedia.org/wiki/Regular_language ... c'est en fait impossible, prouvable mathématiquement. – derobert

1

N'utilisez pas regex pour cela, utilisez (ou écrivez) un analyseur.

Le code suivant suppose que la chaîne HTML d'entrée est bien formée (comme vous l'avez indiqué). Soyez averti que le code va se casser s'il rencontre une entrée invalide!

Si vous ne pouvez pas être sûr de la bonne forme, vous pouvez essayer PHP Tidy.

<?php 
$html = '<tag>text "text"<tag attr="value"><!-- "text" --> text</tag> "text".'; 
echo html_escape_quotes($html); 

/* Parses input HTML and escapes any literal double quotes 
    in the text content with &quot;. Leaves comments alone. */ 
function html_escape_quotes($html) 
{ 
    $output = ""; 
    $length = strlen($html); 
    $delim = "<"; 
    $offset = 0; 
    while ($offset < $length) { 
    $tokpos = strpos($html, $delim, $offset); 
    if ($tokpos === false) $tokpos = $length; 

    $token = substr($html, $offset, $tokpos - $offset); 
    $offset = $tokpos; 

    if ($delim == "<") { 
     $token = str_replace('"', '&quot;', $token); 
     $delim = substr($html, $offset, 4) == "<!--" ? "-->" : ">"; 
    } else { 
     $delim = "<"; 
    } 

    $output .= $token; 
    } 
    return $output; 
} 
?> 
+2

Cela ne fonctionne pas si un attribut contient un '>'. Cela peut ne pas être commun mais c'est valide et donc possible. – Gumbo

+0

Hm ... Je m'attendrais à ce qu'il soit échappé malgré tout. Mais vous avez raison, en théorie c'est possible. +1 pour le commentaire. – Tomalak

+0

Après avoir joué un peu avec regex, je crois que l'expression suivante trouve la fin valide de la balise (toujours en supposant un code HTML valide):/[^ "<>] + ((?:" [^ "] *" |^'] *') * [^ ">] *) *?>/- Que pensez-vous? – Tomalak

0

C'est possible.

Vous pourriez être en mesure de le faire avec regexp, avec quelque chose de semblable à ci-dessous. Vous devrez exécuter plusieurs fois tho, que cette regex ne remplace que 1 "avec" entre les balises.

Serach: (\<.+?\>.+?)(")(.+?\</.+?\>) 
Replace: $1'$3 

Mais, la meilleure approche serait d'utiliser callbacks pour faire le remplacement de la fonction. Il suffit de créer RE qui envoie le contenu d'étiquettes à la fonction, qui peut alors simplement remplacer "avec ce que vous voulez.

Voir plus d'infos here. Rechercher un rappel Comme derobert noté, vous devrez peut-être supprimer des commentaires avant que :)

+0

Même si vous supprimez des commentaires (comment? Avec un analyseur, je suppose), vous vous retrouvez avec toutes sortes de amusant avec par exemple, cordes citées < and > sont valables dans les chaînes entre guillemets Et je n'ai même pas mentionné

0

Vous pouvez essayer de diviser la chaîne et séparer les balises des données textuelles avec cette expression:

<(?:\?[^?]+\?>|[A-Za-z]+(?:[^">]+|"[^"]*")*|!(?:\[CDATA\[(?:[^\]]+|](?:[^\]]|][^>]))*]]|--(?:[^-]+|-(?!->))*--))> 

Ce sera (je l'espère) correspond à tout PI XML, balise d'élément, CDATA et bloc de commentaire.

Alors:

$parts = preg_split('/(<(?:\?[^?]+\?>|[A-Za-z]+(?:[^">]+|"[^"]*")*|!(?:\[CDATA\[(?:[^\]]+|](?:[^\]]|][^>]))*]]|--(?:[^-]+|-(?!->))*--))>)/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); 
$str = ''; 
foreach ($parts as $part) { 
    if ($part[0] == '<') { 
     $str .= $part; 
    } else { 
     $str .= str_replace('"', '&quot;', $part); 
    } 
} 

Mais je doute que cela est très efficace. Un analyseur réel serait plus efficace et correct.

0

Pas le meilleur (fonctionne pas dans toutes les situations) mais assez bon pour moi:

function quoting(&$data) { 
    $quot = '(["\x93\x94\x84]|\&#8220;|\&#8222;|\&#8221;|\&ldquo;|\&bdquo;|\&rdquo;|\&quo;|\&#34;)'; 
    $parse = '<q>$2</q>'; 
    $data = preg_replace('/="([^"]*)"/', '*%Q:$1%*', $data); 
    $data = preg_replace("/$quot(.*?)$quot/", $parse, $data); 
    $data = preg_replace('/\*%Q:(.*?)%\*/', '="$1"', $data); 
} 
Questions connexes