📄 jvqsimplexml.pas
字号:
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;
lElem: TJvSimpleXMLElem;
begin
lStreamPos := Stream.Position;
Result := '';
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
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
if lBuf[I] = '>' then
begin
Result := St;
Count := 0;
Break;
end
else
St := St + lBuf[I];
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;
end;
constructor TJvSimpleXMLProps.Create(Parent: TJvSimpleXMLElem);
begin
inherited Create;
FParent := Parent;
end;
procedure TJvSimpleXMLProps.Delete(const Name: string);
begin
if FProperties <> nil then
Delete(FProperties.IndexOf(Name));
end;
destructor TJvSimpleXMLProps.Destroy;
begin
FParent := nil;
Clear;
FreeAndNil(FProperties);
inherited Destroy;
end;
procedure TJvSimpleXMLProps.DoItemRename(var Value: TJvSimpleXMLProp;
const Name: string);
var
I: Integer;
begin
if FProperties = nil then
Exit;
I := FProperties.IndexOfObject(Value);
if I <> -1 then
FProperties[I] := Name;
end;
procedure TJvSimpleXMLProps.Error(const S: string);
begin
raise EJvSimpleXMLError.Create(S);
end;
procedure TJvSimpleXMLProps.FmtError(const S: string;
const Args: array of const);
begin
Error(Format(S, Args));
end;
function TJvSimpleXMLProps.GetCount: Integer;
begin
if FProperties = nil then
Result := 0
else
Result := FProperties.Count;
end;
function TJvSimpleXMLProps.GetItem(const Index: Integer): TJvSimpleXMLProp;
begin
if FProperties <> nil then
Result := TJvSimpleXMLProp(FProperties.Objects[Index])
else
Result := nil;
end;
function TJvSimpleXMLProps.GetItemNamedDefault(const Name, Default: string): TJvSimpleXMLProp;
var
I: Integer;
begin
Result := nil;
if FProperties <> nil then
begin
I := FProperties.IndexOf(Name);
if I <> -1 then
Result := TJvSimpleXMLProp(FProperties.Objects[I])
else
if Assigned(FParent) and Assigned(FParent.SimpleXML) and (sxoAutoCreate in FParent.SimpleXML.Options) then
Result := Add(Name, Default);
end
else
if Assigned(FParent) and Assigned(FParent.SimpleXML) and (sxoAutoCreate in FParent.SimpleXML.Options) then
begin
Result := Add(Name, Default);
end;
end;
function TJvSimpleXMLProps.GetItemNamed(const Name: string): TJvSimpleXMLProp;
begin
Result := GetItemNamedDefault(Name, '');
end;
function TJvSimpleXMLProps.GetSimpleXML: TJvSimpleXML;
begin
if FParent <> nil then
Result := FParent.GetSimpleXML
else
Result := nil;
end;
function TJvSimpleXMLProps.IntValue(const Name: string; Default: Int64): Int64;
var
Prop: TJvSimpleXMLProp;
begin
Prop := GetItemNamedDefault(Name, IntToStr(Default));
if Prop = nil then
Result := Default
else
Result := Prop.IntValue;
end;
procedure TJvSimpleXMLProps.LoadFromStream(const Stream: TStream);
//<element Prop="foo" Prop='bar' foo:bar="beuh"/>
//Stop on / or ? or >
type
TPosType = (
ptWaiting,
ptReadingName,
ptStartingContent,
ptReadingValue,
ptSpaceBeforeEqual
);
var
lPos: TPosType;
I, lStreamPos, Count: Integer;
lBuf: array [0..cBufferSize - 1] of Char;
lName, lValue, lPointer: string;
lPropStart: Char;
begin
lStreamPos := Stream.Position;
lValue := '';
lPointer := '';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -