Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [XML] DOM i SimpleXML
Forum PHP.pl > Forum > PHP
taktu
Pytanie: jak dobrać się do pliku rss który publikuje interia?

plik: http://kanaly.rss.interia.pl/turystyka.xml

problem: kodowanie pliku to UTF-8, ale znalazły się w nim słowackie znaki które w UTF już niestety nie są.

Do tej pory używałem:

  1. $rssObject = simplexml_load_string( $address, 'SimpleXMLElement', LIBXML_NOCDATA );


Co dało błędy:
  1. Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 1: parser error : Start tag expected, '<' not found in
  2. Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in


Więc spróbowałem:

  1. $xmlDoc = new DOMDocument();
  2. $xmlDoc->load( $address );


No i błąd:

  1. Warning: DOMDocument::load() [function.DOMDocument-load]: Input is not proper UTF-8, indicate encoding ! Bytes: 0xB9 0x69 0x6E 0x73 in http://kanaly.rss.interia.pl/turystyka.xml, line: 94 in


Błąd ominąłem w simplexml_load_string:
  1.  
  2. $file = file_get_contents( $address );
  3.  
  4. $content = mb_convert_encoding( $content, 'UTF-8', mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true));
  5. //lub
  6. $content = iconv( mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true), 'UTF-8', $content );
  7. //efekt ten sam
  8.  
  9. if ($rssObject = simplexml_load_string( $content, 'SimpleXMLElement', LIBXML_NOCDATA ) ){
  10. // ...
  11. }

i otrzymałem
  1. ?šwiÄ?ta Bo??ego Narodzenia we W??oszech sÄ? obchodzone na wiele r?questionmark.gif?nych sposob??w


Czy ktoś ma większe doświadczenie w kodowaniach? Zależy mi na tym aby tekst był czytelny, słowackie znaki mogą być wykrzaczone. Wszelka pomoc mile widziana.
byqu
Spróbuj konwertować polskie znaczki według ich zapisu szesnastkowego:
  1. <?php
  2. $chars = array(
  3. "\xb9" => "\xc4\x85", "\xa5" => "\xc4\x84", "\xe6" => "\xc4\x87", "\xc6" => "\xc4\x86",
  4. "\xea" => "\xc4\x99", "\xca" => "\xc4\x98", "\xb3" => "\xc5\x82", "\xa3" => "\xc5\x81",
  5. "\xf3" => "\xc3\xb3", "\xd3" => "\xc3\x93", "\x9c" => "\xc5\x9b", "\x8c" => "\xc5\x9a",
  6. "\x9f" => "\xc5\xbc", "\xaf" => "\xc5\xbb", "\xbf" => "\xc5\xba", "\xac" => "\xc5\xb9",
  7. "\xf1" => "\xc5\x84", "\xd1" => "\xc5\x83",
  8.  
  9. "\xb1" => "\xc4\x85", "\xa1" => "\xc4\x84", "\xe6" => "\xc4\x87", "\xc6" => "\xc4\x86",
  10. "\xea" => "\xc4\x99", "\xca" => "\xc4\x98", "\xb3" => "\xc5\x82", "\xa3" => "\xc5\x81",
  11. "\xf3" => "\xc3\xb3", "\xd3" => "\xc3\x93", "\xb6" => "\xc5\x9b", "\xa6" => "\xc5\x9a",
  12. "\xbc" => "\xc5\xbc", "\xac" => "\xc5\xbb", "\xbf" => "\xc5\xba", "\xaf" => "\xc5\xb9",
  13. "\xf1" => "\xc5\x84", "\xd1" => "\xc5\x83",
  14. );
  15. $string = strtr($string, $chars);
  16. ?>


Jakby któryś znak zamieniało na nie ten, to zobacz na tablicę http://eazu.pl/index.php/zamiana-polskich-...e-odpowiedniki/ , bo to z niej utworzyłem tę.
taktu
Ciekawy pomysł ale niestety nie pomoże, znaki które wysypują plik są czesko/słowackie np. "Skoru?ina", "Skoru?inske vrchy", "?trbské Pleso". Poza tym jest to kanał turystyka więc równie dobrze autorzy mogą wkleić nazwy niemieckie, arabskie czy jakiekolwiek inne.

W internetowych czytnikach zauważyłem 2 podejścia:
- odczytanie całego pliku i wyświetlenie informacji w taki sposób, w jaki widać po odpaleniu pliku xml w przeglądarce,
- odczytywanie pliku po kawałku, wysypuje się kiedy ma odczytać informację z błędnym kodowaniem,

Zaczynam dochodzić do wniosku że jedynym sposobem jest napisanie własnej klasy do obsługi xml, alby to w końcu zadziałało. Choć tak naprawdę, to powinien być problem interii żeby trzymała się standardów.

edit:

Znalazłem klasę która odczytuje plik kawałkami, wysypuje się gdy trafi na nieodpowiednie kodowanie, ale to i tak lepsze niż nic smile.gif

http://articles.sitepoint.com/article/php-...parsing-rss-1-0
zegarek84
skoro wiesz jakie to kodowanie ma być to pozostaje Ci tylko je wymusić - możesz to zrobić na 2 sposoby, krótkim kodem a mało wydajnym który odradzam tylko wskazuję drogę do przemyśleń:

  1. $convmap = array(0xFF, 0x2FFFF, 0, 0xFFFF);
  2. $text=file_get_contents('http://kanaly.rss.interia.pl/turystyka.xml');
  3. $text=mb_decode_numericentity(mb_encode_numericentity ($text, $convmap, 'UTF-8'), $convmap, 'UTF-8');
  4. $doc = new DOMDocument();
  5. $doc->loadXML($text);
  6. echo $doc->saveXML();



lub idea taka sama aczkolwiek kod dłuższy i w sumie pozostawi się encje dla innych znaków - w niczym w końcu to nie przeszkadza:

  1. function utf2html ($utf2html_string)
  2. {
  3. $f = 0xffff;
  4. $convmap = array(
  5. /* <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1//EN//HTML">
  6.   %HTMLlat1; */
  7. 160, 255, 0, $f,
  8. /* <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols//EN//HTML">
  9.   %HTMLsymbol; */
  10. 402, 402, 0, $f, 913, 929, 0, $f, 931, 937, 0, $f,
  11. 945, 969, 0, $f, 977, 978, 0, $f, 982, 982, 0, $f,
  12. 8226, 8226, 0, $f, 8230, 8230, 0, $f, 8242, 8243, 0, $f,
  13. 8254, 8254, 0, $f, 8260, 8260, 0, $f, 8465, 8465, 0, $f,
  14. 8472, 8472, 0, $f, 8476, 8476, 0, $f, 8482, 8482, 0, $f,
  15. 8501, 8501, 0, $f, 8592, 8596, 0, $f, 8629, 8629, 0, $f,
  16. 8656, 8660, 0, $f, 8704, 8704, 0, $f, 8706, 8707, 0, $f,
  17. 8709, 8709, 0, $f, 8711, 8713, 0, $f, 8715, 8715, 0, $f,
  18. 8719, 8719, 0, $f, 8721, 8722, 0, $f, 8727, 8727, 0, $f,
  19. 8730, 8730, 0, $f, 8733, 8734, 0, $f, 8736, 8736, 0, $f,
  20. 8743, 8747, 0, $f, 8756, 8756, 0, $f, 8764, 8764, 0, $f,
  21. 8773, 8773, 0, $f, 8776, 8776, 0, $f, 8800, 8801, 0, $f,
  22. 8804, 8805, 0, $f, 8834, 8836, 0, $f, 8838, 8839, 0, $f,
  23. 8853, 8853, 0, $f, 8855, 8855, 0, $f, 8869, 8869, 0, $f,
  24. 8901, 8901, 0, $f, 8968, 8971, 0, $f, 9001, 9002, 0, $f,
  25. 9674, 9674, 0, $f, 9824, 9824, 0, $f, 9827, 9827, 0, $f,
  26. 9829, 9830, 0, $f,
  27. /* <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special//EN//HTML">
  28.   %HTMLspecial; */
  29. /* These ones are excluded to enable HTML: 34, 38, 60, 62 */
  30. 338, 339, 0, $f, 352, 353, 0, $f, 376, 376, 0, $f,
  31. 710, 710, 0, $f, 732, 732, 0, $f, 8194, 8195, 0, $f,
  32. 8201, 8201, 0, $f, 8204, 8207, 0, $f, 8211, 8212, 0, $f,
  33. 8216, 8218, 0, $f, 8218, 8218, 0, $f, 8220, 8222, 0, $f,
  34. 8224, 8225, 0, $f, 8240, 8240, 0, $f, 8249, 8250, 0, $f,
  35. 8364, 8364, 0, $f);
  36.  
  37. return mb_encode_numericentity($utf2html_string, $convmap, 'UTF-8');
  38. }
  39.  
  40. $convmap = array(0xFF, 0x2FFFF, 0, 0xFFFF);
  41. $text=file_get_contents('http://kanaly.rss.interia.pl/turystyka.xml');
  42. $text=utf2html($text);
  43. $doc = new DOMDocument();
  44. $doc->loadXML($text);
  45. echo $doc->saveXML();


jednak jeszcze zamiast funkcji file_get_contents radziłbym używać curl'a z włączoną opcją gzip coby mniej na łączu było transferu lub fsockopen - tyle, że tutaj trzeba sprawdzać jeszcze nagłówki przychodzące i jeśli jest skompresowane gzip'em to samemu dekompresować...

taktu
Dzięki za odpowiedź, rzeczywiście zadziałało tak jak trzeba.

Dodam tylko na koniec że nie warto podpowiadać funkcji mb_detect_encoding() jakich kodowań ma szukać. Okazało się że z podpowiedziami źle wykrywała kodowanie..


  1. //wystarczyło linię:
  2.  
  3. $content = mb_convert_encoding( $content, 'UTF-8', mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true));
  4.  
  5. //zamienic na:
  6.  
  7.  
  8. $content = mb_convert_encoding( $content, 'UTF-8', mb_detect_encoding($content));


i działa równie dobrze.
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.