Avatar billede hugopedersen Nybegynder
30. august 2013 - 10:05 Der er 13 kommentarer og
1 løsning

Slette fra en XML fil

Jeg har en XML fil som ligner nedenstående.
Hvordan kan jeg slette alle underpunkter til et punkt.
F.eks. kunne jeg kome i tanke om at slette alle punkter under <Logfiles> med en procedure der skulle hedde ClearSection(Section: string);

Jeg har ikke kunnet finde noget på nettet der giver et godt resultat.

Håber det giver mening

<Configuration>
  <Logfiles>
    <Database>False</Database>
    <Debug>False</Debug>
    <Errors>True</Errors>
    <Events>True</Events>
  </Logfiles>
  <Supported_DB>
    <Type_0>MySQL</Type_0>
    <Type_3>Access</Type_3>
  </Supported_DB>
  <License>
    <Demo_licens>False</Demo_licens>
  </License>
  <Logon>
    <Last_user>HP</Last_user>
  </Logon>
</Configuration>
Avatar billede kroning Nybegynder
30. august 2013 - 10:15 #1
Det mest simple, som jeg ofte bruger, er vel at benytte pos og posex funktionerne til at finde "<Logfiles>" (i1) og "</Logfiles>" (i2) og så slette alt mellem i1 og i2
Avatar billede hugopedersen Nybegynder
30. august 2013 - 10:44 #2
Jeg var inde på noget med at loade filen ind i en TStringlist og så søge i den og slette mellem de 2 forekomster.
Men jeg ser et mindre problem i at XML dokumentet jo er loadet i memory så jeg skal lige have checket om det virker med først at gemme det og så lave det Stringlist nummer og så loade det igen efterfølgende.

Det undrer mig bar at der ikke er standard funktioner til det.
Avatar billede kroning Nybegynder
30. august 2013 - 10:48 #3
Jeg kan ikke se noget problem...
Avatar billede hugopedersen Nybegynder
30. august 2013 - 10:52 #4
I hvad ?
Avatar billede kroning Nybegynder
30. august 2013 - 10:56 #5
:-) Du skriver "Men jeg ser et mindre problem i at XML dokumentet...", jeg er ikke helt klar over hvad problemet skulle være.
Avatar billede hugopedersen Nybegynder
30. august 2013 - 11:00 #6
Hvis jeg nu begynder at manipulere med filen mens den stadig er loadet i memory så vil de ændringer jeg har lavet jo bare blive overskrevet når filen skrives fra memory - som jeg ser det
Avatar billede kroning Nybegynder
30. august 2013 - 11:11 #7
Mener du at der er andre programmer som også ændre i filen?
Avatar billede hugopedersen Nybegynder
30. august 2013 - 11:17 #8
Nej
Men så vidt jeg kan hitte frem til så bliver XML loadet i memory og kun skrevet når dokumentet releases.
Men jeg kan have misforstået noget
Avatar billede kroning Nybegynder
30. august 2013 - 11:34 #9
Hvilket program laver din XML fil og når du skal til at ændre i det har dette program så stadig loadet XML filen?
Avatar billede hugopedersen Nybegynder
30. august 2013 - 12:59 #10
Det er mit eget program der styrer det hele.
Det er et led i et større projekt hvor jeg er ved at lave nogle generelle moduler til at styre gemme/læse opsætning af program enten i DB, INI, Registry eller XML

Min klasse til XML er nedenfor hvis det giver mening

//*********************************************************
// Class for connecting to XML file
// Used for storing settings
// © OZ8HP Hugo Pedersen
//*********************************************************
unit U_Storage.Xml;

{$I Defines.inc}

interface

uses
  Forms, SysUtils, Windows, XmlIntf, XMLDoc;

type
  TSettingsConn = class
  private
    fModified: boolean;
    fConfigfile: string;
    fXMLDoc: TXMLDocument;
  public
    constructor Create(const FileName: string); overload;
    constructor Create; overload;
    property ConfigFile: string read fConfigFile write fConfigFile;

    procedure SaveFile;

    function ReadString(aSection, aKey, aDefault: string): string;
    procedure WriteString(aSection, aKey, aValue: string);

    function Readboolean(const aSection, aKey: string; aDefault: boolean): boolean;
    procedure Writeboolean(const aSection, aKey: string; aValue: boolean);
    function ReadDate(const aSection, aKey: string; const aDefault: TDate): TDate;
    procedure WriteDate(const aSection, aKey: string; const aValue: TDate);
    function ReadInteger(const aSection, aKey: string; aDefault: integer): integer;
    procedure WriteInteger(const aSection, aKey: string; aValue: integer);

    procedure AppendSection(const aSection: string);
    procedure ClearSection(const aSection : string);
    procedure InsertSection(const Old, New : string);
    procedure UpdateFile;
  end;

var
  SettingsConn: TSettingsConn;

implementation

uses
  Vcl.Dialogs,
  U_AppConsts;


// Start of functions and procedures for helping class
function CleanaValue(aValue: string): string;
begin
  aValue := StringReplace(aValue, ' ',  '_',  [rfReplaceAll, rfIgnoreCase]);
  Result := aValue;
end;

function SettingsFileBuild: string;
begin
  Result := ChangeFileExt(Application.ExeName, '.xml');
{$IFDEF USESETTINGS}
  Result := ExtractFilePath(Application.ExeName) + 'settings.xml';
{$ENDIF}
end;
// End of functions and procedures for helping class

{ TSettingsConn }
constructor TSettingsConn.Create(const FileName: string);
begin
  inherited Create;
  fConfigfile    := FileName;
  fXMLDoc        := TXMLDocument.Create(Application);
  fXMLDoc.Options := [doNodeAutoIndent];
  if FileExists(fConfigfile) then
    fXMLDoc.LoadFromFile(fConfigfile)
  else
    begin
      fXMLDoc.Active := True;
      fXMLDoc.AddChild('Configuration');
      fXMLDoc.SaveToFile(fConfigfile);
    end;
end;

constructor TSettingsConn.Create;
begin
  Create(SettingsFileBuild);
end;

procedure TSettingsConn.SaveFile;
begin
  if not fModified then
    Exit;
  fXMLDoc.Active := True;
  fXMLDoc.SaveToFile(fConfigfile);
  fModified := False;
end;

// *****************************************************************************
//  Everything in XML is read/write as strings
// *****************************************************************************
function TSettingsConn.ReadString(aSection, aKey, aDefault: string): string;
var
  Node: IXMLNode;
  Child: IXMLNode;
begin
  aSection := CleanaValue(aSection);
  aKey := CleanaValue(aKey);
  Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(aSection);

  if not Assigned(Node) then
    begin
      Result := aDefault;
      Exit;
    end;

  Child:= Node.ChildNodes.FindNode(aKey);
  if not Assigned(Child) then
    begin
      Result := aDefault;
      Exit;
    end;

  Result := Child.Text;
end;

procedure TSettingsConn.WriteString(aSection, aKey, aValue: string);
var
  Node: IXMLNode;
  Child: IXMLNode;
begin
  aSection := CleanaValue(aSection);
  aKey := CleanaValue(aKey);
  if ReadString(aSection, aKey, '') = aValue then
    Exit;

  Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(aSection);
  if not Assigned(Node) then
    Node := fXMLDoc.DocumentElement.AddChild(aSection);

  Child:= Node.ChildNodes.FindNode(aKey);
  if not Assigned(Child) then
    Child:= Node.AddChild(aKey);

  Child.Text := aValue;
  fModified := True;
  SaveFile;
end;

// *****************************************************************************
//  All other datatypes are converted and read/write as string
// *****************************************************************************
function TSettingsConn.Readboolean(const aSection, aKey: string; aDefault: boolean): boolean;
begin
  Result := boolean(ReadInteger(aSection, aKey, integer(aDefault)));
end;

function TSettingsConn.ReadDate(const aSection, aKey: string; const aDefault: TDate): TDate;
begin
  Result := StrToDate(ReadString(aSection, aKey, DateToStr(aDefault)));
end;

function TSettingsConn.ReadInteger(const aSection, aKey: string; aDefault: integer): integer;
begin
  Result := StrToInt(ReadString(aSection, aKey, IntToStr(aDefault)));
end;

procedure TSettingsConn.Writeboolean(const aSection, aKey: string; aValue: boolean);
begin
  WriteInteger(aSection, aKey, Integer(aValue));
end;

procedure TSettingsConn.WriteDate(const aSection, aKey: string; const aValue: TDate);
begin
  WriteString(aSection, aKey, DateToStr(aValue));
end;

procedure TSettingsConn.WriteInteger(const aSection, aKey: string; aValue: integer);
begin
  WriteString(aSection, aKey, IntToStr(aValue));
end;
// *****************************************************************************


// *****************************************************************************
//  Following procedures are here to make all connections look the same
//  They are standard in FastIniFile
// *****************************************************************************
procedure TSettingsConn.AppendSection(const aSection: string);
begin
  // Dummy procedure to make class look like other connection classes
end;

procedure TSettingsConn.ClearSection(const aSection : string);
begin
  // Dummy procedure
end;

procedure TSettingsConn.InsertSection(const Old, New : string);
begin
  // Dummy procedure
end;

procedure TSettingsConn.UpdateFile;
begin
  // Dummy procedure
end;

// Getters and setters

initialization
  SettingsConn := TSettingsConn.Create;

finalization
  FreeAndNil(SettingsConn);


end.
Avatar billede kroning Nybegynder
30. august 2013 - 13:54 #11
procedure TSettingsConn.ClearSection(const aSection : string);
var
  Node: IXMLNode;
begin
  Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(aSection);
  if Assigned(Node) then
        fXMLDoc.DocumentElement.ChildNodes.Remove(Node);

  fModified := True;
  SaveFile;
end;
Avatar billede hugopedersen Nybegynder
30. august 2013 - 15:51 #12
Det var da ikke så slemt som jeg havde regnet med :-)

Der er nogle meget kryptiske løsninger der ude som har forvirret mig hele dagen.

Men smid et svar kroning.
Avatar billede kroning Nybegynder
30. august 2013 - 16:00 #13
Svar

Og den skal nok rettes til:

procedure TSettingsConn.ClearSection(const aSection : string);
var
  Node: IXMLNode;
begin
  Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(aSection);
  if Assigned(Node) then
  begin
        fXMLDoc.DocumentElement.ChildNodes.Remove(Node);

      fModified := True;
      SaveFile;
  end;
end;

Ingen grund til at SaveFile hvis der ikke er slettet noget.
Avatar billede hugopedersen Nybegynder
30. august 2013 - 16:14 #14
Nej og det vil vel også være en sikkerhed mod fejl hvis man forsøger at slette en node der ikke findes.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester



Seneste spørgsmål Seneste aktivitet
I går 23:37 Poe strøm Af lurup i LAN/WAN
I går 14:46 GIF-EDITOR Af snestrup2000 i Billedbehandling
I går 14:03 Logge ind Af Bob i PC
I går 12:12 2 skærme - 1 virker - den anden siger No signal Af eksmojo i Skærme
I går 10:33 openvpn projekt Af dcedata1977 i Windows