Эта тема на forum.dklab.ru


mrMoRiC: Функция xml_parse_into_struct() парсит до первой русской буквы
Есть кусок кода, который отлично работает на локалке, работал на другом хостинге, но после переезда стал тупить:


$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, trim(&$contents), $xml_values);
xml_parser_free($parser);
if(!$xml_values){
echo xml_get_error_code($parser);
return;//Hmm...
}
else {
//Для отладки
print_r( $xml_values ); //БАГ !
}

Итак, при выводе на странице вижу, что парсинг произошёл только частично (те теги, в которых был русский текст не распарсились). Думаю, что проблема связана с кодировкой.

Информация:
1). Читаю xml в формать windows-1251
2). Ошибки в .htaccess были включены
3). Memory Limit и Time Execution в предосттачном объёме.

Так почему же так происходит?
Михаил Ошер:
проверь входную кодировку ( файла )
mrMoRiC:
Кодировка xml-файла: windows-1251
Заголовок в xml-файле: <?xml version="1.0" encoding="windows-1251"?>
Кодировка файла с php-парсером: windows-1251
bæv:
Miraage, http://forum.dklab.ru/about/todo/PravilaEtogoForuma-ProchitayteObyazatelno.html — на форуме принято обращение «на Вы».


mrMoRiC, спросите у хостера, установлена ли на сервере локаль win1251.
Anonymous:
bæv
Ок сейчас сделаю запрос, но ведь сам сайт нормально отображается (русский шрифт). Если бы локаль была не установлена, то это влияло бы не только на xml. Или я не прав?
mrMoRiC:
Под Гостем я отвечал.

Решил, чтобы было более понятно привести скрины. На них я делаю вывод xml, преобразованного в массив. Видно, что на новом хостинге функция не учитывает русский текст и возвращает только те теги, которые содержат цифры и английский текст.
dimagolov:
если верить ману, то XML Parser поддерживает аж 3 кодировки, из них 2 однобайтных и 1251 там нету. кроме того, кодировка автоопределяется по BOM, а не по всяким левым заголовкам.
mrMoRiC:
Значит, добавил я преобразование к UTF-8 контента перед вызовом функции xml_parse_into_struct()
Т.е.:

$contents = iconv( 'WINDOWS-1251', 'UTF-8', $contents );
// other code here
xml_parse_into_struct($parser, trim( &$contents ), $xml_values);


На внехе и на локалке вывод стал одинаковым. Выводит всё, но в кроказябрах и с ошибкой:

Warning: xml_parse_into_struct() : input conversion failed due to input error, bytes 0x98 0xD0 0xBD 0xD0
dimagolov:
во-первых, смотреть что получается в $contents пробовали?
во-вторых, там заголовок encoding="windows-1251" по логике становится лишним
в-третьих, XML Parser определяет кодировку по BOM, и их в $contents точно нету, нужно добавлять.
Anonymous:
в-третьих, XML Parser определяет кодировку по BOM, и их в $contents точно нету, нужно добавлять
Если можно, то пример кода. Не понимаю как "добавить" этот BOM в $contents?
dimagolov:
конкатенацией:
$BOM="..."; // тут вставить нужные байтики, гугл рулит
$contents = $BOM.iconv( 'WINDOWS-1251', 'UTF-8', $contents );
mrMoRiC:

$BOM = chr( 239 ) . chr( 187 ) . chr( 191 );
$contents = $BOM . iconv( 'WINDOWS-1251', 'UTF-8', $contents );

Нет, такая же ошибка выводится:

Warning: xml_parse_into_struct() : input conversion failed due to input error, bytes 0x98 0xD0 0xBD 0xD0
mrMoRiC:
Победил! :)


$contents = iconv( 'WINDOWS-1251', 'UTF-8', $contents );
$contents = str_replace ( 'windows-1251', 'utf-8', $contents );
$parser = xml_parser_create( 'UTF-8' );
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, trim( &$contents ), $xml_values);
xml_parser_free($parser);


В итоге получим $xml_values в UTF-8. Если у вас (также как у меня кодировка самой страницы windows-1251), то
дополнительно придётся все элементы $xml_values перекодировать в windows-1251.

Пользуйтесь на здоровье! :)

Эта тема на forum.dklab.ru