- Filtrowanie i oczyszczanie ciągu w kodowaniu z rodziny ISO 8859
- htmlentities dla wszystkich kodowań ISO 8859 + encje numeryczne
- Dekodowanie encji html / xml
Otóż w Polsce do tej pory często wykorzystywanym kodowaniem jest ISO-8859-2 ale czasy swojej świetności ma już dawno za sobą. Było używane wszędzie tam gdzie nie było obsługi polskich znaków a chciano je wprowadzić. Dzisiaj mamy Unicode i mnóstwo kodowań które je obsługuje.
Każde kodowanie z rodziny ISO 8859 jest zgodne z kodowaniem ASCII lub jak kto woli bazuje na nim, innymi słowy pierwsze 127 (licząc od zera 128, 0x00 – 0x7F) znaków kontrolnych i drukowanych się pokrywa.
Filtrowanie każdego kodowania z rodziny ISO/IEC 8859
Otóż każde z tych kodowań zawiera mnóstwo znaków kontrolnych oraz nieużywanych pozycji. Funkcja clean_iso_8859()
oczyszcza właśnie ciąg z tych niepotrzebnych znaków, przyjmuje dwie wartości, pierwsza to ciąg do oczyszczenia a druga to nazwa kodowania w formacie iso-8859-X
gdzie X to numer kodowania jakie chcemy oczyścić. Otrzymamy gotowy ciąg z którym możemy dalej robić co nam się żywnie podoba.
Zamienia lub usuwa:
SOFT HYPHEN
naHYPHEN-MINUS
(dywiz na minusa, można zmienić; znak dywizu nie obsługuje chyba żadna przeglądarka)NO-BREAK SPACE
naSPACE
(niełamliwą spację na zwykła spację, można zmienić)- Każde wystąpienie powyżej 2 spacji na pojedynczą
Usuwa znaki kontrolne oraz nieużywane pozycje(zależnie od wybranego kodowania) oprócz:
- HORIZONTAL TABULATION (\t|\x09)
- LINE FEED (\n|\x0A)
- CARRIAGE RETURN (\r|\x0D)
- SPACE ( |\x20)
Nie każde kodowanie zawiera dodatkowe pozycje do usunięcia, jak na razie zawierają je:
- iso-8859-3
- iso-8859-6
- iso-8859-7
- iso-8859-8
- iso-8859-11 (tutaj nie ma znaku dywizu)
I tylko w wypadku filtrowania tych wyżej wymienionych kodowań należy podawać drugi parametr dla tej funkcji.
function clean_iso_8859($string, $encoding = NULL) { // clean_iso_8859() by tosiek - https://tosiek.pl/ if (!isset($string)) { trigger_error('clean_iso_8859() first parameter cannot be empty', E_USER_WARNING); return NULL; } else { settype($string, 'string'); if ($encoding != NULL) { settype($encoding, 'string'); $encoding = strtolower($encoding); } $pattern = array( 0 => "\xAD", // SOFT HYPHEN to HYPHEN-MINUS 1 => "\xA0", // NO-BREAK SPACE to SPACE ); $replacement = array( 0 => "\x2D", 1 => "\x20", ); //Remove unused positions in encodings switch ($encoding) { case NULL: break; case 'iso-8859-1': break; case 'iso-8859-2': break; case 'iso-8859-3': $string = preg_replace('/[\\xA5\\xAE\\xBE\\xC3\\xD0\\xE3\\xF0]/', '', $string); break; case 'iso-8859-4': break; case 'iso-8859-5': break; case 'iso-8859-6': $string = preg_replace('/[\\xA1\\xA2\\xA3\\xA5\\xA6\\xA7\\xA8\\xA9\\xAA\\xAB\\xAE\\xAF\\xB0\\xB1\\xB2\\xB3\\xB4\\xB5\\xB6\\xB7\\xB8\\xB9\\xBA\\xBC\\xBD\\xBE\\xC0\\xDB\\xDC\\xDD\\xDE\\xDF\\xF3\\xF4\\xF5\\xF6\\xF7\\xF8\\xF9\\xFA\\xFB\\xFC\\xFD\\xFE\\xFF]/', '', $string); break; case 'iso-8859-7': $string = preg_replace('/[\\xAE\\xD2\\xFF]/', '', $string); break; case 'iso-8859-8': $string = preg_replace('/[\\xA1\\xBF\\xC0\\xC1\\xC2\\xC3\\xC4\\xC5\\xC6\\xC7\\xC8\\xC9\\xCA\\xCB\\xCC\\xCD\\xCE\\xCF\\xD0\\xD1\\xD2\\xD3\\xD4\\xD5\\xD6\\xD7\\xD8\\xD9\\xDA\\xDB\\xDC\\xDD\\xDE\\xFB\\xFC\\xFF]/', '', $string); break; case 'iso-8859-9': break; case 'iso-8859-10': break; case 'iso-8859-11': unset($pattern[0], $replacement[0]); //Do not replace SOFT HYPHEN because there is THAI CHARACTER YO YING $string = preg_replace('/[\\xDB\\xDC\\xDD\\xDE\\xFC\\xFD\\xFE\\xFF]/', '', $string); break; case 'iso-8859-12': trigger_error('clean_iso_8859() character set \'iso-8859-12\' not exists', E_USER_WARNING); return NULL; break; case 'iso-8859-13': break; case 'iso-8859-14': break; case 'iso-8859-15': break; case 'iso-8859-16': break; default: trigger_error('clean_iso_8859() unexpected character encoding in parameter 2', E_USER_WARNING); return NULL; } //Replace others ALL ISO/IEC 8859 $string = str_replace($pattern, $replacement, $string); $string = preg_replace('/\\x20{2,}/', "\x20", $string); //Replace more then one SPACE to once /*********ALL ISO/IEC 8859********* Remove <control> characters: * NULL (\x00) - BACKSPACE (\x08) * VERTICAL TABULATION (\x0B) * FORM FEED (\x0C) * SHIFT OUT (\x0E) - UNIT SEPARATOR (\x1F) * DELETE (\x7F) - <control> (\x9F) Without: - HORIZONTAL TABULATION (\t|\x09) - LINE FEED (\n|\x0A) - CARRIAGE RETURN (\r|\x0D) - SPACE ( |\x20) *********ALL ISO/IEC 8859*********/ $string = preg_replace('/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x9F]/', '', $string); return $string; } } |
htmlentities ISO/IEC 8859
Otóż standardowa funkcja htmlentities()
nie obsługuje żadnego kodowani z rodziny ISO oprócz latin1 i latin9. Dla reszty kodowań także da się zapisać każdy znak za pomocą encji ale niestety nie za pomocą encji symbolicznych np. ó co odpowiada znakowi ó. Dlatego, żeby to wszystko ujednolicić i nie mieszać różnych rodzajów encji zdecydowałem się zapisać wszystko za pomocą encji numerycznych to jest ź odpowiada znak ź. Tablice z encjami należy umieścić w skrypcie gdzieś przed funkcją (podzieliłem je także na pojedyncze kodowania):
- tablica z encjami dla wszystkich kodowań ISO
- htmlentities iso-8859-1
- htmlentities iso-8859-2
- htmlentities iso-8859-3
- htmlentities iso-8859-4
- htmlentities iso-8859-5
- htmlentities iso-8859-6
- htmlentities iso-8859-7
- htmlentities iso-8859-8
- htmlentities iso-8859-9
- htmlentities iso-8859-10
- htmlentities iso-8859-11
- htmlentities iso-8859-13
- htmlentities iso-8859-14
- htmlentities iso-8859-15
- htmlentities iso-8859-16
Funkcja htmlentities_iso()
przyjmuje takie same wartości (dla kodowania należy podawać w formacie iso-8859-X
gdzie X to numer kodowania) jak oryginalna htmlentities()
. Wymaga aby wcześniej skrypcie PHP były podane wyżej wymienione tablice, albo tylko te, z których będziemy korzystać. Nie mogę dać gwarancji czy działa w 100% z ustawionym $double_encode = false – wymagałoby testu na wszystkich istniejących encjach czy ich nie zamienia powtórnie – powiem tyle: u mnie działa ; ) Jak na razie nie jestem w stanie znaleźć jakiegoś praktycznego zastosowania tych dwóch funkcji.
function htmlentities_iso($string, $flags = ENT_COMPAT, $charset = 'iso-8859-1', $double_encode = true) { // htmlentities_iso() by tosiek - https://tosiek.pl/ if (!isset($string)) { trigger_error('htmlentities_iso() expects at least 1 parameter', E_USER_WARNING); return NULL; } else { settype($string, 'string'); settype($flags, 'string'); settype($charset, 'string'); settype($double_encode, 'boolean'); $charset = strtolower($charset); //Encode existing entities? if ($double_encode == true) { $string = str_replace("\x26", '&', $string); // or & } else { $string = preg_replace('/&(?!(((#|#X|#x)+[a-fA-F0-9]{1,4})|[a-zA-Z]{1,10}[0-9]{0,3})+;)/', '&', $string, -1); // or & } //Get html translation table switch ($charset) { case 'iso-8859-1': global $trans_iso_8859_1; $trans = $trans_iso_8859_1; break; case 'iso-8859-2': global $trans_iso_8859_2; $trans = $trans_iso_8859_2; break; case 'iso-8859-3': global $trans_iso_8859_3; $trans = $trans_iso_8859_3; break; case 'iso-8859-4': global $trans_iso_8859_4; $trans = $trans_iso_8859_4; break; case 'iso-8859-5': global $trans_iso_8859_5; $trans = $trans_iso_8859_5; break; case 'iso-8859-6': global $trans_iso_8859_6; $trans = $trans_iso_8859_6; break; case 'iso-8859-7': global $trans_iso_8859_7; $trans = $trans_iso_8859_7; break; case 'iso-8859-8': global $trans_iso_8859_8; $trans = $trans_iso_8859_8; break; case 'iso-8859-9': global $trans_iso_8859_9; $trans = $trans_iso_8859_9; break; case 'iso-8859-10': global $trans_iso_8859_10; $trans = $trans_iso_8859_10; break; case 'iso-8859-11': global $trans_iso_8859_11; $trans = $trans_iso_8859_11; break; case 'iso-8859-12': trigger_error('htmlentities_iso() character set \'iso-8859-12\' not exists, assuming iso-8859-1', E_USER_WARNING); global $trans_iso_8859_1; $trans = $trans_iso_8859_1; break; case 'iso-8859-13': global $trans_iso_8859_13; $trans = $trans_iso_8859_13; break; case 'iso-8859-14': global $trans_iso_8859_14; $trans = $trans_iso_8859_14; break; case 'iso-8859-15': global $trans_iso_8859_15; $trans = $trans_iso_8859_15; break; case 'iso-8859-16': global $trans_iso_8859_16; $trans = $trans_iso_8859_16; break; default: trigger_error('htmlentities_iso() charset \'' . htmlentities($charset, ENT_QUOTES, 'UTF-8', true) . '\' not supported, assuming iso-8859-1', E_USER_WARNING); global $trans_iso_8859_1; $trans = $trans_iso_8859_1; } //Set quote style switch ($flags) { case '0': break; case '3': $trans["\x27"] = '''; case '2': $trans["\x22"] = '"'; // or " break; default: trigger_error('htmlentities_iso() expects parameter 2 to be long', E_USER_WARNING); return NULL; } $trans["\x3C"] = '<'; // or < $trans["\x3E"] = '>'; // or > $search = array_keys($trans); $replace = array_values($trans); $string = str_replace($search, $replace, $string); return $string; } } |
html_entity_decode_iso
I tutaj mam dylemat czy opierać się także na tablicach czy po prostu zamieniać każdą możliwą encję wyrażeniami regularnymi. Przy automatycznym dekodowaniu encji mógłby być problem ze znakami – tak czy siak trzeba by było skonwertować więc znowu się narzuca użycie tablic… Jak na razie w manualu jest podobna funkcja – wystarczy użyć tablic wyżej.
Funkcja html_entity_decode_iso()
przyjmuje identyczne argumenty jak oryginalna html_entity_decode() tyle, że kodowanie należy podawać w formacie iso-8859-X
gdzie X to numer kodowania. Dodałem także czwarty parametr – odpowiada on za podwójne dekodowanie encji tj. jeżeli poprzednio zakodowało encję podwójnie czyli zamiast początkowego & (ampersand) wsadziło encję: & to po ustawieniu 4 parametru na true
funkcja najpierw podmieni podwójnie zakodowane encje a później te z tablic dla właściwego kodowania np. &#160; lub &#160; bądź &#160; najpierw zamieni początkowa encję znaku ampersand na odpowiedni znak   a potem zgodnie z tablicą na wartość “\xa0”.
function html_entity_decode_iso($string, $flags = ENT_COMPAT, $charset = 'iso-8859-1', $double_encode = false) { if (!isset($string)) { trigger_error('html_entity_decode_iso() expects at least 1 parameter', E_USER_WARNING); return NULL; } else { settype($string, 'string'); settype($flags, 'string'); settype($charset, 'string'); settype($double_encode, 'boolean'); $charset = strtolower($charset); //Decode multi encoded entities if ($double_encode == true) { $string = str_replace('&', '&', $string); $string = preg_replace('/&#(0|x|X)*?(38|26)+;/', '&', $string); } //Get html translation table switch ($charset) { case 'iso-8859-1': global $trans_iso_8859_1; $trans = $trans_iso_8859_1; break; case 'iso-8859-2': global $trans_iso_8859_2; $trans = $trans_iso_8859_2; break; case 'iso-8859-3': global $trans_iso_8859_3; $trans = $trans_iso_8859_3; break; case 'iso-8859-4': global $trans_iso_8859_4; $trans = $trans_iso_8859_4; break; case 'iso-8859-5': global $trans_iso_8859_5; $trans = $trans_iso_8859_5; break; case 'iso-8859-6': global $trans_iso_8859_6; $trans = $trans_iso_8859_6; break; case 'iso-8859-7': global $trans_iso_8859_7; $trans = $trans_iso_8859_7; break; case 'iso-8859-8': global $trans_iso_8859_8; $trans = $trans_iso_8859_8; break; case 'iso-8859-9': global $trans_iso_8859_9; $trans = $trans_iso_8859_9; break; case 'iso-8859-10': global $trans_iso_8859_10; $trans = $trans_iso_8859_10; break; case 'iso-8859-11': global $trans_iso_8859_11; $trans = $trans_iso_8859_11; break; case 'iso-8859-12': trigger_error('html_entity_decode_iso() character set \'iso-8859-12\' not exists, assuming iso-8859-1', E_USER_WARNING); global $trans_iso_8859_1; $trans = $trans_iso_8859_1; break; case 'iso-8859-13': global $trans_iso_8859_13; $trans = $trans_iso_8859_13; break; case 'iso-8859-14': global $trans_iso_8859_14; $trans = $trans_iso_8859_14; break; case 'iso-8859-15': global $trans_iso_8859_15; $trans = $trans_iso_8859_15; break; case 'iso-8859-16': global $trans_iso_8859_16; $trans = $trans_iso_8859_16; break; default: trigger_error('html_entity_decode_iso() charset \'' . htmlentities($charset, ENT_QUOTES, 'UTF-8', true) . '\' not supported, assuming iso-8859-1', E_USER_WARNING); global $trans_iso_8859_1; $trans = $trans_iso_8859_1; } //Set quote style switch ($flags) { case '0': break; case '3': $trans["\x27"] = '''; case '2': $trans["\x22"] = '"'; // or " break; default: trigger_error('html_entity_decode_iso() expects parameter 2 to be long', E_USER_WARNING); return NULL; } $trans["\x3C"] = '<'; // or < $trans["\x3E"] = '>'; // or > $search = array_values($trans); $replace = array_keys($trans); $string = str_replace($search, $replace, $string); return $string; } } |
Najnowsze komentarze