30. august 2013 - 10:05Der 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.
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
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.
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
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
// 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);
// ***************************************************************************** // 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;
// ***************************************************************************** // 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;
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);
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.
Nej og det vil vel også være en sikkerhed mod fejl hvis man forsøger at slette en node der ikke findes.
Synes godt om
Ny brugerNybegynder
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.