За последние 24 часа нас посетили 18192 программиста и 1651 робот. Сейчас ищут 1628 программистов ...

XML парсер с правильным выводом кириллицы

Тема в разделе "Решения, алгоритмы", создана пользователем sahaba, 5 фев 2010.

?

Оцените

  1. Гуд

    0 голосов
    0,0%
  2. Не очень гуд

    0 голосов
    0,0%
  3. Ужас а не гуд

    0 голосов
    0,0%
  1. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    Проблема кодировки при парсинге xml наверное встречалась не только мне. Дело в том что используя xml_parser_create() и xml Windows-1251 при выводе данных получается вот какая штука: Если текст начинается с руского символа все нормально, но если первый символ не русский теряется все что находится до первого вхождения русского символа.

    Например:
    текст мой мейл blabla@blabla.com пишите сюда будет выводиться нормально, а если blabla@blabla.com это мой мейл пишите сюда выводится как это мой мейл пишите сюда.
    Вот как я решил эту проблему:

    PHP:
    1. // Функция для преоброзования русских символов в код
    2. function cyrcode($s){
    3.  for($i=0, $m=strlen($s); $i<  $m; $i++){
    4.  $c=ord($s[$i]);
    5.  if ($c<  =127){
    6.  $t.=chr($c);
    7.  continue;
    8.  }
    9.  if ($c  >=128 && $c<  =255){
    10.  $t.="#".$c;
    11.  continue;
    12.  }
    13.  }
    14.  return $t;
    15. }
    16.  
    17. // Функция обратного преоброзования кода в русские символы
    18. function cyrchr($s){
    19.  $col=substr_count($s,"#");
    20.  for ($i=0; $i<  $col; $i++)
    21.  $s=substr_replace ($s, chr(substr($s,strpos($s,"#")+1,3)), strpos($s,"#"),4);
    22.  $t=$s;
    23.  return $t;
    24. }
    25.  
    26. $xml_parser = xml_parser_create ();
    27. xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, FALSE);
    28. xml_set_element_handler($xml_parser, "startElement", "endElement");
    29.  
    30. // Здесь собственно можно использовать функцию cyrchr
    31. xml_set_character_data_handler($xml_parser, "stringElement");
    32.  
    33. if (!($fp = fopen($file, "r"))) {die("could not open XML input");}
    34. while ($data = fgets($fp)) {
    35.  $data=cyrcode($data);
    36.  if (!xml_parse($xml_parser, $data, feof($fp))) {
    37.  echo "<  br  >XML Error: ".xml_error_string(xml_get_error_code($xml_parser))." at line ".xml_get_current_line_number($xml_parser);
    38.  break;
    39.  }
    40. }
    Если код ужасный, не ругайтесь, а помогите написать хороший. А то средства системные жрет сильно, особенно ощушается если xml больше 10MB
     
  2. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    А работать в utf-8 не?
    Ну или там iconv какой применить?
     
  3. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    как раз при использовании таких функций как iconv и откидывается в начале латиница
     
  4. r00les

    r00les Активный пользователь

    С нами с:
    4 сен 2009
    Сообщения:
    142
    Симпатии:
    0
    ISO-8859-1 (по умолчанию)

    А вы укажите кодировку желаемую, вот так попробуйте:

    ....
    $xml_parser = xml_parser_create ( 'US-ASCII' );
    ....
     
  5. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    ну там всеголишь поддерживается три кодировки US-ASCII, UTF-8 и ISO-8859-1. Я незнаю честно говоря что такое US-ASCII, но это точно не win1251. Помоему US это чтото типа United States. В любом случае я так пробовал. Ваще у меня такое ощущение что xml_parser_createу глубоко наплевать что там у него прописано. он никак не реагирует на эти настройки.
    Может надо изменять кодировку XML?
     
  6. r00les

    r00les Активный пользователь

    С нами с:
    4 сен 2009
    Сообщения:
    142
    Симпатии:
    0
    sahaba

    И ещё, почему вы не используете для тех же целей: simplexml ?
     
  7. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    Я пробовал и simplexml, но (помоему он отказался работать изза слишком большого файла xml). У меня каталог товаров, в котором находится болле 100 000 товаров. Короче xml весит более 145MB. Почемуто simplexml я отбросил сразу. Можно конечно кусками грузить, но не думаю что в конечном итоге я буду экономить на памяти.
     
  8. iliavlad

    iliavlad Активный пользователь

    С нами с:
    24 янв 2009
    Сообщения:
    1.689
    Симпатии:
    4
    если не секрет, сколько по времени вы его парсите?
     
  9. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    на локалке минут сорок. А вот на разных хостах по разному. Многие просто отказываются парсить.
     
  10. r00les

    r00les Активный пользователь

    С нами с:
    4 сен 2009
    Сообщения:
    142
    Симпатии:
    0
    sahaba

    Советую тебе проиндексировать его, и работая уже как с бинарной структурой, считывая срез нужных данных по байтам.
     
  11. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    r00les, буду благодарен если ты мне поподробнее объяснишь.
     
  12. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    помоему это будет не меньше памяти жрать. XML ку я беру с другого хоста, раз в неделю. Чтобы его сделать бинарным, полюбому мне надо закачать его к себе на хост, потом уже поработать с ним. А это уже 145МБ входящего трафика, на что хостер мой ругается. Вот если закачивать себе этот файл кусками и собрать потом его.... ну незнаю...
    На cron чтоли посадить весь проццес??? ... Но так тоже не валидно. XML может измениться в любой момент...
     
  13. r00les

    r00les Активный пользователь

    С нами с:
    4 сен 2009
    Сообщения:
    142
    Симпатии:
    0
    sahaba

    проиндексировать, это значит прогнать и хранить в памяти или ещё где отдельно индексы каждого ключа, а файл обрабатывать кусками, с индекса начинаешь считывать определённое количество байт, до следующего индекса, обрабатываешь и дальше пошёл.
     
  14. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    А чем
    тебе ненравится? я имею ввиду он тоже кусками (построчно) читает файл, обрабатывает эту строку потом идет на следующую.

    Мне интересно что с бинарной системой делать? как понять бинарный, насколько я помню это сжатие данных типа рар зип Если это так, как мне с ним работать с удаенного комутера :?:
     
  15. r00les

    r00les Активный пользователь

    С нами с:
    4 сен 2009
    Сообщения:
    142
    Симпатии:
    0
    sahaba

    это значит ты не со строками работаешь а на более несшим уровне, с байтами.
     
  16. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    r00les
    Чето я торможу. если я не сжимаю исходный файл, с чембы я не работал мне все равно надо весь файл обрабатывать. Если я многократно обращалсябы к разным данным можно былобы, а в моем случае, я просто прохожусь по всему файлу и вношу все данные в базу.
    Какой смысл брать исходный файл делить его на куски ... а потом все обратно. По твоему это скоростнее будет?
    Если я реально торможу прошу скинуть ссылку где я могу подробнее прочитать об этом.
     
  17. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    sahaba
    забей. Тебе сейчас насоветуют.

    Простейший случай индексации xml файла это создание таблицы смещений токенов относительно начала файла и их размеров.
    Тогда при поиске токена (ноды) ты будешь искать его ключ в таблице, брать оттуда смещение и длину токена и читать сразу нужный кусок файла.

    На больших XML сэкономить ресурсы не получиться (во всяком случае пока не сделают аппаратную поддержку xml в процессорах как обещают).

    Максимум что ты можешь сделать это разбить свой парсинг на этапы, но в этом случае тебе придется весь парсинг реализовывать ручками поскольку большинство инструментов толкает все сразу в память для ускорения обработки.

    Но сэкономив память ты проиграешь в скорости обработки и потраченных ресурсах процессора.

    Может ты озвучишь первоначальную задачу, которая побудила тебя парсить его?
     
  18. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    Создал каталог ("партнерка интернет магазина"). Они постоянно обновляют свой XML, а я в неделю 1 раз беру у них новый файл.
     
  19. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Понятно.
    XML сильно сложной структуры?

    Пробежись обычным fread и найди начало и конец минимальных полных блоков информации нужной тебе
    пример блока:
    HTML:
    1. <item>
    2.     <name></name>
    3.     <count></count>
    4.     <description></description>
    5. </item>
    Запиши смещение начала каждого такого блока и его длину в промежуточный файл.
    Потом в цикле берешь эту информацию, читаешь свой XML поблочно и парсишь уже эти конкретные блоки. Затем обрабатывай как тебе нужно.
    И только после этого парсишь следующий блок.

    Памяти будет кушать существенно меньше.
     
  20. r00les

    r00les Активный пользователь

    С нами с:
    4 сен 2009
    Сообщения:
    142
    Симпатии:
    0
    Simpliest

    БЛЯДЬ ! а я про что говорил, ну конечно не так гениальноумно как ты мистер умник. Но то же самое. БЛЯДЬ !
     
  21. sahaba

    sahaba Активный пользователь

    С нами с:
    5 фев 2010
    Сообщения:
    21
    Симпатии:
    0
    Simpliest Благодарю за помощь. Надо попробовать.