2009-04-27 13 views
5

Mam funkcję, która zastępuje atrybut href kotwicy w ciągu za pomocą DOMDocument Php. Oto fragment:Jak uniemożliwić DOMDocument Php na kodowanie encji html?

$doc  = new DOMDocument('1.0', 'UTF-8'); 
$doc->loadHTML($text); 
$anchors = $doc->getElementsByTagName('a'); 

foreach($anchors as $a) { 
    $a->setAttribute('href', 'http://google.com'); 
} 

return $doc->saveHTML(); 

Problemem jest to, że loadHTML ($ text) otacza $ tekst DOCTYPE html, body itd tagi. Próbowałem pracować wokół to w ten sposób zamiast loadHTML():

$doc  = new DOMDocument('1.0', 'UTF-8'); 
$node  = $doc->createTextNode($text); 
$doc->appendChild($node); 
... 

Niestety, ten koduje wszystkie podmioty (kotwy w komplecie). Czy ktoś wie, jak to wyłączyć? Dokładnie przejrzałem dokumenty i próbowałem je zhakować, ale nie mogę tego rozgryźć.

Dzięki! :)

Odpowiedz

3
$ tekst jest przetłumaczony łańcuch z miejscem uchwyt tagów kotwicznych

Jeśli te miejsce posiadacze mają surowe, dobrze zdefiniowane sformatować prosty preg_replace lub preg_replace_callback może rade.
Nie sugeruję manipulowania dokumentami html z regex w ogóle, ale dla małego dobrze zdefiniowanego podzbioru są odpowiednie.

1

XML ma tylko very few predefined entities. Wszystkie twoje jednostki html są zdefiniowane gdzieś indziej. Kiedy używasz loadhtml() te definicje encji są ładowane automagicznie, z loadxml() (lub bez load() w ogóle) nie są.
Funkcja createTextNode() wykonuje dokładnie to, co sugeruje nazwa. Wszystko, co przekazujesz jako wartość, jest traktowane jako treść tekstowa, a nie jako znacznik. To znaczy. jeśli przekazujesz coś, co ma specjalne znaczenie dla znaczników (<, > ...), jest zakodowane w taki sposób, że analizator składni może odróżnić tekst od rzeczywistego znacznika (& lt ;, & gt ;, ...)

Skąd pochodzi tekst? Nie możesz dokonać wymiany w rzeczywistym dokumencie HTML?

+0

loadHTML, nie występuje tłumaczenie encji. Skończyłem hacking wokół problemu w wątły sposób, uruchamiając mb_substr ($ text, 122, -19); na wynik z $ doc-> saveHTML(). Yikes! :) $ tekst jest tłumaczonym ciągiem znaków z znacznikami zakotwiczenia miejsca, więc wymiana musi zostać wykonana w czasie wykonywania.Wolałbym nie parsować całego dokumentu, ponieważ byłoby trudno przetworzyć tylko przetłumaczone linki. Dobry pomysł. – thesmart

0

skończyło się hacking to w rozrzedzonym sposób zmienia:

return $doc->saveHTML(); 

do:

$text  = $doc->saveHTML(); 
return mb_substr($text, 122, -19); 

ten wycina wszystkie niepotrzebne śmieci, zmieniając w ten sposób:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" 
"http://www.w3.org/TR/REC-html40/loose.dtd"> <html><body><p> 
You can <a href="http://www.google.com">click here</a> to visit Google.</p> 
</body></html> 

w tym:

You can <a href="http://www.google.com">click here</a> to visit Google. 

Czy każdy może znaleźć coś lepszego?

-1

OK, oto ostateczne rozwiązanie, które znalazłem. Postanowiła pójść z sugestią VolkerK.

public static function ReplaceAnchors($text, array $attributeSets) 
{ 
    $expression = '/(<a)([\s\w\d:\/=_&\[\]\+%".?])*(>)/'; 

    if (empty($attributeSets) || !is_array($attributeSets)) { 
     // no attributes to set. Set href="#". 
     return preg_replace($expression, '$1 href="#"$3', $text); 
    } 

    $attributeStrs = array(); 
    foreach ($attributeSets as $attributeKeyVal) { 
     // loop thru attributes and set the anchor 
     $attributePairs = array(); 
     foreach ($attributeKeyVal as $name => $value) { 
      if (!is_string($value) && !is_int($value)) { 
       continue; // skip 
      } 

      $name    = htmlspecialchars($name); 
      $value    = htmlspecialchars($value); 
      $attributePairs[] = "$name=\"$value\""; 
     } 
     $attributeStrs[] = implode(' ', $attributePairs); 
    } 

    $i  = -1; 
    $pieces = preg_split($expression, $text); 
    foreach ($pieces as &$piece) { 
     if ($i === -1) { 
      // skip the first token 
      ++$i; 
      continue; 
     } 

     // figure out which attribute string to use 
     if (isset($attributeStrs[$i])) { 
      // pick the parallel attribute string 
      $attributeStr = $attributeStrs[$i]; 
     } else { 
      // pick the last attribute string if we don't have enough 
      $attributeStr = $attributeStrs[count($attributeStrs) - 1]; 
     } 

     // build a opening new anchor for this token. 
     $piece = '<a '.$attributeStr.'>'.preg_replace($expression, '$1 href="#"$3', $piece); 
     ++$i; 
    } 

    return implode('', $pieces); 

Umożliwia to wywołanie funkcji za pomocą zestawu różnych atrybutów zakotwiczenia.