📄 jvsimplexml.pas
字号:
Stream.Free;
end;
procedure TJvSimpleXMLElems.AddChild(const Value: TJvSimpleXMLElem);
begin
CreateElems;
// If there already is a container, notify it to remove the element
if Assigned(Value.Container) then
Value.Container.Notify(Value, opRemove);
FElems.AddObject(Value.Name, Value);
Notify(Value, opInsert);
end;
procedure TJvSimpleXMLElems.AddChildFirst(const Value: TJvSimpleXMLElem);
begin
CreateElems;
// If there already is a container, notify it to remove the element
if Assigned(Value.Container) then
Value.Container.Notify(Value, opRemove);
FElems.InsertObject(0, Value.Name, Value);
Notify(Value, opInsert);
end;
function TJvSimpleXMLElems.AddFirst(const Name: string): TJvSimpleXMLElemClassic;
begin
Result := TJvSimpleXMLElemClassic.Create(Parent);
Result.FName := Name; //Directly set parent to avoid notification
AddChildFirst(Result);
end;
function TJvSimpleXMLElems.AddFirst(Value: TJvSimpleXMLElem): TJvSimpleXMLElem;
begin
if Value <> nil then
AddChildFirst(Value);
Result := Value;
end;
function TJvSimpleXMLElems.AddComment(const Name,
Value: string): TJvSimpleXMLElemComment;
begin
Result := TJvSimpleXMLElemComment.Create(Parent);
Result.FName := Name;
Result.Value := Value;
AddChild(Result);
end;
function TJvSimpleXMLElems.AddCData(const Name, Value: string): TJvSimpleXMLElemCData;
begin
Result := TJvSimpleXMLElemCData.Create(Parent);
Result.FName := Name;
Result.Value := Value;
AddChild(Result);
end;
function TJvSimpleXMLElems.AddText(const Name, Value: string): TJvSimpleXMLElemText;
begin
Result := TJvSimpleXMLElemText.Create(Parent);
Result.FName := Name;
Result.Value := Value;
AddChild(Result);
end;
procedure TJvSimpleXMLElems.BinaryValue(const Name: string;
const Stream: TStream);
var
Elem: TJvSimpleXMLElem;
begin
Elem := GetItemNamed(Name);
if Elem <> nil then
Elem.GetBinaryValue(Stream);
end;
function TJvSimpleXMLElems.BoolValue(const Name: string; Default: Boolean): Boolean;
var
Elem: TJvSimpleXMLElem;
begin
try
Elem := GetItemNamedDefault(Name, BoolToStr(Default));
if (Elem = nil) or (Elem.Value = '') then
Result := Default
else
Result := Elem.BoolValue;
except
Result := Default;
end;
end;
procedure TJvSimpleXMLElems.Clear;
var
I: Integer;
begin
if FElems <> nil then
begin
for I := 0 to FElems.Count - 1 do
begin
// TJvSimpleXMLElem(FElems.Objects[I]).Clear; // (p3) not needed -called in Destroy
FElems.Objects[I].Free;
FElems.Objects[I] := nil;
end;
FElems.Clear;
end;
end;
constructor TJvSimpleXMLElems.Create(const AOwner: TJvSimpleXMLElem);
begin
inherited Create;
FParent := AOwner;
end;
procedure TJvSimpleXMLElems.Delete(const Index: Integer);
begin
if (FElems <> nil) and (Index >= 0) and (Index < FElems.Count) then
begin
TObject(FElems.Objects[Index]).Free;
FElems.Delete(Index);
end;
end;
procedure TJvSimpleXMLElems.CreateElems;
begin
if FElems = nil then
FElems := THashedStringList.Create;
end;
procedure TJvSimpleXMLElems.Delete(const Name: string);
begin
if FElems <> nil then
Delete(FElems.IndexOf(Name));
end;
destructor TJvSimpleXMLElems.Destroy;
begin
FParent := nil;
Clear;
FreeAndNil(FElems);
inherited Destroy;
end;
procedure TJvSimpleXMLElems.DoItemRename(var Value: TJvSimpleXMLElem;
const Name: string);
var
I: Integer;
begin
I := FElems.IndexOfObject(Value);
if I <> -1 then
FElems[I] := Name;
end;
function TJvSimpleXMLElems.GetCount: Integer;
begin
if FElems = nil then
Result := 0
else
Result := FElems.Count;
end;
function TJvSimpleXMLElems.GetItem(const Index: Integer): TJvSimpleXMLElem;
begin
if (FElems = nil) or (Index > FElems.Count) then
Result := nil
else
Result := TJvSimpleXMLElem(FElems.Objects[Index]);
end;
function TJvSimpleXMLElems.GetItemNamedDefault(const Name, Default: string): TJvSimpleXMLElem;
var
I: Integer;
begin
Result := nil;
if FElems <> nil then
begin
I := FElems.IndexOf(Name);
if I <> -1 then
Result := TJvSimpleXMLElem(FElems.Objects[I])
else
if Assigned(Parent) and Assigned(Parent.SimpleXML) and (sxoAutoCreate in Parent.SimpleXML.Options) then
Result := Add(Name, Default);
end
else
if Assigned(Parent) and Assigned(Parent.SimpleXML) and (sxoAutoCreate in Parent.SimpleXML.Options) then
Result := Add(Name, Default);
end;
function TJvSimpleXMLElems.GetItemNamed(const Name: string): TJvSimpleXMLElem;
begin
Result := GetItemNamedDefault(Name, '');
end;
function TJvSimpleXMLElems.IntValue(const Name: string; Default: Int64): Int64;
var
Elem: TJvSimpleXMLElem;
begin
Elem := GetItemNamedDefault(Name, IntToStr(Default));
if Elem = nil then
Result := Default
else
Result := Elem.IntValue;
end;
function TJvSimpleXMLElems.LoadFromStream(const Stream: TStream; AParent: TJvSimpleXML): string;
var
I, lStreamPos, Count, lPos: Integer;
lBuf: array [0..cBufferSize - 1] of Char;
St: string;
Po: string;
lElem: TJvSimpleXMLElem;
begin
lStreamPos := Stream.Position;
Result := '';
Po := '';
St := '';
lPos := 0;
// We read from a stream, thus replacing the existing items
Clear;
repeat
Count := Stream.Read(lBuf, SizeOf(lBuf));
if AParent <> nil then
AParent.DoLoadProgress(Stream.Position, Stream.Size);
for I := 0 to Count - 1 do
begin
//Increment Stream pos for after comment
Inc(lStreamPos);
case lPos of
0: //We are waiting for a tag and thus avoiding spaces
begin
case lBuf[I] of
' ', Tab, Cr, Lf:
begin
end;
'<':
begin
lPos := 1;
St := lBuf[I];
end;
else
begin
//This is a text
lElem := TJvSimpleXMLElemText.Create(Parent);
Stream.Seek(lStreamPos - 1, soFromBeginning);
lElem.LoadFromStream(Stream);
lStreamPos := Stream.Position;
CreateElems;
FElems.AddObject(lElem.Name, lElem);
Break;
end;
end;
end;
1: //We are trying to determine the kind of the tag
begin
lElem := nil;
case lBuf[I] of
'/':
if St = '<' then
begin
lPos := 2;
St := '';
end
else
begin
lElem := TJvSimpleXMLElemClassic.Create(Parent);
St := St + lBuf[I];
end;
' ', '>', ':': //This should be a classic tag
begin
lElem := TJvSimpleXMLElemClassic.Create(Parent);
St := St + lBuf[I];
end;
else
begin
if (St <> '<![CDATA') or not (lBuf[i] in [' ', Tab, Cr, Lf]) then
St := St + lBuf[I];
if St = '<![CDATA[' then
lElem := TJvSimpleXMLElemCData.Create(Parent)
else
if St = '<!--' then
lElem := TJvSimpleXMLElemComment.Create(Parent);
//<?
end;
end;
if lElem <> nil then
begin
CreateElems;
Stream.Seek(lStreamPos - (Length(St)), soFromBeginning);
lElem.LoadFromStream(Stream);
lStreamPos := Stream.Position;
FElems.AddObject(lElem.Name, lElem);
St := '';
lPos := 0;
Break;
end;
end;
2: //This is an end tag
case lBuf[I] of
'>':
begin
if Po <> '' then
Result := Po + ':' + St
else
Result := St;
Count := 0;
Break;
end;
':':
begin
Po := St;
St := '';
end;
else
St := St + lBuf[I];
end;
end;
end;
until Count = 0;
Stream.Seek(lStreamPos, soFromBeginning);
end;
procedure TJvSimpleXMLElems.Notify(Value: TJvSimpleXMLElem;
Operation: TOperation);
begin
case Operation of
opRemove:
if Value.Container = Self then // Only remove if we have it
FElems.Delete(FElems.IndexOf(Value.Name));
opInsert:
Value.Container := Self;
end;
end;
procedure TJvSimpleXMLElems.SaveToStream(const Stream: TStream;
const Level: string; Parent: TJvSimpleXML);
var
I: Integer;
begin
for I := 0 to Count - 1 do
Item[I].SaveToStream(Stream, Level, Parent);
end;
function TJvSimpleXMLElems.Value(const Name: string; Default: string): string;
var
Elem: TJvSimpleXMLElem;
begin
Result := '';
Elem := GetItemNamedDefault(Name, Default);
if Elem = nil then
Result := Default
else
Result := Elem.Value;
end;
function SortItems(List: TStringList; Index1, Index2: Integer): Integer;
var
I: Integer;
begin
Result := 0;
for I := 0 to GSorts.Count - 1 do
if TJvSimpleXMLElems(GSorts[I]).FElems = List then
begin
Result := TJvSimpleXMLElems(GSorts[I]).FCompare(TJvSimpleXMLElems(GSorts[I]), Index1, Index2);
Break;
end;
end;
procedure TJvSimpleXMLElems.CustomSort(AFunction: TJvSimpleXMLElemCompare);
begin
if FElems <> nil then
begin
GSorts.Add(Self);
FCompare := AFunction;
FElems.CustomSort(SortItems);
GSorts.Remove(Self);
end;
end;
procedure TJvSimpleXMLElems.Sort;
begin
if FElems <> nil then
FElems.Sort;
end;
//=== { TJvSimpleXMLProps } ==================================================
function TJvSimpleXMLProps.Add(const Name, Value: string): TJvSimpleXMLProp;
var
Elem: TJvSimpleXMLProp;
begin
if FProperties = nil then
FProperties := THashedStringList.Create;
Elem := TJvSimpleXMLProp.Create();
FProperties.AddObject(Name, Elem);
Elem.FName := Name; //Avoid notification
Elem.Value := Value;
Elem.Parent := Self;
Result := Elem;
end;
function TJvSimpleXMLProps.Add(const Name: string; const Value: Int64): TJvSimpleXMLProp;
begin
Result := Add(Name, IntToStr(Value));
end;
function TJvSimpleXMLProps.Add(const Name: string; const Value: Boolean): TJvSimpleXMLProp;
begin
Result := Add(Name, BoolToStr(Value));
end;
function TJvSimpleXMLProps.BoolValue(const Name: string;
Default: Boolean): Boolean;
var
Prop: TJvSimpleXMLProp;
begin
try
Prop := GetItemNamedDefault(Name, BoolToStr(Default));
if (Prop = nil) or (Prop.Value = '') then
Result := Default
else
Result := Prop.BoolValue;
except
Result := Default;
end;
end;
procedure TJvSimpleXMLProps.Clear;
var
I: Integer;
begin
if FProperties <> nil then
begin
for I := 0 to FProperties.Count - 1 do
begin
TJvSimpleXMLProp(FProperties.Objects[I]).Free;
FProperties.Objects[I] := nil;
end;
FProperties.Clear;
end;
end;
procedure TJvSimpleXMLProps.Delete(const Index: Integer);
begin
if (FProperties <> nil) and (Index >= 0) and (Index < FProperties.Count) then
begin
TObject(FProperties.Objects[Index]).Free;
FProperties.Delete(Index);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -