unit MyXML;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ExtCtrls;

const Version = '1.0';

type

MXML = class(TObject)
public
   XMLFileName : String;
   Wiersze     : TStringList;

   procedure   ReadSections(var Lista : TStringList);
   function    SectionIndex(const Section : String) : Integer;
   procedure   DeleteKey(const Section : String; const Name : String);
   function    ValueExist(const Section : String; const Name : String) : Boolean;
   procedure   WriteString(const Section : String; const Name : String; const Value : String);
   procedure   AddSection(const Section : String);
   function    SectionExist(const Section : String) : Boolean;
   procedure   EraseSection(const Section : String);   

   constructor Create(const FileName : String); virtual;
   destructor  Destroy(); override;
end;

implementation
{------------------------------------------------------------------------------}
constructor MXML.Create(const FileName : String);
begin
   XMLFileName := FileName;
   Wiersze     := TStringList.Create();

   if FileExists(FileName) then
   begin
      Wiersze.LoadFromFile(XMLFileName);
   end
   else begin
		Wiersze.Add('<?xml version = "1.0" encoding = "Windows-1250"?>');
		Wiersze.Add('<xmlini>');	// root
		Wiersze.Add('<info>');
		Wiersze.Add('<program>' + Version + '</program>');
		Wiersze.Add('</info>');
		Wiersze.Add('</xmlini>');

      Wiersze.SaveToFile(XMLFileName);
   end;

	// jeżeli plik byl pusty
   if Wiersze.Count = 0 then
   begin
		Wiersze.Add('<?xml version = "1.0" encoding = "Windows-1250"?>');
		Wiersze.Add('<xmlini>');
		Wiersze.Add('<info>');
		Wiersze.Add('<program>' + Version + '</program>');
		Wiersze.Add('</info>');
		Wiersze.Add('</xmlini>');

      Wiersze.SaveToFile(XMLFileName);
   end;
end;

destructor MXML.Destroy();
begin
	if Assigned(Wiersze) then
   begin
		// zrzut aktualnej zawartości do pliku
      Wiersze.SaveToFile(XMLFileName);

   	Wiersze.Clear();
      FreeAndNil(Wiersze);
   end;

	inherited;
end;

function MXML.SectionExist(const Section : String) : Boolean;
begin
   if Wiersze.IndexOf('<' + Section + '>') >= 0 then
   begin
   	Result := true;
   end
   else begin
   	Result := false;
   end;
end;

procedure MXML.AddSection(const Section : String);
var
   iLast : Integer;

begin
	iLast := Wiersze.Count-1;
   Wiersze.Delete(iLast);

   Wiersze.Add('<'  + Section + '>');
   Wiersze.Add('</' + Section + '>');
   Wiersze.Add('</xmlini>');
end;

function MXML.ValueExist(const Section : String; const Name : String) : Boolean;
var
   ret : Boolean;
   lp  : Integer;
   txt : String;
   poz : Integer;

begin
   ret := false;

   for lp := 0 to Wiersze.Count-1 do
	begin
      txt := Wiersze[lp];
      poz := Pos('<' + Name + '>', txt);
      if poz >= 0 then
   	begin
			ret := true;
         break;
      end;
   end;

	Result := ret;
end;

procedure MXML.DeleteKey(const Section : String; const Name : String);
var
   start  : Integer;
   koniec : Integer;
   txt    : String;
   lp     : Integer;
   poz    : Integer;

begin
   start  := Wiersze.IndexOf('</' + Section + '>');
   koniec := Wiersze.IndexOf('<'  + Section + '>');

   lp := start;
   while lp <= koniec do
   begin
      txt := Wiersze[lp];
      poz := Pos('<' + Name + '>', txt);

      if poz >= 0 then
      begin
         Wiersze.Delete(lp);
      end;
   end;
end;

function MXML.SectionIndex(const Section : String) : Integer;
var
	sekcja : String;

begin
	sekcja := '<' + Section + '>';
   Result := Wiersze.IndexOf(sekcja);
end;

procedure MXML.WriteString(const Section : String;
                           const Name    : String;
                           const Value   : String);
var
	txt : String;
   idx : Integer;

begin
	// jezeli sekcja ma już taki węzeł to go usuwam
   if ValueExist(Section, Name) then
   begin
      DeleteKey(Section, Name);
   end;

   txt := '';
   txt := txt + '<' + Name + '>' + Value + '</' + Name + '>';
   idx := SectionIndex(Section);
   Wiersze.Insert(idx+1, txt);
end;

procedure MXML.ReadSections(var Lista : TStringList);

var
   lp      : Integer;
   txt     : String;
   poz1    : Integer;
   poz2    : Integer;
   dl      : Integer;
   frag    : String;

begin
   for lp := 0 to Wiersze.Count-1 do
   begin
      txt  := Wiersze[lp];
      poz1 := Pos('<', txt);
      poz2 := Pos('/', txt);

      if (poz1 >= 0) and (poz2 >= 0) then
      begin
         dl   := Length(txt);
         frag := Copy(txt, 3, dl);
         Lista.Add(frag);
      end;
   end;
end;

procedure MXML.EraseSection(const Section: String);
var
	lp     : Integer;
   start  : Integer;
   koniec : Integer;

begin
   start  := Wiersze.IndexOf('<'  + Section + '>');
   koniec := Wiersze.IndexOf('</' + Section + '>');

   lp := koniec;
   while lp >= start do
   begin
      Wiersze.Delete(lp);
      Dec(lp);
   end;
end;

end.

