Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Wyrażenia regularne, kolorowanie składni html
Forum PHP.pl > Forum > Przedszkole
Shili
Witam.
Od jakiegoś czasu męczę się z kolorowaniem składni języka html. Na wstępie chciałabym powiedzieć, że wszystkie gotowe rozwiązania, jakie widziałam nie rozwiązują mojego problemu, a jeśli istnieje jakieś, które rozwiązuje z chęcią się zapoznam winksmiley.jpg

Chciałabym pokolorować kod html w ten sposób, że błędne tagi (na razie jedynie błędnie zamknięte) nie są kolorowane wcale, a wyświetlane jako zwykły tekst. Wyglądać ma to tak:

Aktualnie doszłam do wyświetlenia czegoś w tym stylu i kompletnie nie mam pojęcia jak ruszyć dalej i usunąć błędne wyświetlanie atrybutów.

Linia odpowiedzialna za kolorowanie wartości atrybutów i przykładowy (inny trochę niż na obrazkach, bo z kolorowaniem samych wartości atryburów i krótszy) kod:
  1. <?php
  2. $tekst = "<img src=\"alt.gif\" alt=\"kwa\"<span alt=\"lala\"></span>";
  3. $tekst = preg_replace('/((.*?))(=\")(.*?)(\").*?/', '${1}${3}[span style="color: violet;"]${4}[/span]${5}', $tekst);
  4. $tekst = str_replace('<', '&lt;', $tekst);
  5. $tekst = str_replace('>', '&gt;', $tekst);
  6. $tekst = str_replace('[', '<', $tekst);
  7. $tekst = str_replace(']', '>', $tekst);
  8. echo $tekst;
  9. ?>


Od razu mówię - tak, wiem, że str_replace mogę wziąć w tablicę i z pewnością tak zrobię. Wiem, że na tagi mogą być zamienione znaki wprowadzone przez użytkownika. Style zamienią się w przyszłości na klasy, ogólnie jest to jedynie zarys i z pewnością będzie poprawiony, tak samo jak będę myśleć nad bardziej efektywnymi sposobami przetwarzania i co ważniejsze bezpieczniejszymi, na dzień dzisiejszy chodzi mi jedynie o wyrażenie regularne.

Myślałam jeszcze nad automatycznym domykaniem niezamkniętych znaczników, ale to nie jest rozwiązanie, ku któremu chciałabym się skłaniać, wolałabym, żeby nieprawidłowo sformułowane tagi były traktowane po prostu jako zwykły tekst.

Próbowałam sprawdzać, czy ciąg kończy się znacznikiem zamykającym/otwierającym, ale działa to u mnie poprawnie tylko w przypadku jednego atrybutu. Jeśli to możliwe poprosiłabym o naprowadzenie na poprawny tok myślenia z tego względu, że wyrażenia regularne (nad czym ubolewam) nigdy nie były i nie są nadal moją mocną stroną.

Z góry dziękuję ^^
Kicok
Pobaw się funkcją preg_replace_callback" title="Zobacz w manualu PHP" target="_manual:
( [EDIT] Poprawiony kod )
  1. <?php
  2.  
  3. $tekst = '<img src="alt.gif" alt="kwa"
  4. <!-- A tutaj jest komentarz -->
  5. <div style="background: none; border: 1px solid black;" width = '500px'>
  6. Byla sobie zabka <span class=small>mala i &amp; jakas encja &copy;</span>
  7. </div>';
  8.  
  9.  
  10. function koloruj( $znalezione )
  11. {
  12. static $tagiHTML = array( 'a', 'span', 'div', 'p', /* (...) */ );
  13.  
  14.  
  15. // Komentarz
  16. if( $znalezione[1] == '!--' ) {
  17. return '<span style="color:silver;">&lt;' . htmlspecialchars( $znalezione[1].$znalezione[2] ) . '&gt;</span>';
  18. }
  19.  
  20. // Tag HTML?
  21. if( in_array( strtolower( ltrim( $znalezione[1], '/' ) ), $tagiHTML ) ) {
  22. return '<span style="color:blue;">&lt;' . $znalezione[1] . '</span>' . preg_replace( '/([a-z0-9:_]+s*=s*)(&quot;|')?(.*?)((?(2)2|(s|$)))/i', '<span style="color:green;">$1$2</span><span style="color:violet;">$3</span><span style="color:green;">$4</span>', $znalezione[2] ) . '<span style="color:blue;">&gt;</span>';
  23. }
  24.  
  25.  
  26. // Cała reszta?
  27. return htmlspecialchars( $znalezione[0] );
  28. }
  29.  
  30. $tekst = htmlspecialchars( $tekst );
  31.  
  32. // Encje
  33. $tekst = preg_replace( '/(&amp;[a-z0-9#]+;)/', '<span style="color:yellow;">$1</span>', $tekst );
  34.  
  35. // Kolorowanie tagów
  36. $tekst = preg_replace_callback( '/&lt;(/?S+)((?:(?:(&quot;|').*?3)|.(?!(?:l|g)t;))*?)&gt;/', 'koloruj', $tekst );
  37. echo nl2br( $tekst );
  38.  
  39. ?>




PS. Wiem że te wyrażenia są zabójcze, ale chyba nie da się tego napisać prosto ;]

(?: ... ) - To samo co zwykły nawias okrągły, ale wartość nie jest wyciągana do zmiennej $1, $2, itd.
(\\/?\\S+) - Może ale nie musi występować ukośnik, a potem co najmniej 1 znak "drukowalny" (nie biały)
(&quot;|\').*?\\3 - Cudzysłów albo apostrof, a potem dowolne znaki aż do napotkania cudzysłowu (jeśli na początku był cudzysłów) lub apostrofu (jeśli na początku był apostrof). Po prostu pod \\3 jest to, co zostało dopasowane do trzeciego nawiasu
(?!(?:l|g)t;)) - (?! to przewidywanie negatywne. Działa podobnie jak klasa znaków [^...], ale nie "zjada" znaków. Całość oznacza, że w danym miejscu NIE MOŻE wystąpić "lt;" lub "gt;"
(&quot;|\')?(.*?)((?(2)\\2|\\s|$))) - (?(condition)if_true|if_false) to tzw. dopasowanie warunkowe. Całość oznacza: Spróbuj dopasować cudzysłów lub apostrof, ale jak się nie uda to nic nie szkodzi. Potem dowolne znaki. A następnie warunek: Jeśli pod 2 nawiasem zostało coś dopasowane, to wstaw tam wartość dopasowania z drugiego nawiasu, a jeżeli nie, to wstaw (\\s|$). Czyli jeśli na początku był cudzysłów, do dopasuj znaki aż do napotkania cudzysłowu. Jeśli na początku był apostrof, to dopasuj aż do napotkania apostrofu. A jeśli na początku nie było nic, to dopasuj aż do napotkania pierwszego białego znaku lub końca tekstu (zależy co wystąpi najpierw ;] )
Shili
Ok, dzięki za sugestię i poświęcony czas i kod smile.gif Z funkcją jeszcze nie zapoznałam się bliżej, ale pewnie czas już najwyższy tongue.gif

@edit
Kurcze, dzięki biggrin.gif
Szkoda, że nie mogę Ci postawić plusa drugi raz, bo zdecydowanie wyjaśnienie na niego zasługuje ^^
cbagov
A ja bym jednak probowal wrocic i skrocic, sprawdz to:


//$tekst = " <img src=\"alt.gif\" alt=\"kwa\"<span alt=\"lala\"></span>";


$tekst="<table border=\"0\" cellpadding=\"1\" cellspacing=\"0\" width=\"100%\" >

<tr> <td align=\"center\" valign=\"top\" <table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">

<tr></tr>";



$_tmp_preg_search = '/"([^"\<>]*(?:\\.[^"\<>]*)*)"([^<"]*?)(?=[^<]*?>)/';

$_tmp_preg_replace = ' [span style="color:red;font-weight:bold"]"${1}"[/span]${2}';


$tekst = preg_replace( $_tmp_preg_search, $_tmp_preg_replace, $tekst);

$tekst = str_replace('<', '&lt;', $tekst);

$tekst = str_replace('>', '&gt;', $tekst);

$tekst = str_replace('[', '<', $tekst);

$tekst = str_replace(']', '>', $tekst);


echo $tekst;

exit;

[/color]

[color="#000040"]Sprawdzilem na paru dluzszych zrodlach i chodzi, tyle, ze wiadomo w regexp sa zawsze 2 wyjscia: 1. da sie inaczej, 2. moze nie dzialac w specyficznych okolicznosciach winksmiley.jpg
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.