Merhaba.
- Senin için PARSE fonksiyonunu yazdım, kolaylık sağlayayım istedim. Artık gerisini getirirsin.
- Parse işlemi yapıldıktan sonra karşılaştırıp yeni bir XML üretmek çocuk oyuncağı.
- Bu örnek ile veri alanlarının yerleri değişse dahi sonuç alabilirsin. Çünkü bileşenlerine alan isimleri bazında ayırıyoruz. Yoksa Önce soyad sonra ad olsaydı ve değerler aynı olsaydı dahi gösterdiğin örnek sayfada değişmiş gibi algılanırdı değil mi?!
- Aşağıdaki örnekte daha parse işemi sırasında dahi aynı veri alanlarının olup olmadığını araştırıp satırları direkt sildirerek filtre edebilir, finalde aListe içeriğini olduğu gibi değişiklikler listesi olarak kullanabilirsin.
- SQL'deki satırları alt alta <row \> <row \> şeklinde eklesen dahi bu parse fonksiyonu hepsini ID'lendirerek aListe içerisine alacağından sıknıtı yaşamazsın. Bir kere EOF döngüsü sonuna kadar bir STRINGLIST veya MEMO benzeri yerde biriktirdiğin XML Row'larını kümülatif olarak fonksiyona verebilir hepsinin bir batında çözümünü sağlayabilirsin.
Takip edeceğin iş akışını yazayım :
(1) a- DocID 1'e ait alanları sırasıyla almak.
. b- DocID 2'de aynı isimli alan var mı diye aramak.
. c- Varsa değerlerini karşılaştırmak
. d- Değerler farklı ise yeni değeri değişmiş olarak kodlamak.
(2) a- DocID 1'deki alan DocID 2'de yok ise NULL çekip değeri değişmiş deyip elinizdeki tek değeri yazmak
(3) bu işlemleri bir Doc1-> Doc2 yönünde yaptığınız gibi bir de tersini Doc-2'den Doc-1 yönünde yapmak. Çünkü görebildiğim üzere Doc-2'de olan Doc-1'de olmayan alanlar da olabiliyor ...
Kod: Tümünü seç
function ParseEt( strDoc1, strDoc2: String ): String;
Type
pVeri = ^tveri;
tVeri = Record
DocId : Word; // Doc1 mi Doc2 mi olduğu
Satir,
AlanIdx : Integer;
AlanAdi,
AlanDeger : String;
end;
Procedure ParseEdilsin( strDoc: String; DocID:Word; Liste:TStrings );
Const
strSatirBasi = '<ROW';
Var
Veri : pVeri;
iSat, Idx : Integer;
begin
iSat := 0;
while POS( strSatirBasi, UpperCase(strDoc) ) > 0 do // Tek satır da olsa birden fazla da olsa çalışır...
begin // Satır Başı...
System.Delete( strDoc, 1, POS( strSatirBasi, UpperCase(strDoc) ) + Length(strSatirBasi)-1 );
inc(iSat);
strDoc := Trim(strDoc);
Idx := 0;
while Pos('="', strDoc) > 0 do // Başlık ve Değer var...
begin
New(Veri);
Inc(Idx);
Veri.DocId := DocID; // Doc-1 veya Doc-2 olduğunu ifade ediyoruz...
Veri.Satir := iSat;
Veri.AlanIdx := Idx;
Veri.AlanAdi := Trim( Copy(strDoc, 1, Pos('="', strDoc)-1 ) );
System.Delete( strDoc, 1, Pos('="', strDoc) + 1 );
Veri.AlanDeger := Trim( Copy(strDoc, 1, Pos('"', strDoc)-1 ) );
System.Delete( strDoc, 1, Pos('"', strDoc) );
Liste.AddObject( Veri.AlanAdi, TObject(Veri) );
end;
end;
end;
Var
aListe : TStringList;
i : Integer;
begin
Result := '';
aListe := TStringList.Create;
// Aynı şeyi iki defa yazmayalım diye procedure yaptım...
ParseEdilsin( strDoc1, 1, aListe );
ParseEdilsin( strDoc2, 2, aListe );
// Şimdi "aListe" içerisinde Başlık ve Değer içerikleri
// tümüyle parse edilmiş şekilde var...
// artık karşılaştırma yapabiliriz...
for i := 0 to aListe.Count - 1 do
begin
Result := Result + Format('Doc:%.2d @ Id:%d - Idx:%.2d : %s = %s'#13, [
pVeri( aListe.Objects[i] ).DocId
, pVeri( aListe.Objects[i] ).Satir
, pVeri( aListe.Objects[i] ).AlanIdx
, pVeri( aListe.Objects[i] ).AlanAdi
, pVeri( aListe.Objects[i] ).AlanDeger
]);
end;
// Sonunda hafızayı boşaltıp free edelim...
for i := 0 to aListe.Count - 1
do Dispose( pVeri(aListe.Objects[i]) );
aListe.Clear;
aListe.Free;
end;
Kullanımı :
Kod: Tümünü seç
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
Memo3.Lines.Text := ParseEt( Memo1.Lines.Text, Memo2.Lines.Text );
end;
