2010-06-03 7 views
1

Je recherche un code de remplacement approprié qui me permette de remplacer le contenu d'une balise HTML ayant une certaine classe, par exemple.Remplacer le contenu d'un tag par une certaine classe

$class = "blah"; 
$content = "new content"; 
$html = '<div class="blah">hello world</div>'; 

// code to replace, $html now looks like: 
// <div class="blah">new content</div> 

nu à l'esprit que:

  1. il ne sera pas nécessairement être une div, il pourrait être <h2 class="blah">
  2. La classe peut avoir plus d'une classe et doit encore être remplacé par exemple <div class="foo blah green">hello world</div>

Je pense expressions régulières devrait être en mesure de le faire, sinon je suis ouvert à d'autres suggestions telles que l'utilisation de la classe DOM (bien que je préférerais éviter cela, si possible, car il doit être PHP4 compatible) .

+0

Cela serait extrêmement facile si vous pouviez vous le permettre en JavaScript, en particulier jQuery. –

+0

Il semble exister des analyseurs html dans php4: http://www.google.com/search?client=ubuntu&channel=fs&q=html+parser+php4&ie=utf-8&oe=utf-8 – greg0ire

+0

J'utiliserais une regex comme affiché avant mais en utilisant le simple_html_dom est aussi une solution possible. – 2ndkauboy

Répondre

1

Do not use regular expressions to parse HTML. Vous pouvez utiliser le construit en DOMDocument, ou quelque chose comme simple_html_dom:

require_once("simple_html_dom.php"); 

$class = "blah"; 
$content = "new content"; 
$html = '<div class="blah">hello world</div>'; 

$doc = new simple_html_dom(); 
$doc->load($html); 

foreach ($doc->find("." . $class) as $node) { 
    $node->innertext = $content; 
} 

Désolé, je ne vois pas l'exigence de PHP4. Voici une solution utilisant le DOMDocument standard comme mentionné ci-dessus.

function DOM_getElementByClassName($referenceNode, $className, $index=false) { 
    $className = strtolower($className); 
    $response = array(); 

    foreach ($referenceNode->getElementsByTagName("*") as $node) { 
     $nodeClass = strtolower($node->getAttribute("class")); 

     if (
       $nodeClass == $className || 
       preg_match("/\b" . $className . "\b/", $nodeClass) 
      ) { 
      $response[] = $node; 
     } 
    } 

    if ($index !== false) { 
     return isset($response[$index]) ? $response[$index] : false; 
    } 

    return $response; 
} 

$doc = new DOMDocument(); 
$doc->loadHTML($html); 

foreach (DOM_getElementByClassName($doc, $class) as $node) { 
    $node->nodeValue = $content; 
} 

echo $doc->saveHTML(); 
+0

+ 1 pour glisser dans la diatribe de bobince: P – Matt

+0

C'est plus une épopée moderne qu'une diatribe;) –

-2

Il n'est pas nécessaire d'utiliser la classe DOM, cela serait probablement fait plus rapidement en utilisant jQuery, comme l'a dit Khnle, ou vous pourriez utiliser la fonction preg_replace(). Donnez-moi un peu de temps, je vais écrire une rapide regex pour vous.

Mais je recommande d'utiliser quelque chose comme jQuery, de cette façon, vous pouvez servir rapidement la page à l'utilisateur et permettre à son ordinateur de faire le traitement au lieu de votre serveur.

+0

Et si l'utilisateur a désactivé JavaScript? Ce n'est jamais une bonne idée de faire quelque chose dans JS si vous pouvez le faire sur le serveur car le serveur est beaucoup plus rapide qu'un client pourrait l'être. – 2ndkauboy

+0

Javascript et jQuery ne sont pas la solution pour tout. – Matt

+0

+ tout le point est que je ne peux pas utiliser jQuery il doit être côté serveur! – fire

-1

Si vous êtes sûr que $ html est un code HTML valide, vous pouvez utiliser un analyseur HTML ou même analyseur XML si son code XML valide.

Mais la façon rapide et sale dans Regex serait quelque chose comme:

$html = preg_replace('/(<[^>]+ class="[^>]*' . $class . '[^"]*"[^>]*>)[^<]+(<\/[^>]+>)/siU', '$1' . $content . '$2', $html); 

n'a pas testé trop, mais cela devrait fonctionner. Dites-moi si vous trouvez des cas où ce n'est pas le cas. ;)

Edit: Ajouté "et sale" ...;)

Edit 2: Nouvelle version du RegEx:

<?php 

$class = "blah"; 
$content = "new content"; 
$html = '<div class="blah test"><h1><span>hello</span> world</h1></div><div class="other">other content</div><h2 class="blah">remove this</h2>'; 

$html = preg_replace('/<([\w]+)(\s[^>]*class="[^"]*' . $class . '[^"]*"[^>]*>).+(<\/\\1>)/siU', '<$1$2' . $content . '$3', $html); 

echo $html; 

?> 

Le dernier problème est à gauche s'il y a une classe qui ne possède "blah" dans son nom, comme "tooMuchBlahNow". Voyons comment nous pouvons y remédier. Btw: Est-ce déjà évident que j'adore jouer avec RegEx? ;)

+0

@ b-i-d cela semble fonctionner pour les caractères alphanumériques mais pas s'il y a du HTML dans le tag ...? – fire

+0

Oui, ce n'était pas dans les spécifications de la question. Pour HTML dans le tag, le RegEx doit être un peu plus compliqué. Laissez-moi y penser ... –

+0

Mis à jour ma réponse. Un seul "problème" est parti. –

Questions connexes