убрать левые символы из XML документа

demon_mhm

Новичок
убрать левые символы из XML документа

Есть такая проблема. Приходит сторонний XML-файл,достаточно объемный. Но, местами там попадаются какие-то кривые символы типа копирайтов или траейдмарков и ХЗ чего вообще, и парсинг документа, естественно валится. Кто-нибудь может подсказать, как программно убрать всю левоту из документа? Тоесть оставить только русские-английские буквы, знаки пунктуации, теги и пр... Понятно, что надо прогонять через регулярку, есть спецы по регулярным выражениям? Помогите пожалуйста или хоть ткните носом где поискать?
 

neko

tеam neko
я думаю надо этот документ прочесть в правильной кодировке
 

demon_mhm

Новичок
нет, с кодировкой всё в порядке, правда, скорее всего, попадаются куски, взятые из документов в другой кодировке. Я собираюсь ими пренебречь. Перефразируя свой вопрос, спрошу: Как убрать из документа символы,которые не могут быть распознаны в текущей кодировке?
 

neko

tеam neko
зависит от того какая кодировка является "текущей".
 

Alexandre

PHPПенсионер
demon_mhm это глупо прогонять через регулярку довольно большой текст.

str_replace() и strtr().
 

demon_mhm

Новичок
Alexandre, согласен с Вами, только вот какое условие для замены использовать? В принципе, размер текста не критичен, так как документ парсится всего один раз, при получении, разбирается на классы и эти классы кешируются. В дальнейшем работаю с ними. Регулярки решил использовать, т.к. они дают больше гибкости.
 

neko

tеam neko
как можно знать какое условие замены использовать если до сих пор неясно о каких конкретно символах и кодировках идет речь?

функции "убрать всю левоту" в php нет.

-~{}~ 05.04.07 13:29:

> Текущая - UTF, хотя я не совсем понимаю, какая разница

это не кодировка.
 

demon_mhm

Новичок
neko, очень верно подмечено. Действительно, неизвестно о каких символах и кодировках идет речь. Известно только, что эти незвестные символы нужно убрать из документа, оставив только то, что распознаётся как символы в кодировке UTF-8.
Оч жалко что нет такой функции :)
 

neko

tеam neko
> хотя я не совсем понимаю, какая разница

это заметно.

я объясню.

разница заключается в том, что чтобы какие-то символы убрать, надо
сначала определить какие именно.
"кривые символы типа копирайтов или траейдмарков и ХЗ чего вообще" определением не является.
 

demon_mhm

Новичок
В данном случае, нужно пойти от обратного: определить какие символы мы хотим видеть в документе, а все остальные убрать. Вот я и хотел поинтересоваться у общественности как правильно это сделать.
 

neko

tеam neko
> Известно только, что эти незвестные символы нужно убрать из документа,
> оставив только то, что распознаётся как символы в кодировке UTF-8.

это скорее всего сделать не получится.

-~{}~ 05.04.07 13:36:

> В данном случае, нужно пойти от обратного: определить какие символы мы
> хотим видеть в документе, а все остальные убрать.

ну дык.
возьми и сделай список символов
и посимвольно проверяй

но это как-то, странно мне
ты уверен, что проблема именно в этих документах?
а не в другом месте?
 

phprus

Moderator
Команда форума
demon_mhm
Текущая - UTF, хотя я не совсем понимаю, какая разница
Разница есть, так как в FAQ-е описана функция которая убирает из строки в UTF-8 битые символы. Вот ссылка: http://phpclub.ru/faq/wakka.php?wakka=encodings/encodings3&v=12pe
А вот код (Код приведен из-за того, что у меня при попытке зайти на вышеназванную страницу он отображается не полностью. Про этот баг я уже писал, но его так и не профиксили):
PHP:
function StripBadUTF8($str) { // (C) SiMM, based on ru.wikipedia.org/wiki/Unicode
$ret = '';
for ($i = 0;$i < strlen($str); ) {
    $tmp = $str[$i++];
    $ch = ord($tmp);
    if ($ch > 0x7F) {
        if ($ch < 0xC0) continue;
        elseif ($ch < 0xE0) $di = 1;
        elseif ($ch < 0xF0) $di = 2;
        elseif ($ch < 0xF8) $di = 3;
        elseif ($ch < 0xFC) $di = 4;
        elseif ($ch < 0xFE) $di = 5;
        else continue;

        for ($j = 0;$j < $di;$j++) {
            $tmp .= $ch = $str[$i + $j];
            $ch = ord($ch);
            if ($ch < 0x80 || $ch > 0xBF) continue 2;
        }
        $i += $di;
    }
    $ret .= $tmp;
}
return $ret;
}
Alexandre
Так как в задаче сказано удалить все символы кроме разрешенных, то ИМХО в данном случае регулярка будет быстрее чем посимволный перебор строки и проверка каждого символа.

neko
это скорее всего сделать не получится.
Кто сказал, что не получится?
 

demon_mhm

Новичок
Абсолютно уверен, т.к. другие документы тем же кодом парсятся нормально, а на одном документе парсинг валится с ошибкой "invalid token". Так как повлиять на содержимое документа я не могу, остается править то, что присылают...

-~{}~ 05.04.07 13:55:

phprus, спасибо огромное. Но к сожалению, Ваша функция не решает задачи. Вот кусок кода, на котором валится парсер:
PHP:
<browser>Son?©SonyEricssonK500i</browser>
Это строки user-agent браузеров телефонов. Не думал что там такая каша, но она есть, оказывается...
Данные идут прямо из базы, так что, даже если мне дадут доступ, всё равно надо ставить фильтр перед записью в базу, который будет решать те же задачи
 

Alexandre

PHPПенсионер
phprus а что делает регулярка? не посимвольно ли сканирует строку + накрученные правила

у меня левота убирается так
PHP:
function stripcode($str){

{
	$trans = array (
	  '©' => '&copy;',
	  '®' => '&reg;',
	  '№' => '&#8470;',
	  '–' => '&#150;',
	  '«' => '&laquo;',
	  '»' => '&raquo;',
	  '…' => '...', // и прочие вордовские символы
	  '’' => "'")

strtr($str, $trans);

 for($i=0;  $i<strlen($str) ; $i++)
 {
      if ( $str[$i] == 'ё') continue;
      if ( $str[$i] == 'Ё') continue;
      if ( ord( $str[$i] ) > 127  AND ord( $str[$i] ) <192 )
        $str[$i] = "*";
 }
 return $str;
}
далее разбираешься с символами, которые були заменены на *, отлавливаешь их и вновь вносишь в свой заменитель
мой массив значительно больше.
 

demon_mhm

Новичок
Alexandre, я бы не стал сравнивать проматывание строки посимвольно средставми ПХП и preg_match, мне кажется, второе гораздо быстрее, т.к. реализовано на C, ИМХО
Большое спасибо за советы, но они не помогли, к сожалению, а помогло вот что:
PHP:
`tidy -xml -m -config tidy.conf file.xml`
в файле tidy.conf одна строчка: escape-cdata=yes
 

denver

?>Скриптер
Разочарую всех тут, но функция "убрать всё лишнее" в php есть :)
PHP:
echo iconv("UTF-8", "UTF-8//IGNORE", $xml);
 

demon_mhm

Новичок
denver, пробовал, не помогает :) Про iconv я сразу подумал. Но она всего лишь игнорирует то, чего не может перекодировать, тоесть вся кривизна как была,так и остаётся, а вот tidy как раз помог
 

denver

?>Скриптер
demon_mhm
Выложи плиза пример XML (маленького) который содержит те не-UТF8 символы которые не вырезает iconv.
 
Сверху