2010-11-04 3 views
0

Dans la fonction doReplace ci-dessous, comment déterminer si l'instance de $ keyword n'est pas un enfant d'un tableau de balises html nommées (h1, h2, h3, h4, h5, h6, b, u, i, etc) à partir du point de remplacement où le mot-clé apparaît dans le contenu? Je ne me soucie pas de vérifier les balises imbriquées à ce stade.Comment déterminer si la chaîne de texte apparaît en tant qu'enfant d'une balise html nommée

Je pense qu'une certaine récursivité serait impliquée, à l'intérieur de la fonction deReplace.

function doReplace($keyword) 
{ 
//if(!is_keyword_in_named_tag()) 
    return ' <b>'.trim($keyword).'</b>'; 
} 

function init() 
{ 
    $content = "This will be some xhtml formatted 
    content that will be resident on the page in memory"; 
    $theContent = 
     preg_replace_callback("/\b('my test string')\b/i","doReplace", $content); 
    return $theContent; 
} 

Donc, si la variable $ content contient ...

<h1>This is my test string</h1> 

Puis la chaîne "ma chaîne de test" ne serait pas remplacé.

Mais si la variable #content contient ...

<h1>This is my test string</h1> 
<div>This is my test string too <b>my test string 3</b></div> 

Ensuite, le contenu serait remplacé ...

<h1>This is my test string</h1> 
<div>This is <b>my test string</b> too <b>my test string 3</b></div> 
+0

En l'état actuel, vous passez cette variable par valeur. Dans la fonction doReplace, $ keyword n'est rien d'autre qu'une chaîne. Je recommande d'extraire XPath et de faire des vérifications dans init(). – castis

+0

OK, exécutez un xpath sur la chaîne de contenu pour tester le contexte du mot clé avant d'envoyer le mot clé à doReplace()? –

Répondre

0

Vous pouvez utiliser quelque chose comme PHP Simple HTML DOM Parser.

Mise à jour: DOMDocument est une meilleure solution (et pas seulement de façon plus rapide, mais fonctionne bien avec les balises imbriquées aussi), donc à utiliser that au lieu de celui-ci.

Exemple:

require_once('simple_html_dom.php'); 

$html = str_get_html('<h1>This is my test string</h1> 
<div>This is my test string too <b>my test string 3</b></div>'); 

foreach ($html->find('text') as $element) 
{ 
    if (!in_array($element->parent()->tag, array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'b', 'u', 'i'))) 
     $element->innertext = str_replace('my test string', '<b>my test string</b>', $element->innertext); 
} 

echo $html; 
1

essayer avec DOMDocument et DOMXPath:

<?php 

function doReplace($html) 
{ 
    $dom = new DOMDocument(); 
    // loadHtml() needs mb_convert_encoding() to work well with UTF-8 encoding 
    $dom->loadHtml(mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8")); 

    $xpath = new DOMXPath($dom); 

    foreach ($xpath->query('//text()[ 
     not(ancestor::h1) and 
     not(ancestor::h2) and 
     not(ancestor::h3) and 
     not(ancestor::h4) and 
     not(ancestor::h5) and 
     not(ancestor::h6) and 
     not(ancestor::b) and 
     not(ancestor::u) and 
     not(ancestor::i) 
     ]') as $node) 
    { 
     $replaced = str_ireplace('my test string', '<b>my test string</b>', $node->wholeText); 
     $newNode = $dom->createDocumentFragment(); 
     $newNode->appendXML($replaced); 
     $node->parentNode->replaceChild($newNode, $node); 
    } 

    // get only the body tag with its contents, then trim the body tag itself to get only the original content 
    echo mb_substr($dom->saveXML($xpath->query('//body')->item(0)), 6, -7, "UTF-8"); 
} 

$html = '<h1>This is my test string</h1> 
<h2><span>Nested my test string</span></h2> 
<div>This is my test string too <b>my test string 3</b></div>'; 

echo doReplace($html); 
Questions connexes