Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2005.02.20;
Скачать: [xml.tar.bz2];

Вниз

Обработка 3000 xml файлов   Найти похожие ветки 

 
s_ilnar ©   (2005-01-18 21:13) [0]

Имеются более 3000 фалов приблизительно такого содержания (и кол-во увеличивается 500 шт в месяц).
Необходимо Выдергивать некоторые данные

Я пока вижу 2 варианта
1. Подключаться к файлу как к базе данных
2. Открывать файл и получать данные следующим способом
-------------------------------------------------------------------------------------------------------------------
function Xml(FileName:string;Key:string):string;
var
F:File;
Str:array [1..3000] of char;
ss:string;
begin
 AssignFile(F,FileName);
 Reset(F);
 BlockRead(F,Str,FileSize(F));
 CloseFile(F);
 ss:=str;
 if pos("<"+key+">",ss)=0 then begin xml:="###Error###"; exit; end;
 Delete(ss,1,pos("<"+key+">",ss)+length(key)+1);
 Delete(ss,pos("<",ss),length(ss));
 Xml:=ss;
end;
--------------------------------------------------------------------------------------------------------------------

МАСТЕРА пожалуйста помогите что делать т.к. файлов более 3000 и обрабатывать эту кучу долговато

Что рекомендуете

-----------------------------------
XML File
-------------------------------
<?xml version="1.0" encoding="windows-1251"?>
<CONTRACT>
<Status>0</Status>
<DealerCode>E000</DealerCode>
<DealerPointCode>E000001</DealerPointCode>
<DealerContractCode>4</DealerContractCode>
<DealerContractDate>2003-12-16</DealerContractDate>
<ABSContractCode></ABSContractCode>
<CUSTOMER>
<CUSTOMERTYPESId>0</CUSTOMERTYPESId>
<SPHERESId>-1</SPHERESId>
<Resident>1</Resident>
<Ratepayer>1</Ratepayer>
<PERSON>
<PERSONTYPESId>0</PERSONTYPESId>
<PERSONNAME>
<SEXTYPESId>0</SEXTYPESId>
<LastName>Иванов</LastName>
<FirstName>Иван</FirstName>
<SecondName>Иванович</SecondName>
</PERSONNAME>
<DOCUMENT>
<DOCTYPESId>1</DOCTYPESId>
<Seria>1010</Seria>
<Number>101010</Number>
<GivenBy>Ивановским РОВД</GivenBy>
<Date>2000-00-00</Date>
<Birthday>2000-00-00</Birthday>
</DOCUMENT>
<INN></INN>
</PERSON><ADDRESS>
<ZIP>400000</ZIP
><Country>Российская Федерация</Country>
<Area></Area>
<Region></Region>
<PLACETYPESId>2</PLACETYPESId>
<PlaceName>Иванов</PlaceName>
<STREETTYPESId>1</STREETTYPESId>
<StreetName>Ивановская</StreetName>
<House>48</House>
<BUILDINGTYPESId>-1</BUILDINGTYPESId>
<Building></Building>
<ROOMTYPESId>-1</ROOMTYPESId>
<Room></Room>
</ADDRESS>
</CUSTOMER>
<BANKPROPLIST/>
<DELIVERY>
<DELIVERYTYPESId>1</DELIVERYTYPESId>
<ADDRESS>
<ZIP>422110</ZIP>
<Country>Российская Федерация</Country>
<Area></Area>
<Region></Region>
<PLACETYPESId>2</PLACETYPESId>
<PlaceName>Иванов</PlaceName>
<STREETTYPESId>1</STREETTYPESId>
<StreetName>Ивановская</StreetName>
<House>48</House>
<BUILDINGTYPESId>-1</BUILDINGTYPESId>
<Building></Building>
<ROOMTYPESId>-1</ROOMTYPESId>
<Room></Room>
</ADDRESS>
<Notes></Notes>
</DELIVERY>
<CONTACT>
<PERSONNAME>
<SEXTYPESId>0</SEXTYPESId>
<LastName>Иванов И.И.</LastName>
<FirstName></FirstName>
<SecondName></SecondName>
</PERSONNAME>
<PhonePrefix>900</PhonePrefix>
<Phone>000000</Phone>
<FaxPrefix></FaxPrefix>
<Fax></Fax>
<EMail></EMail>
<PagerOperatorPrefix></PagerOperatorPrefix>
<PagerOperator></PagerOperator>
<PagerAbonent></PagerAbonent>
<Notes></Notes>
</CONTACT>
<CONNECTIONS>
<CONNECTION>
<PAYSYSTEMSId>3</PAYSYSTEMSId>
<BILLCYCLESId>-1</BILLCYCLESId>
<CELLNETSId>2</CELLNETSId>
<PRODUCTSId>1000</PRODUCTSId>
<PhoneOwner>1</PhoneOwner>
<SerNumber>520000000000000</SerNumber>
<SimLock>0</SimLock>
<IMSI>897000000000000000</IMSI>
<MOBILES>
<MOBILE>
<CHANNELTYPESId>1</CHANNELTYPESId>
<CHANNELLENSId>0</CHANNELLENSId>
<SNB>9000000000</SNB>
<BILLPLANSId>392</BILLPLANSId>
<SERVICES>
<SERVICESId>1</SERVICESId>
<SERVICESId>3</SERVICESId>
<SERVICESId>16</SERVICESId>
<SERVICESId>17</SERVICESId>
<SERVICESId>8</SERVICESId>
</SERVICES>
</MOBILE>
</MOBILES>
</CONNECTION>
</CONNECTIONS>
<Comments></Comments>
<CLIENTVER>1.0.0.275</CLIENTVER>
</CONTRACT>

-------------------------------------


 
Alex_Bredin ©   (2005-01-18 21:24) [1]

в D7 есть библиотеки MSXML, MSXMLDOM, c их помощью можно парсить ХМЛ примерно так(кода кусок):


var
 xml: IXMLDOMDocument;
 n, nn, nnn, nnnn: IXMLDOMNode;
 Query: TTransactionQuery;
 TransactionType: TTransactionType;

begin
 if not fileexists(XMLFileName) then
   raise Exception.Create(Format(RsFileNotFound,[XMLFileName]));
  Result:= TStringList.Create;
  xml := CreateDOMDocument;
  xml.load(XMLFileName);
  n := xml.firstChild;
  while Assigned(n) do
  begin
    if n.nodeName ="нужная нода" then
     begin
      nn:=n.firstChild;
      while assigned(nn) do
        begin
            if nn.nodeName = "еще нужная дочерняя нода" then
              begin
 


итд итп

плохо что все это недокументировано, но есть MSDN, да и Code completion помогает


 
Anatoly Podgoretsky ©   (2005-01-18 21:36) [2]

А вот что ты будешь делать, когда  размер файоа окажется больше 3000 байт
BlockRead(F,Str,FileSize(F));
Тем более, что Str по сути не используется.


 
s_ilnar ©   (2005-01-18 21:50) [3]

Alex_Bredin скорее всего мой способ работает быстрее

и на счет str и ss переменных
(ss:string; str:array[1..3000] of char;)
по идее string=255 символов, но когда я ss:=str то ы в ss лежало более 2500 символов. Как это можете обьяснить
И еще файлы на данный момент не превышают 3000 байт


 
Anatoly Podgoretsky ©   (2005-01-18 22:02) [4]

По идее string это до 2 миллиардов символов.
И по второй идее, это на данный момент.


 
Fay ©   (2005-01-18 23:02) [5]

Блин! Чё за уродскай формат?! Кто придумал вытаскивать атрибуты в элементы?!

По вопросу. Какого размера будут файлы?


 
Anatoly Podgoretsky ©   (2005-01-18 23:18) [6]

Fay ©   (18.01.05 23:02) [5]
Это не важно если не использовать Hard Coded массивов и при это не проверять файл на допустимость.


 
Fay ©   (2005-01-19 00:36) [7]

Anatoly Podgoretsky ©   (18.01.05 23:18) [6]
Если это о размере, то попробуйте открыть в IE такой XML размером ~ 10Мб.


 
Ditrix ©   (2005-01-19 10:23) [8]

может выход такой?
использовать XML только как формат импорта-експорта данных
а для хранения использовать RDBM


 
s_ilnar ©   (2005-01-19 10:59) [9]

Мастера мне необходимо чтоб считывание файлов проходило быстро!!!
Предложите пжлста способ как это реализовать

СПАСИБО


 
Соловьев ©   (2005-01-19 11:09) [10]

Ужас. вот что значит использовать формат не по назначению.
Когда-то писал парсер xml на С - работает шустро, напиши длл на Visual C++ и  дергай ее, пусть тебе она возращает строку или нужный отпарсеный результат.


 
Erik1 ©   (2005-01-19 11:09) [11]

Только кешировать это дело, или изменить постановку задачи. Приведи полностью проблему.


 
s_ilnar ©   (2005-01-19 11:22) [12]

Проблема в следующем
Имеется боолее 3000 файлов (для каждого клиента заводиться отдельный файл, эти файлы создаются не моей программой а обробатывать их надо моей программой
че предложите, когда обробатывается  300 файлов терпеть еще можно
но когда все 3000 файлов это занимает определенное время (~3 мин)

И самая большая проблема надо их еще сортировать по дате,
а дата как вы понимаете записан в файле и считывать как я понимаю придется вся базу (все 3000 файлов)

Ладно у меня их 3000,а у други более 50000

ПОМОГИТЕ


 
Alex_Bredin ©   (2005-01-19 11:25) [13]

разбери файлы один раз, загони данные в БД и работай с ней


 
s_ilnar ©   (2005-01-19 11:32) [14]

Alex_Bredin

Я тоже так думал но есть небольшая заминка иногда эти файлы могут редактироваться


 
Соловьев ©   (2005-01-19 12:07) [15]

А что если загнать файлі в блоб поля и на сервере их парсить?
Кажись в MS SQL есть такая фича... Или FireBird - UDF


 
DSKalugin ©   (2005-01-19 13:09) [16]

у меня тоже стоит подобная задача.
Я собираюсь загнать это все в строку AnsiString и вырезать информацию между нужными тегами, двигаясь вдоль строки.
Но работаю как  с обычным текстовым файлом

var RenaultF:TextFile;
   strKAFile:AnsiString;
begin
 if not OpenDialog.Execute then exit;
 AssignFile(RenaultF,OpenDialog.FileName);
 try
   Reset(RenaultF);
   Read(RenaultF,strKAFile);
 finally
   CloseFile(RenaultF);
 end;
....


 
Arm79 ©   (2005-01-20 14:24) [17]

А если вместо DOM использовать SAX с одновременным внесением данных в БД?


 
vizcoldy   (2005-01-20 16:29) [18]

Если не секрет, чем программа занимется - это ведь файлы Dol, я тут недавно писала кое-что, связанное сней и с этими файлами?


 
s_ilnar ©   (2005-01-23 10:40) [19]

vizcoldy
ТЫ ПРАВ
Че ты под нее писал

Я пишу отчет месячный и ежедневный для отправки в представитьства beeline


 
Ломброзо ©   (2005-01-23 15:49) [20]

ИМХО тут решать все проблемы "в лоб" глупо и вообще пустая трата времени. Совет такой: сесть за изучение .NET, XML, XML Schemas. Что-то мне подсказывает, что раз Beeline требует файлы именно такого формата, то их софтина, занимающаяся разбором, использует какую-то XSD-схему или для десериализации этого XML в какие-то объекты, или для десериализации его в дотнетовский "оторванный" DataSet, который в свою очередь сливает данные в реляционную базу данных. Так что имеет смысл связаться с представительством, поинтересоваться у них механизмом обработки отчётов, попросить схему, помучать .NET  и пр.


 
Ломброзо ©   (2005-01-23 15:51) [21]

Другой вариант - помучать XSLT для трансформации древовидных данных в плоский табличный вид.


 
s_ilnar ©   (2005-01-24 08:47) [22]

Вы мне скажите если работать с файлами как с базой данных это будет быстрее чем как с файлами.

Я думаю что результат будет один и тот же т.к. подключить файл как базу данных и пока какой нибудь dataset считает его мои код за тоже время сумеет его обработать (код на самом верху)


 
Erik1 ©   (2005-01-24 11:16) [23]

Вобщето есть простое решение, странно что некто непредложил. Делаем так сначала импортируем все данные в базу данных, можно многопоточным образом. В базе создаем заголовочную таблицу где записываем имя файла, его дату создания и ID. При следущем старте поверяем какие файлы изменились. Если фаил изменился по парсим его и синхронизуем данные в базе. Опятьтаки все можно делать в потоках, да и изменяться наверное не все файлы. :) Вобще выйгрыш может достигать до 10 раз 10000%!


 
DSKalugin ©   (2005-01-24 11:42) [24]

Даю мой пример. Сделай по образу и подобию.

<?xml version="1.0" standalone="yes"?>
<NewDataSet>
 <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
   <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:Locale="ru-RU">
     <xs:complexType>
       <xs:choice maxOccurs="unbounded">
         <xs:element name="tovar">
           <xs:complexType>
             <xs:sequence>
               <xs:element name="id" type="xs:int" minOccurs="0" />
               <xs:element name="Name" type="xs:string" minOccurs="0" />
               <xs:element name="Car" type="xs:string" minOccurs="0" />
               <xs:element name="Price" type="xs:double" minOccurs="0" />
               <xs:element name="Big_grup" type="xs:int" minOccurs="0" />
               <xs:element name="Sub_grup" type="xs:int" minOccurs="0" />
               <xs:element name="Sklad" type="xs:double" minOccurs="0" />
               <xs:element name="Sklad2" type="xs:int" minOccurs="0" />
               <xs:element name="Sklad3" type="xs:int" minOccurs="0" />
               <xs:element name="ID_ZAMENI" type="xs:int" minOccurs="0" />
             </xs:sequence>
           </xs:complexType>
         </xs:element>
         <xs:element name="news">
           <xs:complexType>
             <xs:sequence>
               <xs:element name="Id" type="xs:int" minOccurs="0" />
               <xs:element name="NEWS" type="xs:string" minOccurs="0" />
               <xs:element name="Date" type="xs:dateTime" minOccurs="0" />
             </xs:sequence>
           </xs:complexType>
         </xs:element>
         <xs:element name="BigGrup">
           <xs:complexType>
             <xs:sequence>
               <xs:element name="ID" type="xs:int" minOccurs="0" />
               <xs:element name="Name" type="xs:string" minOccurs="0" />
             </xs:sequence>
           </xs:complexType>
         </xs:element>
         <xs:element name="SubGrup">
           <xs:complexType>
             <xs:sequence>
               <xs:element name="BIG_ID" type="xs:int" minOccurs="0" />
               <xs:element name="ID" type="xs:int" minOccurs="0" />
               <xs:element name="Name" type="xs:string" minOccurs="0" />
               <xs:element name="Percent" type="xs:int" minOccurs="0" />
             </xs:sequence>
           </xs:complexType>
         </xs:element>
       </xs:choice>
     </xs:complexType>
   </xs:element>
 </xs:schema>
 <tovar>
   <id>1</id>
   <Name>000056</Name>
   <Car>VALEO Комплект сцепления 56</Car>
   <Price>108.75</Price>
   <Big_grup>14</Big_grup>
   <Sub_grup>49</Sub_grup>
   <Sklad>0</Sklad>
   <Sklad2>0</Sklad2>
   <Sklad3>0</Sklad3>
 </tovar>
 <tovar>
   <id>2</id>
   <Name>000057</Name>
   <Car>VALEO Комплект сцепления 57</Car>
   <Price>135.94</Price>
   <Big_grup>14</Big_grup>
   <Sub_grup>49</Sub_grup>
   <Sklad>0</Sklad>
   <Sklad2>0</Sklad2>
   <Sklad3>0</Sklad3>
 </tovar>
..............


 
DSKalugin ©   (2005-01-24 11:42) [25]

а вот сам код чтения XML и экспорт его в Парадокс-таблицу
Писано на скору руку. Вылизывать код потом буду. так что сильно к меткам не придерайтесь.

implementation {$R *.dfm}  uses strutils;
const defdir="u:\Almar";
var strXMLFile,UTF8FileName, ANSIFileName:AnsiString;
   rcnt:LongInt;

procedure TForm1.Button1Click(Sender: TObject);

label r,Start;

const FieldCount=10;
     oTovarTag="<tovar>";
     cTovarTag="</tovar>";

type TXMLStruct=array [1..FieldCount] of ShortString;

var AlmarF:TextFile;
   i,ol,fl:LongInt;
   val:AnsiString;
   oTovarStruct, TovarStruct:TXMLStruct;

begin
 OpenDialog.InitialDir:=defdir;
 OpenDialog.Filter:="obnovlenie.xml|obnovleni*.xml";
 if not OpenDialog.Execute then exit;
 UTF8FileName:=OpenDialog.FileName;
 XMLUtf8ToAnsi(UTF8FileName,ANSIFileName);
 TovarStruct[1]:="id";
 TovarStruct[2]:="Name";
 TovarStruct[3]:="Car";
 TovarStruct[4]:="Price";
 TovarStruct[5]:="Big_grup";
 TovarStruct[6]:="Sub_grup";
 TovarStruct[7]:="Sklad";
 TovarStruct[8]:="Sklad2";
 TovarStruct[9]:="Sklad3";
 TovarStruct[10]:="ID_ZAMENI";
 for i:=1 to FieldCount do begin
   oTovarStruct[i]:="<"+TovarStruct[i]+">";
   StringGrid1.Cells[i-1,0]:=TovarStruct[i];
 end;
 AssignFile(AlmarF,ANSIFileName);
 FileMode := 0;
 StatusBar.Panels[3].Text:=ANSIFileName;
 rcnt:=0;
 try
   Reset(AlmarF);
   StringGrid1.Hide;
   while not Eof(AlmarF) do begin
     ReadLn(AlmarF,strXMLFile);
     strXMLFile:=Trim(strXMLFile);
     if strXMLFile=oTovarTag then begin
       inc(rcnt); i:=1;
       StringGrid1.RowCount:=rcnt+1;
       repeat
         strXMLFile:="";
r:
         ReadLn(AlmarF,val);
         val:=Trim(val);
         if (val[Length(val)]<>">") then begin
           strXMLFile:=strXMLFile+val+" ";
           goto r;
         end
         else strXMLFile:=strXMLFile+val;
Start:
         if AnsiStartsStr(oTovarStruct[i], strXMLFile)
         then begin
           ol:=Length(oTovarStruct[i]);
           fl:=Length(strXMLFile);
           StringGrid1.Cells[i-1,rcnt]:=Copy(strXMLFile,ol+1,fl-2*ol-1);
         end
         else begin
           StringGrid1.Cells[i-1,rcnt]:="?";
           inc(i);
           if (i<=FieldCount) then goto Start;
         end;
         inc(i);
       until ((strXMLFile=cTovarTag) or (i>FieldCount));
// for testing if rcnt=50 then break;
     end;
     Application.ProcessMessages;
   end;
 finally
   StatusBar.Panels[3].Text:=IntToStr(rcnt);
   StringGrid1.Show;
   CloseFile(AlmarF);
 end;
 ShowMessage("Reading Over")
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
 Close
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 StatusBar.Panels[1].Text:="";
 StatusBar.Panels[3].Text:="";
 StringGrid1.ColWidths[0]:=50;
 StringGrid1.ColWidths[1]:=125;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
 SetLength(strXMLFile,0);
 Session.Close;
end;

procedure TForm1.SpeedButton3Click(Sender: TObject);
var i:LongInt;
begin
 Session.Close;
 tbPrice.EmptyTable;
 tbPrice.Open;
 for i:=1 to rcnt do begin
   tbPrice.Append;
   tbPriceid.AsInteger:=StrToInt(StringGrid1.Cells[0,i]);
   tbPriceName.AsString:=StringGrid1.Cells[1,i];

   if StringGrid1.Cells[2,i]<>"?" then tbPriceCar.AsString:=StringGrid1.Cells[2,i];
   tbPricePrice.asFloat:=StrToFloat(StringGrid1.Cells[3,i]);
   tbPriceBig_grup.AsInteger:=StrToInt(StringGrid1.Cells[4,i]);
   tbPriceSub_Grup.AsInteger:=StrToInt(StringGrid1.Cells[5,i]);
   tbPriceSklad.AsInteger:=StrToInt(StringGrid1.Cells[6,i]);
   tbPriceSklad2.AsInteger:=StrToInt(StringGrid1.Cells[7,i]);
   tbPriceSklad3.AsInteger:=StrToInt(StringGrid1.Cells[8,i]);
   if StringGrid1.Cells[9,i]<>"?" then tbPriceId_zameni.AsInteger:=StrToInt(StringGrid1.Cells[9,i]);
   tbPrice.Post;
   Application.ProcessMessages;
 end;
 tbPrice.Close;
 ShowMessage("ok")
end;

procedure TForm1.SpeedButton2Click(Sender: TObject);
var c,r:LongInt;
begin
  c:=StrToInt(Edit1.Text);
  for r:=1 to rcnt do
      if StringGrid1.Cells[c,r]="?" then begin
         StringGrid1.Col:=c;
         StringGrid1.Row:=r;
         Abort
      end;
end;

procedure TForm1.XMLUtf8ToAnsi(const iFileName: AnsiString; var oFileName: AnsiString);
var UTF_F,ANSI_F:TextFile;
   sBuf: WideString;
   dBuf: AnsiString;
begin
 oFileName:=ExtractFilePath(iFileName)+"obnovlenie.ANSI.xml";
 AssignFile(UTF_F,iFileName);
 AssignFile(ANSI_F,oFileName);
 Reset(UTF_F);
 Rewrite(ANSI_F);
 try
 while not EOF(UTF_F) do begin
   ReadLn(UTF_F,sBuf);
   dBuf:=Utf8ToAnsi(sBuf);
   WriteLn(ANSI_F,dBuf);
 end;
 finally
   CloseFile(UTF_F);
   CloseFile(ANSI_F);
 end;
end;

end.


 
DSKalugin ©   (2005-01-24 11:49) [26]

label r
предназначена для склеивания строк, которые разорваны переносом типа

<Car>VALEO Комплект
сцепления
57</Car>

label Start;
предназначена для пропуска отсутствующих полей. Напимер поля <Car> в записи может не быть


 
Erik1 ©   (2005-01-24 16:19) [27]

to DSKalugin
Ну и причем тут твой пример. У человека 5000 файлов и даже простой цикл поиска по ним занимает огромное количество времени! Чем ему поможет твой пример?
 А вот база поможет, поскольку позволяет создать индексы, а с их использованием поиск ускоряется на порядки.


 
Ломброзо ©   (2005-01-24 21:01) [28]

DSKalugin ©   (24.01.05 11:42) [24]

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



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2005.02.20;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.56 MB
Время: 0.037 c
1-1107506780
Zilog
2005-02-04 11:46
2005.02.20
LoadFromResourceName


1-1107333376
denis24
2005-02-02 11:36
2005.02.20
изменения размера шрифта при редактировании в stringgtide


1-1107834997
Аккум
2005-02-08 06:56
2005.02.20
Динамический array of record в памяти как располагается ?


1-1107722490
SLAK
2005-02-06 23:41
2005.02.20
типы дробных чисел


14-1106727696
vidiv
2005-01-26 11:21
2005.02.20
Kerio WR... и http





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский