2012-12-15 10 views
5

Mam zawartość html przechowywaną w tabeli bazy danych. w tej treści HTML chcę zastąpić "NIEKTÓRE SŁOWA" tagiem linku. Ale jeśli "NIEKTÓRE SŁOWA" znajduje się już w tagu linku, powinienem je pominąć ..Wyrażenie regularne PHP zastępujące "niektóre słowa" znacznikiem łącza, ale powinno wykluczać "niektóre słowa" wewnątrz znaczników łącza

np.
Zawartość

<p>Lorem ipsum dolor SOME WORDS, consectetur adipiscing elit. <a href="http://example.com">SOME WORDS</a> elementum pharetra velit at cursus. Quisque blandit, nibh at eleifend ullamcorper</p> 

Wyjście powinno być

<p>Lorem ipsum dolor <a href="http://someurl">SOME WORDS</a>, consectetur adipiscing elit. <a href="http://example.com">SOME WORDS</a> elementum pharetra velit at cursus. Quisque blandit, nibh at eleifend ullamcorper</p> 

jak widać, należy wykluczyć istniejące teksty łącza przy wymianie.

Kilka wskazówek, jak dotrzeć na właściwy tor jest bardzo doceniane.

+2

Nie używać wyrażeń regularnych, należy użyć parser HTML, takich jak domDocument –

+0

TRY - http://www.solmetra.com /scripts/regex/index.php - and - http://weblogtoolscollection.com/regex/regex.php - i kilka innych bzdur. – qooplmao

+1

Pamiętasz tę dziewczynę z ringu? Próbowała używać wyrażeń regularnych również do przetwarzania kodu HTML i sprawdzania, co się z nią stało! –

Odpowiedz

3

ten sposób można to rozwiązać za pomocą DOMDocument zamiast wyrażeń regularnych:

$contents = <<<EOS 
<p>Lorem ipsum dolor SOME WORDS, consectetur adipiscing elit. <a href="http://example.com">SOME WORDS</a> elementum pharetra velit at cursus. Quisque blandit, nibh at eleifend ullamcorper</p> 
EOS; 

$doc = new DOMDocument; 
libxml_use_internal_errors(true); 
$doc->loadHTML($contents); 
libxml_clear_errors(); 

$xp = new DOMXPath($doc); 

// find all text nodes 
foreach ($xp->query('//text()') as $node) { 
     // make sure it's not inside an anchor 
     if ($node->parentNode->nodeName !== 'a') { 
       $node->nodeValue = str_replace(
        'SOME WORDS', 
        'SOME OTHER WORDS', 
        $node->nodeValue 
       ); 
     } 
} 
// DOMDocument creates a full document and puts your fragment inside a body tag 
// So we enumerate the children and save their HTML representation 
$body = $doc->getElementsByTagName('body')->item(0); 
foreach ($body->childNodes as $node) { 
     echo $doc->saveHTML($node); 
} 
+0

dzięki .. rozwiązał problem .. Nie myślałem o użyciu parsera html .. – sanandrl

+0

Nie ma za co.Parsery HTML to świetny temat do nauki :) –

0

To powinno wystarczyć.

Wystarczy sprawdzić w regex jeśli niektóre słowa jest otoczony znacznikami

preg_replace('/[^>]SOME WORDS[^<]/','<a href="http://someurl">SOME WORDS</a>',$str); 
+2

to pęknie na coś takiego: here are SOME WORDS for you

1

Proste regex będzie działać tylko wtedy, gdy jest to dokładna fraza i wewnątrz linku bez innych symboli lub słów. Można wykonać iterację wszystkich wystąpień SOME WORDS, aby sprawdzić, czy znajdują się one w łączu, obliczając liczbę razy, kiedy przed wystąpieniem znajdował się znacznik otwierający i zamykający link. Spróbuj tego kodu:

$str = '<p>Lorem ipsum dolor SOME WORDS, consectetur adipiscing elit. <a href="http://example.com">SOME WORDS</a> elementum pharetra velit at cursus. Quisque blandit, nibh at eleifend ullamcorper</p>'; 
echo 'Before:' . $str; 
$str_lc = strtolower($str); 
$phrase = 'SOME WORDS'; 
$link = '<a href="http://someurl">SOME WORDS</a>'; 
$offset = 0; 
while($position = strpos($str, $phrase, $offset)) 
{ 
    if (substr_count($str_lc, "<a", 0, $position) <= substr_count($str_lc, "</a>", 0, $position)) { 
     $str = substr_replace($str, $link, $position, strlen($phrase)); 
     $str_lc = strtolower($str); 
     $offset = $position + strlen($link) - strlen($phrase); 
    } else { 
     $offset = $position + 1; 
    } 
} 
echo 'After:' . $str; 
1

Jeśli masz pokój dla 3 linii będzie to bezpieczny zakład:

$text=preg_replace('~<a(.*)(SOME WORDS)(.*)</a>~','<a$1PLACEHOLDER$3</a>',$text); 
$text=preg_replace('~SOME WORDS~','REPLACEMENT WORDS',$text); 
$text=preg_replace('~PLACEHOLDER~','SOME WORDS',$text); 

on użyje tekst zastępczy/tag/cokolwiek, więc nie zastępują link zawartość (jeśli taka istnieje).

Powiązane problemy