Metin düzenini Parse etmek [ÇÖZÜLDÜ]

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
kadrikaya
Üye
Mesajlar: 38
Kayıt: 01 Ara 2016 11:31

Metin düzenini Parse etmek [ÇÖZÜLDÜ]

Mesaj gönderen kadrikaya » 09 Kas 2019 08:12

Merhaba,
Bir metin parçasını belirli bir düzende parse etmem gerekiyor, günlerin verdiği yorgunluktan düşünemez oldum, yardımlarınızı rica ediyorum arkadaşlar. Bu metin içinde beni ilgilendiren tek şey <ul> ve <li> ile başlayanları ayırmam gerek ayırırken de şunu bilmem gerek, Kahve 1.<ul> nin elemanıdır, Sıcak Çay 2.<ul> nin elemanıdır. Meyveli 1.<ul> nin elemanıdır. ve bu <ul> ler değişkendir yani liste daha karışık bir şekilde artabilir de, yani gelen metnin ne olduğu belli olmayacak ama her ne metin gelirse gelsin, sadece söylediğim şekilde ul ve li ler ile ilgileniyorum. <ul> olmadan sadece <li> olma olasılığı da var. Ayrıca ul ve li ler haricindeki bütün metin parçasını da ayrıca ayrıştırmam gerek.

ilk <ul> ye kadar olan metin parçasını hangi tag içinde olduğu önemli değil komple bir değişkene alacak, sonra listeyi söylediğim şekilde parse edecek
liste parse bittiğinde devam edecek ve sonraki ul veya li ye kadar olan metni yine bir değişkene alacak, sonra bulduğu listeyi yine parse edecek.
bu işlem metin bitinceye kadar devam edecek.

Ve bu işin DOM document ve benzeri şekilde olmaması gerek, direk string işlem yapmam gerekli

Yardımlarınız içi şimdiden teşekkürler.

Kod: Tümünü seç

<b>Öylesine metin başlığı bold</b><br>
<p>paragraf metni ne olduğu önemli değil</p>
<ul>
  <li>Kahve</li>
  <li>Su</li>
  <li>Çay
  	<ul>
      <li>Sıcak Çay</li>
      <li>Soğuk Çay</li>
      
      <li>Diğer Çay
      	<ul>
        	<li>Rezene</li>
      		<li>Kuş Burnu</li>	
        </ul>
      </li>      
      <li>Gazlı</li>
  	</ul>
  </li>
  <li>Meyveli</li>
</ul>

<b>Farklı metinler tekrar eder bold</b><br>
<p>Farklı bir paragraf metni ne olduğu önemli değil</p>

<ul>
  <li>Sıcak Çay</li>
  <li>Soğuk Çay</li>

  <li>Diğer Çay
    <ul>
      <li>Rezene</li>
      <li>Kuş Burnu</li>	
    </ul>
  </li>      
  <li>Gazlı</li>
</ul>
En son kadrikaya tarafından 10 Kas 2019 04:04 tarihinde düzenlendi, toplamda 1 kere düzenlendi.

mkysoft
Kıdemli Üye
Mesajlar: 3026
Kayıt: 25 Ağu 2003 11:35
Konum: İstanbul
İletişim:

Re: Metin düzenini Parse etmek

Mesaj gönderen mkysoft » 10 Kas 2019 08:47

Ve bu işin DOM document ve benzeri şekilde olmaması gerek, direk string işlem yapmam gerekli
Eğer standartları biliyorsanız string işlemleri ie yapabilirsiniz ama tavsiye etmem. Xml ya da html için aşağıdakilerin hepsi aynıdır.

Kod: Tümünü seç

<ul>
<ul >
<ul x="y">
<ul x>
<ul 
>

kadrikaya
Üye
Mesajlar: 38
Kayıt: 01 Ara 2016 11:31

Re: Metin düzenini Parse etmek

Mesaj gönderen kadrikaya » 10 Kas 2019 11:38

Teşekkür ederim, ancak malesef string işlem yapmak zorundayım. Standart zaten html standardı. Onları parse etmek hiç sorun değil zaten sorun olan iç içe listeler oluyor gösterirken aynı düzende göstermem gerek.

Bu arada biraz işten uzaklaşıp sakin kafa ile düşününce problemi çözdüm sanırım, sadece kodu biraz düzenlemem gerekli.
Düzenleme sonrası paylaşırım. İhtiyaç olabilir.
Tekrar teşekkürler.

kadrikaya
Üye
Mesajlar: 38
Kayıt: 01 Ara 2016 11:31

Re: Metin düzenini Parse etmek

Mesaj gönderen kadrikaya » 10 Kas 2019 02:06

Arkadaşlar merhaba,
istediğimi yaptım, isteyen belki faydası olur. Öncelikle amacın ne olduğunu kısaca tekrar anlatayım.
Gelen yalın bir html text veri içindeki metini ve listeleme yapısını ayıklayarak her biri için ayrı bir label obje oluşturmak
ve bir VerticalScrollBox içinde yukarıdan aşağı sıralamak. Sıralarken oluşturduğum label objesi eğer bir listeleme elemanı
ise bunu Html yapısındaki iç içe düzenine aynen uyacak şekilde marjin ayarı yaparak listelemek ve listelemelerin başına liste olduğunu
gösterecek başka bir obje koymak.

Bu arada uygulama mobil uygulama FMX form ve Label yerine alcinoe componenti ALText kullandım.
Herkese kolaylıklar dilerim.

Burası kod parçasna metni ve VertScrollBox objesini gönderiyorum

Kod: Tümünü seç

procedure Page_Text_Create(Text:String;_Parent: TFMXObject);
var
  Lbl :TALText ;
  Create_Text, Ilk_4, Ilk_5:string;

  text_end,li_s,li_e,ul_s,ul_e,
  chr_pos, Indent_UL_LI :integer;

  ul_var, li_var : Boolean;

  En_Kucuk, I : integer;
  Karsilastir:Array of integer ;
begin
   SetLength(Karsilastir,4);
   ul_var := False;
   Indent_UL_LI := 1;
   while true do
   begin
      Karsilastir[0] := 0;
      Karsilastir[1] := 0;
      Karsilastir[2] := 0;
      Karsilastir[3] := 0;
      Text := Trim(Text);
      Text_End := Pos('<#apitextend#>',Text);
      if (Text_End =1) or ( Text ='') then
      Break;

      Ilk_4 := copy(Text,1,4);
      ilk_5 := copy(Text,1,5);
      if (Ilk_4 ='<ul>') or (Ilk_4 ='<li>')  then
      begin
         Delete(Text,1,4);
         if Ilk_4 ='<ul>' then Indent_UL_LI:= Indent_UL_LI +1;
      end;

      if (ilk_5 ='</ul>') or (ilk_5 ='</li>')  then
      begin
         Delete(Text,1,5);
         if ilk_5 ='</ul>' then Indent_UL_LI:= Indent_UL_LI -1;
      end;

      if (ilk_5 <>'</ul>') and (ilk_5 <>'</li>') and (Ilk_4 <> '<ul>') and (Ilk_4 <> '<li>')  then
      begin
         ul_s := Pos('<ul>',Text);
         li_s := Pos('<li>',Text);
         ul_e := Pos('</ul>',Text);
         li_e := Pos('</li>',Text);

         Karsilastir[0] := ul_s;
         Karsilastir[1] := li_s;
         Karsilastir[2] := ul_e;
         Karsilastir[3] := li_e;
         En_Kucuk := 10000;
         for i := 0 to Length(Karsilastir)-1 do
         begin
           if Karsilastir[i] > 0 then
           if Karsilastir[i] < En_Kucuk then
             En_Kucuk := Karsilastir[i];
         end;
         chr_pos := En_Kucuk;

         Create_Text := Copy(Text,1,chr_pos-1);
         Text_Create(Text_Html_Tags_Clear(Create_Text),Indent_UL_LI, _Parent);
         Delete(Text,1,chr_pos-1);
      end;


   end;

end;
Bu kod parçası yukarıda işlenen metin parçasını bu koda gönderiyor ve metin yada liste elemanı olma durumuna göre objeleri oluşturuyor

Kod: Tümünü seç

procedure Text_Create(Text: String; Indent:Integer; _Parent:TFMXObject);
var
  Lbl :TALText ;
  Bul : Integer;
  Paragraf: String;
  _Indent : Single;
begin
   if Indent = 0 then _Indent := 1;
   if Indent > 0 then _Indent := Indent *2;

   while True do
   begin
      Bul := Pos('<br><br>',Text);
      if Bul > 1 then
      begin
         Paragraf := Copy(Text,1,Bul-1);
         Paragraf := StringReplace(Paragraf,'<br>',Chr(13),[rfReplaceAll]);
         Paragraf := StringReplace(Paragraf,'<br />',Chr(10),[rfReplaceAll]);
         lbl := TALText.Create(nil);
         lbl.Text := Trim(Paragraf);
         Paragraf:= EmptyStr;
         lbl.TextIsHtml := True;
         lbl.TextSettings.WordWrap:=True;
         lbl.Margins.Left := 10*_Indent;
         lbl.Margins.Right := 5;

         if Indent > 1 then
         begin
            lbl.Margins.Top :=5;
            lbl.Margins.Bottom := 0;
         end else
         begin
            lbl.Margins.Top :=10;
            lbl.Margins.Bottom := 10;
         end;

         Lbl.Position.Y :=  20000;
         lbl.Parent := _Parent;//VertScrollBox1;
         lbl.Align := TAlignLayout.Top;
         lbl.AutoSize := True;
         Delete(Text,1,Bul+7);
         Trim(Text);

         if Indent > 1 then
            Indent_Create(Indent, Lbl.Position.X - 10, Lbl.Position.Y + 5, _Parent);

      end else
      if Text.Length > 0 then
      begin
         lbl := TALText.Create(nil);
         Text := StringReplace(Text,'<br>',Chr(13),[rfReplaceAll]);
         Paragraf := StringReplace(Paragraf,'<br />',Chr(10),[rfReplaceAll]);

         lbl.Text := Trim(Text);

         lbl.TextIsHtml := True;
         lbl.TextSettings.WordWrap:=True;
         lbl.Margins.Left := 10*_Indent;
         lbl.Margins.Right := 5;
         if Indent > 1 then
         begin
            lbl.Margins.Top :=5;
            lbl.Margins.Bottom := 0;
         end else
         begin
            lbl.Margins.Top :=10;
            lbl.Margins.Bottom := 10;
         end;
         Lbl.Position.Y := 20000;
         lbl.Parent := _Parent;//VertScrollBox1;
         lbl.Align := TAlignLayout.Top;
         lbl.AutoSize := True;

         if Indent > 1 then
            Indent_Create(Indent, Lbl.Position.X - 10, Lbl.Position.Y + 5, _Parent);

         Break;
      end else Break;
   end;
end;
Bu koda parçasıda Text_Create prosedüründe oluşan metin parçası liste elemanı ise oluşan objenin pozisyonlarına göre yanında nokta görünecek
şekilde rectangle objesi oluşturuyor

Kod: Tümünü seç

procedure Indent_Create(Indent, Pos_X, Pos_Y: Single; _Parent:TFMXObject);
var
Indent_Rectangle :TALRectangle ;
begin
   Indent_Rectangle := TALRectangle.Create(nil);
   if Indent = 2 then
      Indent_Rectangle.Fill.Color := TAlphaColors.Black
   else
      Indent_Rectangle.Fill.Color := TAlphaColors.White;

   Indent_Rectangle.Height  := 5;
   Indent_Rectangle.Width   := 5;
   Indent_Rectangle.XRadius := 3;
   Indent_Rectangle.YRadius := 3;
   Indent_Rectangle.Position.X := Pos_X;
   Indent_Rectangle.Position.Y := Pos_Y;
   Indent_Rectangle.Parent  := _Parent;//VertScrollBox1;
end;

Cevapla