2009-06-03 6 views
2

je besoin d'un regex pour faire ce qui suit (malheureusement, il doit être une expression régulière, je ne peux le code parce qu'il fonctionne dans un produit acheté):Regex pour sélectionner toutes les balises HTML image conditionnellement à la valeur src

Je souhaite sélectionner toutes les balises d'image dans un segment de code HTML où la balise d'image ne contient pas d'attribut de classe ou, si elle contient un attribut de classe, cet attribut ne contient pas de chaîne spécifique au début. Fondamentalement, je veux dépouiller (en faisant correspondre) toutes les étiquettes d'image d'un morceau de html SAUF pour les images avec une classe particulière appliquée à eux.

Cela pourrait être deux expressions régulières séparées - Je veux juste faire correspondre - pas extraire toutes les données.

Ainsi, par exemple, disons que la classe je veux garder est appelé Jolie.

Je voudrais l'expression rationnelle au match:

<img src="xx"/> 
<img border="x" src="xx"/> 
<img whatever other attributes src="xx"/> 
<img class="ugly" src="xx"/> 
<img whatever other attributes class="fugly" src="xx"/> 

mais pas correspondre

<img class="Pretty" src="xx"/> 
<img whatever other attributes class="Pretty" src="xx"/> 
<img class="Pretty subpretty" src="xx"/> 

S'il est plus facile de le faire dans un regex (un pour correspondre à tous les tags d'image sans attribut de classe, et un pour faire correspondre ceux avec des attributs de classe qui ne sont pas "jolis") c'est tout à fait bien aussi.

+0

Pouvez-vous garantir que l'attribut class (le cas échéant) est toujours avant l'attribut src? – laalto

+2

Donc, ce produit acheté vous donne une interface pour altérer certaines sources html avec des expressions régulières, mais vous ne pouvez pas extraire le HTML pour utiliser un simple analyseur? – Svante

+0

@myself: cette information n'est pas vraiment nécessaire - pensait à l'attribut src après le titre de la question mais la question elle-même n'en a pas besoin. – laalto

Répondre

8

Utilisez XPath à la place, comme c'est ce qu'il est pour:

//img[not(contains(@class,'Pretty'))] 

Cette expression XPath cherche tous les éléments img dont class attribut ne contient pas la chaîne 'Pretty'. Je pense que cela fonctionne pour les éléments qui manquent l'attribut class.

Parsing XML et HTML avec des expressions régulières est généralement une très mauvaise idée. Bien sûr, XPath ne fonctionne que si le HTML en question est strict. Si ce n'est pas un document XML valide, vous voudrez peut-être revenir à autre chose, mais même si regex n'est pas le bon outil pour le travail.

Addendum: Je me suis trompé sur revenir à cela en 30 minutes. Quelque chose est arrivé et je n'ai pas le temps de le régler. Si cela ne fonctionne pas pour les éléments qui manquent l'attribut class, utilisez l'expression suivante:

//img[(not(@class)) or (not(contains(@class,'Pretty')))] 
+0

+1 sauf que XPath peut aussi être utilisé sur du XML non valide en utilisant HTML Agility Pack et des paquets similaires – Dror

+0

Dans XPath, 'not()' est une fonction, pas un opérateur. Vous devez ajouter/corriger vos parenthèses. http://www.w3.org/TR/xpath.html#function-not –

+0

@Ben: Merci pour les heads up. – Welbog

2

Un peu rapide et sale, mais cela fonctionne:

/(?!<img\b[^>]+\bclass="?[^>"]*\bPretty\b)<img\b[^>]*>/ 

Comment ça marche:

<img\b[^>]+\bclass="?[^>"]*\bPretty\b correspond à toutes "Pretty" images.

<img\b[^>]*> matchs toutes les images. Donc, placez le sous-modèle d'image "Joli" dans une vue négative devant le sous-masque pour faire correspondre toutes les images. Cela correspondra alors à toutes les images, moins celles qui correspondent au joli sous-motif.

1
<img(?:\s+(?:(?!class\b)\w+="[^"]*"|class="(?!Pretty)[^"]*"))*/> 

qui semble répondre à votre question, mais il y a beaucoup de détails que vous ne l'avez pas l'adresse, comme:

  • sont la TAG- et noms d'attributs toujours en minuscules?Que se passe-t-il si le nom de la classe commence par "pretty" (c'est-à-dire, est-ce que la casse est sensible)?

  • Les valeurs d'attribut sont-elles toujours entre guillemets, et toujours avec des guillemets?

  • Y aura-t-il des espaces supplémentaires, comme autour du "=" ou avant le final "/>"? Est-ce que votre "outil acheté" prend en charge les regex avec des retards de recherche négatifs?

0

Oui, à tous ceux qui a suggéré que je serais mieux d'utiliser autre chose que regex vous êtes de droite bien sûr, mais je suppose que vous avez manqué la première phrase de la question.

J'ai fini par trouver la solution, le look de nick et d'alan M est le plus proche, merci les gars! Heureusement, je peux utiliser des lookahead négatifs pour que ça fonctionne parfaitement :)

Questions connexes