2010-03-08 6 views
3

en ligne Je trouve ce code regex utile ici tout en cherchant à analyser des attributs de balises HTML:RegEx pour extraire tous les attributs des balises HTML, y compris JavaScript

(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']? 

Il fonctionne très bien, mais il manque un élément clé que j'ai besoin. Certains attributs sont des déclencheurs d'événements qui ont en ligne le code Javascript dans les comme ceci:

onclick="doSomething(this, 'foo', 'bar');return false;" 

Ou:

onclick='doSomething(this, "foo", "bar");return false;' 

Je ne peux pas comprendre comment obtenir l'expression originale de ne pas compter les citations de la JS (simple ou double) alors qu'il est imbriqué dans l'ensemble des guillemets qui contiennent la valeur de l'attribut.

Je DEVRAIS ajouter que ceci n'est pas utilisé pour analyser un document HTML entier. Il est utilisé comme argument dans une ancienne fonction "tableau pour sélectionner le menu" que j'ai mise à jour. L'un des arguments est une balise qui peut ajouter des attributs HTML supplémentaires à l'élément de formulaire.

J'ai fait une fonction améliorée et déprécie l'ancien ... mais dans le cas où quelque part dans le code est un appel à l'ancienne fonction, j'en ai besoin pour les analyser dans le nouveau format de tableau. Exemple:

// Old Function 
function create_form_element($array, $type, $selected="", $append_att="") { ... } 
// Old Call 
create_form_element($array, SELECT, $selected_value, "onchange=\"something(this, '444');\""); 

La nouvelle version prend un tableau de paires attr => value pour créer des balises supplémentaires.

create_select($array, $selected_value, array('style' => 'width:250px;', 'onchange' => "doSomething('foo', 'bar')")); 

Ceci est simplement un problème de compatibilité ascendante où tous les appels à la fonction VIEILLE sont acheminés vers le nouveau, mais l'argument append_att de $ dans l'ancienne fonction doit être transformé en un tableau pour le nouveau, d'où mon besoin d'utiliser regex pour analyser de petits extraits HTML. S'il y a une meilleure façon de faire cela, je suis ouvert aux suggestions.

+3

ne Parse pas html avec ... -_- regex –

+2

http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 –

+2

C'est exactement pourquoi vous ne devriez pas analyser html avec regex. – Amarghosh

Répondre

2

Le problème avec votre expression régulière est qu'elle essaie de gérer à la fois des guillemets simples et doubles. Il ne prend pas en charge les valeurs d'attribut qui contiennent l'autre citation. Cette regex fonctionnera mieux:

(\w+)=("[^<>"]*"|'[^<>']*'|\w+) 
+2

Ferme, mais les valeurs d'attribut HTML 4.01 _can_ contiennent des chevrons. En outre, un nom d'attribut et une valeur d'attribut sans guillemets peuvent contenir des tirets, des points et des deux-points. Une meilleure expression est donc: '([\ w \ - .:] +) \ s * = \ s * (" [^ "] *" | '[^'] * '| [\ w \ - .:] +) '(Pédant, je sais ...) – ridgerunner

0

serait encore préférable d'utiliser des backreferences, en PHP l'expression régulière serait:

([a-zA-Z_:][-a-zA-Z0-9_:.]+)=(["'])(.*?)\\2 

\\2 est une référence à (["'])

De plus, cette régulière expression correspondra aux attributs contenant _, - et :, qui sont autorisés selon W3C, cependant, cette expression ne correspondra pas aux attributs dont les valeurs ne sont pas contenues d entre guillemets.

+0

Qu'en est-il de:' 'nom_attribut = valeur non spécifiée" '? – ridgerunner

+0

Les espaces dans les définitions attribut/valeur sont - pour autant que je sache - pas autorisés .. Ou n'est-ce pas ce que vous –

+0

Désolé, la solution ne correspond pas aux attributs dont les valeurs sont entre guillemets (soit 'name =" dq val "' ou 'name = 'sq val''), mais ne permet pas de faire correspondre les attributs avec les valeurs _unquoted_ ('name = uq_val'. – ridgerunner

1

regex suivantes fonctionnent selon les spécifications de syntaxe HTML disponibles ici

http://www.w3.org/TR/html-markup/syntax.html

modèles regex

// valid tag names 
$tagname = '[0-9a-zA-Z]+'; 
// valid attribute names 
$attr = "[^\s\\x00\"'>/=\pC]+"; 
// valid unquoted attribute values 
$uqval = "[^\s\"'=><`]*"; 
// valid single-quoted attribute values 
$sqval = "[^'\\x00\pC]*"; 
// valid double-quoted attribute values 
$dqval = "[^\"\\x00\pC]*"; 
// valid attribute-value pairs 
$attrval = "(?:\s+$attr\s*=\s*\"$dqval\")|(?:\s+$attr\s*=\s*'$sqval')|(?:\s+$attr\s*=\s*$uqval)|(?:\s+$attr)"; 

et la requête regex finale sera

// start tags + all attr formats 
    $patt[] = "<(?'starttags'$tagname)(?'tagattrs'($attrval)*)\s*(?'voidtags'[/]?)>"; 

    // end tags 
    $patt[] = "</(?'endtags'$tagname)\s*>"; // end tag 

    // full regex pcre pattern 
    $patt = implode("|", $patt); 
    // search and match 
    preg_match_all("#$patt#imuUs",$data,$matches); 

espérons que cette aide .

Questions connexes