Xpoint
   [напомнить пароль]

Парсер LibXML - Проблема при insert в Mysql

Метки: [без меток]
2007-01-22 13:29:45 [обр] Сергей[досье]

Вот хотел узнать у Вас друзья,
проблема моя в том что после insert в базе вмеcто русских букв хрень типа иероглифов
но если сделать print в браузер все ok,
в чем может быть проблема?

Локаль Бд CHARSET=cp1251
mysql 4.x
perl 5.8

уже пробовал:

use Encode;
Encode::from_to($text, "utf8", "cp1251");

use cyrillic qw/utf2win detect/;
utf2win($text);

Пример кода:

use locale; 
use POSIX qw(locale_h); 
setlocale(LC_ALL, "ru_RU.CP1251"); 

use LWP::Simple; 
use XML::LibXML; 
use Text::Iconv;

use DBI; 
require 'includes/sub.pl'; 

my $dbh = DBconnect(); 

$dbh->do("delete from category"); 

my $converter = Text::Iconv->new("utf-8", "windows-1251"); 

print "Content-type: text/html\n\n"; 

#my $XMLTEXT=get('http://mixmarket.biz/mixmldirect.plx?id=4294967238'); 
#if(!$XMLTEXT){warn ("Проблемы с $XMLURL");exit;} 

my $parser = XML::LibXML->new(); 
my $doc=$parser->parse_file('xml/TEMP.xml'); 
my $results = $doc->findnodes('//categories/category'); 
foreach my $node ($results->get_nodelist) 
{ 
my $text = $converter->convert($node->textContent()); 

my @attrs=$node->attributes(); 
my (%attr,%TAGS)=(); 
foreach (@attrs) 
{ 
  $attr{$_->getName()}=$_->getValue(); 
}; 


## Формируем запрос 
$dbh->do("INSERT INTO category VALUES (".$attr{id}.",'".$attr{parentId}."','".$text."')"); 

print "$attr{id}|$attr{parentId}|$text\n<br>"; 
}
спустя 15 часов [обр] Роман Чемисов(36/350)[досье]
Сергей[досье]
А в браузер страничку получает в какой Encoding?
спустя 5 часов [обр] Сергей[досье]

Вроде windows-1251,

если сделать

use cyrillic qw/convert detect/;
print detect $text;
выдает кодировку 1251

а если сделать detect при select из БД

выдает кодировку 2858

спустя 6 часов [обр] Закиров Руслан(51/343)[досье]

Сергей[досье] Хороший пример кода отличается от плохого тем, что первый можно скопировать из браузера и он будет работать.

В статье в нашей базе знаний описана Поддержка Unicode в perl. Модуль XML::LibXML использует эту технологию и вы можете решить проблему несколькими способами:

#!/usr/bin/perl

use strict;
use warnings;

use XML::LibXML;
use Encode;
use DBI;

my $dbh = DBI->connect('dbi:mysql:test', root => '' )
    or die "couldn't connect";

$dbh->do('DROP TABLE IF EXISTS test');
$dbh->do('CREATE TABLE test ( category VARCHAR(255) ) DEFAULT CHARSET=cp1251');

{
    $dbh->do('SET NAMES "UTF8"');

    my $parser = new XML::LibXML; 
    my $doc = $parser->parse_file('tmp.cp1251.xml'); 
    foreach my $node ( $doc->findnodes('//category')->get_nodelist ) {
        my $text = $node->textContent;
        $dbh->do("INSERT INTO test(category) VALUES (?)", {}, $text );
    }

    $doc = $parser->parse_file('tmp.utf8.xml');
    foreach my $node ( $doc->findnodes('//category')->get_nodelist ) {
        my $text = $node->textContent;
        $dbh->do("INSERT INTO test(category) VALUES (?)", {}, $text );
    }
}

{
    $dbh->do('SET NAMES "cp1251"');

    my $parser = new XML::LibXML; 
    my $doc = $parser->parse_file('tmp.cp1251.xml'); 
    foreach my $node ( $doc->findnodes('//category')->get_nodelist ) {
        my $text = $node->textContent;
        $dbh->do("INSERT INTO test(category) VALUES (?)", {}, encode( cp1251 => $text ) );
    }

    $doc = $parser->parse_file('tmp.utf8.xml');
    foreach my $node ( $doc->findnodes('//category')->get_nodelist ) {
        my $text = $node->textContent;
        $dbh->do("INSERT INTO test(category) VALUES (?)", {}, encode( cp1251 => $text ) );
    }
}

Первый способ (первый блок кода) устанавливает кодировку соеденинения в UTF-8, что позволяет вам без всяких преобразований передавать UTF-8 текст в запросах к mysql, но стоит отметить, что и получать результаты вы будете в этой кодировке. Последнее можно более точно настроить в mysql 4.1 и выше (читайте доки по mysql).

Второй блок показывает как использовать модуль Encode для конвертации UTF-8 строк из внутреннего представления perl (такие строки возвращаются модулем XML::LibXML) в последовательность байт в любой кодировке. В данном случае кодировку соеденения мы выбираем cp1251, получение и передачу данных организовываем в ней.

Я использовал простой XML файл в двух разных кодировках (iconv вам в помощь):

<?xml version="1.0" encoding="UTF-8"?>
<tmp>
<category>Тест</category>
<category>Тест</category>
</tmp>

Собственно, у вас есть три выбора:

  1. в perl коде использовать UTF-8 (первый пример), а преобразование оставить mysql'ю
  2. преобразовывать результаты модуля в cp1251 (второй пример) и работать далее с cp1251
  3. заставить LibXML возвращать cp1251 (домашнее задание)
спустя 20 часов [обр] Сергей[досье]
Спасибо Вам огромное за Ваш ответ,
но дело в том что я уже пробовал
преобразовывать результаты модуля в cp1251 (второй пример) и работать далее с cp1251
в итоге в базе строки вида:òåïëîâûå çàâåñû
также как и с модулем Text::Iconv;
спустя 43 минуты [обр] Закиров Руслан(51/343)[досье]
Вы попробовали мой код? Он тоже вставляет в БД абракадабру? Версия mysql 4.1 или 4.0?
спустя 47 минут [обр] Сергей[досье]

да он тоже, Версия mysql 4.1

у Всех как у людей только у меня как...

спустя 3 часа 23 минуты [обр] Сергей[досье]

Ура всем спасибо, я как всегда пропустил что нужно обязательно

рабочий вариант:

$dbh->do("INSERT INTO test(category) VALUES (?)", {}, encode( cp1251 => $text ) );

но почему если писать типа:

$dbh->do("INSERT INTO test(category) VALUES ('".encode( cp1251 => $text )."');

получаем коракобозяки?

спустя 1 час 14 минут [обр] Закиров Руслан(51/343)[досье]
А у вас не используется что-то из разряда use utf8 или use encoding ...?
спустя 14 часов [обр] Сергей[досье]
Этого точно нет.
Powered by POEM™ Engine Copyright © 2002-2005