![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Обработка 3000 xml файлов [D7]
s_ilnar © (2005-01-18 21:13:00)Имеются более 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>
-------------------------------------
Ломброзо (2005-01-24 21:01:00) [1]DSKalugin © (24.01.05 11:42) [24]
Гениально. Не перевелись ешё кулибины на Руси. Снимаю шапочку. Признайтесь, Вы носки паяльником никогда не пробовали гладить?
Erik1 (2005-01-24 16:19:00) [2]to DSKalugin
Ну и причем тут твой пример. У человека 5000 файлов и даже простой цикл поиска по ним занимает огромное количество времени! Чем ему поможет твой пример?
А вот база поможет, поскольку позволяет создать индексы, а с их использованием поиск ускоряется на порядки.
DSKalugin (2005-01-24 11:49:00) [3]label r
предназначена для склеивания строк, которые разорваны переносом типа
<Car>VALEO Комплект
сцепления
57</Car>
label Start;
предназначена для пропуска отсутствующих полей. Напимер поля <Car> в записи может не быть
DSKalugin (2005-01-24 11:42:00) [4]а вот сам код чтения 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:42:00) [5]Даю мой пример. Сделай по образу и подобию.
<?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>
..............
Erik1 (2005-01-24 11:16:00) [6]Вобщето есть простое решение, странно что некто непредложил. Делаем так сначала импортируем все данные в базу данных, можно многопоточным образом. В базе создаем заголовочную таблицу где записываем имя файла, его дату создания и ID. При следущем старте поверяем какие файлы изменились. Если фаил изменился по парсим его и синхронизуем данные в базе. Опятьтаки все можно делать в потоках, да и изменяться наверное не все файлы. :) Вобще выйгрыш может достигать до 10 раз 10000%!
s_ilnar (2005-01-24 08:47:00) [7]Вы мне скажите если работать с файлами как с базой данных это будет быстрее чем как с файлами.
Я думаю что результат будет один и тот же т.к. подключить файл как базу данных и пока какой нибудь dataset считает его мои код за тоже время сумеет его обработать (код на самом верху)
Ломброзо (2005-01-23 15:51:00) [8]Другой вариант - помучать XSLT для трансформации древовидных данных в плоский табличный вид.
Ломброзо (2005-01-23 15:49:00) [9]ИМХО тут решать все проблемы "в лоб" глупо и вообще пустая трата времени. Совет такой: сесть за изучение .NET, XML, XML Schemas. Что-то мне подсказывает, что раз Beeline требует файлы именно такого формата, то их софтина, занимающаяся разбором, использует какую-то XSD-схему или для десериализации этого XML в какие-то объекты, или для десериализации его в дотнетовский "оторванный" DataSet, который в свою очередь сливает данные в реляционную базу данных. Так что имеет смысл связаться с представительством, поинтересоваться у них механизмом обработки отчётов, попросить схему, помучать .NET и пр.
s_ilnar (2005-01-23 10:40:00) [10]vizcoldy
ТЫ ПРАВ
Че ты под нее писал
Я пишу отчет месячный и ежедневный для отправки в представитьства beeline
vizcoldy (2005-01-20 16:29:00) [11]Если не секрет, чем программа занимется - это ведь файлы Dol, я тут недавно писала кое-что, связанное сней и с этими файлами?
Arm79 (2005-01-20 14:24:00) [12]А если вместо DOM использовать SAX с одновременным внесением данных в БД?
DSKalugin (2005-01-19 13:09:00) [13]у меня тоже стоит подобная задача.
Я собираюсь загнать это все в строку 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;
....
Соловьев (2005-01-19 12:07:00) [14]А что если загнать файлі в блоб поля и на сервере их парсить?
Кажись в MS SQL есть такая фича... Или FireBird - UDF
s_ilnar (2005-01-19 11:32:00) [15]Alex_Bredin
Я тоже так думал но есть небольшая заминка иногда эти файлы могут редактироваться
Alex_Bredin (2005-01-19 11:25:00) [16]разбери файлы один раз, загони данные в БД и работай с ней
s_ilnar (2005-01-19 11:22:00) [17]Проблема в следующем
Имеется боолее 3000 файлов (для каждого клиента заводиться отдельный файл, эти файлы создаются не моей программой а обробатывать их надо моей программой
че предложите, когда обробатывается 300 файлов терпеть еще можно
но когда все 3000 файлов это занимает определенное время (~3 мин)
И самая большая проблема надо их еще сортировать по дате,
а дата как вы понимаете записан в файле и считывать как я понимаю придется вся базу (все 3000 файлов)
Ладно у меня их 3000,а у други более 50000
ПОМОГИТЕ
Erik1 (2005-01-19 11:09:00) [18]Только кешировать это дело, или изменить постановку задачи. Приведи полностью проблему.
Соловьев (2005-01-19 11:09:00) [19]Ужас. вот что значит использовать формат не по назначению.
Когда-то писал парсер xml на С - работает шустро, напиши длл на Visual C++ и дергай ее, пусть тебе она возращает строку или нужный отпарсеный результат.
s_ilnar (2005-01-19 10:59:00) [20]Мастера мне необходимо чтоб считывание файлов проходило быстро!!!
Предложите пжлста способ как это реализовать
СПАСИБО