mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 16:19:21 +02:00
* fcl-xml, making progress with streaming API, implemented IXmlLineInfo interface and fixed reported locations for attributes and their child nodes.
+ Set Name and Value properties for DocumentType nodes. * Unified HandleEntityStart and HandleEntityEnd code for entity references in content and in attributes. git-svn-id: trunk@20524 -
This commit is contained in:
parent
c1531f5c12
commit
c2a2f88bd4
@ -268,7 +268,7 @@ type
|
|||||||
|
|
||||||
TLiteralType = (ltPlain, ltPubid, ltEntity);
|
TLiteralType = (ltPlain, ltPubid, ltEntity);
|
||||||
|
|
||||||
TXMLTextReader = class(TXMLReader)
|
TXMLTextReader = class(TXMLReader, IXmlLineInfo)
|
||||||
private
|
private
|
||||||
FSource: TXMLCharSource;
|
FSource: TXMLCharSource;
|
||||||
FNameTable: THashTable;
|
FNameTable: THashTable;
|
||||||
@ -341,6 +341,9 @@ type
|
|||||||
procedure SetNodeInfoWithValue(typ: TXMLNodeType; AName: PHashItem = nil);
|
procedure SetNodeInfoWithValue(typ: TXMLNodeType; AName: PHashItem = nil);
|
||||||
function SetupFakeLF(nextstate: TXMLToken): Boolean;
|
function SetupFakeLF(nextstate: TXMLToken): Boolean;
|
||||||
function AddId(aNodeData: PNodeData): Boolean;
|
function AddId(aNodeData: PNodeData): Boolean;
|
||||||
|
function QueryInterface(constref iid: TGUID; out obj): HRESULT; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
|
||||||
|
function _AddRef: Longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
|
||||||
|
function _Release: Longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
|
||||||
protected
|
protected
|
||||||
FNesting: Integer;
|
FNesting: Integer;
|
||||||
FCurrNode: PNodeData;
|
FCurrNode: PNodeData;
|
||||||
@ -392,6 +395,7 @@ type
|
|||||||
procedure ParseAttribute(ElDef: TElementDecl);
|
procedure ParseAttribute(ElDef: TElementDecl);
|
||||||
function ReadTopLevel: Boolean;
|
function ReadTopLevel: Boolean;
|
||||||
procedure NextAttrValueChunk;
|
procedure NextAttrValueChunk;
|
||||||
|
function GetHasLineInfo: Boolean;
|
||||||
function GetLineNumber: Integer;
|
function GetLineNumber: Integer;
|
||||||
function GetLinePosition: Integer;
|
function GetLinePosition: Integer;
|
||||||
public
|
public
|
||||||
@ -1000,6 +1004,24 @@ end;
|
|||||||
|
|
||||||
{ TXMLTextReader }
|
{ TXMLTextReader }
|
||||||
|
|
||||||
|
function TXMLTextReader.QueryInterface(constref iid: TGUID; out obj): HRESULT; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
|
||||||
|
begin
|
||||||
|
if GetInterface(iid,obj) then
|
||||||
|
result := S_OK
|
||||||
|
else
|
||||||
|
result:= E_NOINTERFACE;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TXMLTextReader._AddRef: Longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
|
||||||
|
begin
|
||||||
|
result := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TXMLTextReader._Release: Longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
|
||||||
|
begin
|
||||||
|
result := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TXMLTextReader.ConvertSource(SrcIn: TXMLInputSource; out SrcOut: TXMLCharSource);
|
procedure TXMLTextReader.ConvertSource(SrcIn: TXMLInputSource; out SrcOut: TXMLCharSource);
|
||||||
begin
|
begin
|
||||||
SrcOut := nil;
|
SrcOut := nil;
|
||||||
@ -1746,9 +1768,12 @@ var
|
|||||||
start: TObject;
|
start: TObject;
|
||||||
curr: PNodeData;
|
curr: PNodeData;
|
||||||
StartPos: Integer;
|
StartPos: Integer;
|
||||||
|
StartLoc: TLocation;
|
||||||
entName: PHashItem;
|
entName: PHashItem;
|
||||||
begin
|
begin
|
||||||
SkipQuote(Delim);
|
SkipQuote(Delim);
|
||||||
|
AttrData^.FLoc2 := FTokenStart;
|
||||||
|
StartLoc := FTokenStart;
|
||||||
curr := AttrData;
|
curr := AttrData;
|
||||||
FValue.Length := 0;
|
FValue.Length := 0;
|
||||||
StartPos := 0;
|
StartPos := 0;
|
||||||
@ -1767,10 +1792,16 @@ begin
|
|||||||
if ((ent = nil) or (not FExpandEntities)) and (FSource.FEntity = start) then
|
if ((ent = nil) or (not FExpandEntities)) and (FSource.FEntity = start) then
|
||||||
begin
|
begin
|
||||||
if FValue.Length > StartPos then
|
if FValue.Length > StartPos then
|
||||||
|
begin
|
||||||
AllocAttributeValueChunk(curr, StartPos);
|
AllocAttributeValueChunk(curr, StartPos);
|
||||||
|
curr^.FLoc := StartLoc;
|
||||||
|
end;
|
||||||
AllocAttributeValueChunk(curr, FValue.Length);
|
AllocAttributeValueChunk(curr, FValue.Length);
|
||||||
curr^.FNodeType := ntEntityReference;
|
curr^.FNodeType := ntEntityReference;
|
||||||
curr^.FQName := entName;
|
curr^.FQName := entName;
|
||||||
|
StoreLocation(StartLoc);
|
||||||
|
curr^.FLoc := StartLoc;
|
||||||
|
Dec(curr^.FLoc.LinePos, FName.Length+1);
|
||||||
end;
|
end;
|
||||||
StartPos := FValue.Length;
|
StartPos := FValue.Length;
|
||||||
if Assigned(ent) then
|
if Assigned(ent) then
|
||||||
@ -1796,7 +1827,10 @@ begin
|
|||||||
begin
|
begin
|
||||||
FAttrCleanupFlag := True;
|
FAttrCleanupFlag := True;
|
||||||
if FValue.Length > StartPos then
|
if FValue.Length > StartPos then
|
||||||
|
begin
|
||||||
AllocAttributeValueChunk(curr, StartPos);
|
AllocAttributeValueChunk(curr, StartPos);
|
||||||
|
curr^.FLoc := StartLoc;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
if nonCDATA then
|
if nonCDATA then
|
||||||
BufNormalize(FValue, attrData^.FDenormalized)
|
BufNormalize(FValue, attrData^.FDenormalized)
|
||||||
@ -2193,6 +2227,7 @@ end;
|
|||||||
procedure TXMLTextReader.ParseDoctypeDecl; // [28]
|
procedure TXMLTextReader.ParseDoctypeDecl; // [28]
|
||||||
var
|
var
|
||||||
Src: TXMLCharSource;
|
Src: TXMLCharSource;
|
||||||
|
DTDName: PHashItem;
|
||||||
begin
|
begin
|
||||||
if FState >= rsDTD then
|
if FState >= rsDTD then
|
||||||
FatalError('Markup declaration is not allowed here');
|
FatalError('Markup declaration is not allowed here');
|
||||||
@ -2208,6 +2243,7 @@ begin
|
|||||||
|
|
||||||
CheckName;
|
CheckName;
|
||||||
SetString(FDocType.FName, FName.Buffer, FName.Length);
|
SetString(FDocType.FName, FName.Buffer, FName.Length);
|
||||||
|
DTDName := FNameTable.FindOrAdd(FName.Buffer, FName.Length);
|
||||||
SkipS(True);
|
SkipS(True);
|
||||||
ParseExternalID(FDocType.FSystemID, FDocType.FPublicID, False);
|
ParseExternalID(FDocType.FSystemID, FDocType.FPublicID, False);
|
||||||
SkipS;
|
SkipS;
|
||||||
@ -2249,7 +2285,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
FState := rsAfterDTD;
|
FState := rsAfterDTD;
|
||||||
FCurrNode^.FNodeType := ntDocumentType;
|
FValue.Length := 0;
|
||||||
|
BufAppendString(FValue, FDocType.FInternalSubset);
|
||||||
|
SetNodeInfoWithValue(ntDocumentType, DTDName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLTextReader.ExpectEq; // [25]
|
procedure TXMLTextReader.ExpectEq; // [25]
|
||||||
@ -2792,6 +2830,8 @@ end;
|
|||||||
procedure TXMLTextReader.Close;
|
procedure TXMLTextReader.Close;
|
||||||
begin
|
begin
|
||||||
FReadState := rsClosed;
|
FReadState := rsClosed;
|
||||||
|
FTokenStart.Line := 0;
|
||||||
|
FTokenStart.LinePos := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TXMLTextReader.GetAttributeCount: Integer;
|
function TXMLTextReader.GetAttributeCount: Integer;
|
||||||
@ -2882,14 +2922,27 @@ begin
|
|||||||
result := FSource.SystemID;
|
result := FSource.SystemID;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ IXmlLineInfo methods }
|
||||||
|
|
||||||
|
function TXMLTextReader.GetHasLineInfo: Boolean;
|
||||||
|
begin
|
||||||
|
result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
function TXMLTextReader.GetLineNumber: Integer;
|
function TXMLTextReader.GetLineNumber: Integer;
|
||||||
begin
|
begin
|
||||||
result := FCurrNode^.FLoc.Line;
|
if (FCurrNode^.FNodeType in [ntElement,ntAttribute]) or (FAttrReadState <> arsNone) then
|
||||||
|
result := FCurrNode^.FLoc.Line
|
||||||
|
else
|
||||||
|
result := FTokenStart.Line;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TXMLTextReader.GetLinePosition: Integer;
|
function TXMLTextReader.GetLinePosition: Integer;
|
||||||
begin
|
begin
|
||||||
result := FCurrNode^.FLoc.LinePos;
|
if (FCurrNode^.FNodeType in [ntElement,ntAttribute]) or (FAttrReadState <> arsNone) then
|
||||||
|
result := FCurrNode^.FLoc.LinePos
|
||||||
|
else
|
||||||
|
result := FTokenStart.LinePos;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TXMLTextReader.LookupNamespace(const APrefix: XMLString): XMLString;
|
function TXMLTextReader.LookupNamespace(const APrefix: XMLString): XMLString;
|
||||||
@ -2999,6 +3052,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
FCurrNode := @FNodeStack[FNesting+FAttrCount+1];
|
FCurrNode := @FNodeStack[FNesting+FAttrCount+1];
|
||||||
|
StoreLocation(FCurrNode^.FLoc);
|
||||||
FValue.Length := 0;
|
FValue.Length := 0;
|
||||||
if FAttrReadState = arsText then
|
if FAttrReadState = arsText then
|
||||||
repeat
|
repeat
|
||||||
@ -3033,19 +3087,12 @@ begin
|
|||||||
|
|
||||||
if tok = arsEntity then
|
if tok = arsEntity then
|
||||||
begin
|
begin
|
||||||
FCurrNode^.FNodeType := ntEntityReference;
|
HandleEntityStart;
|
||||||
FCurrNode^.FQName := FNameTable.FindOrAdd(FName.Buffer, FName.Length);
|
|
||||||
FCurrNode^.FValueStart := nil;
|
|
||||||
FCurrNode^.FValueLength := 0;
|
|
||||||
FCurrNode^.FValueStr := '';
|
|
||||||
FAttrReadState := arsText;
|
FAttrReadState := arsText;
|
||||||
end
|
end
|
||||||
else if tok = arsEntityEnd then
|
else if tok = arsEntityEnd then
|
||||||
begin
|
begin
|
||||||
ContextPop(True);
|
HandleEntityEnd;
|
||||||
Dec(FNesting);
|
|
||||||
FCurrNode := @FNodeStack[FNesting+FAttrCount+1];
|
|
||||||
FCurrNode^.FNodeType := ntEndEntity;
|
|
||||||
FAttrReadState := arsText;
|
FAttrReadState := arsText;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -3219,21 +3266,26 @@ end;
|
|||||||
|
|
||||||
procedure TXMLTextReader.HandleEntityStart;
|
procedure TXMLTextReader.HandleEntityStart;
|
||||||
begin
|
begin
|
||||||
FCurrNode := @FNodeStack[FNesting];
|
FCurrNode := @FNodeStack[FNesting+(FAttrCount+1)*ord(FAttrReadState<>arsNone)];
|
||||||
FCurrNode^.FNodeType := ntEntityReference;
|
FCurrNode^.FNodeType := ntEntityReference;
|
||||||
FCurrNode^.FQName := FNameTable.FindOrAdd(FName.Buffer, FName.Length);
|
FCurrNode^.FQName := FNameTable.FindOrAdd(FName.Buffer, FName.Length);
|
||||||
|
FCurrNode^.FColonPos := -1;
|
||||||
FCurrNode^.FValueStart := nil;
|
FCurrNode^.FValueStart := nil;
|
||||||
FCurrNode^.FValueLength := 0;
|
FCurrNode^.FValueLength := 0;
|
||||||
|
FCurrNode^.FValueStr := '';
|
||||||
|
StoreLocation(FCurrNode^.FLoc);
|
||||||
|
{ point past '&' to first char of entity name }
|
||||||
|
Dec(FCurrNode^.FLoc.LinePos, FName.Length+1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLTextReader.HandleEntityEnd;
|
procedure TXMLTextReader.HandleEntityEnd;
|
||||||
begin
|
begin
|
||||||
ContextPop(True);
|
ContextPop(True);
|
||||||
if FNesting > 0 then Dec(FNesting);
|
if FNesting > 0 then Dec(FNesting);
|
||||||
FCurrNode := @FNodeStack[FNesting];
|
FCurrNode := @FNodeStack[FNesting+(FAttrCount+1)*ord(FAttrReadState<>arsNone)];
|
||||||
FCurrNode^.FNodeType := ntEndEntity;
|
FCurrNode^.FNodeType := ntEndEntity;
|
||||||
// TODO: other properties of FCurrNode
|
{ point to trailing ';' }
|
||||||
FNext := xtText;
|
Inc(FCurrNode^.FLoc.LinePos, Length(FCurrNode^.FQName^.Key));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLTextReader.ResolveEntity;
|
procedure TXMLTextReader.ResolveEntity;
|
||||||
@ -3252,6 +3304,7 @@ begin
|
|||||||
if n <> FCurrNode then
|
if n <> FCurrNode then
|
||||||
n^ := FCurrNode^;
|
n^ := FCurrNode^;
|
||||||
|
|
||||||
|
ent := nil;
|
||||||
if Assigned(FDocType) then
|
if Assigned(FDocType) then
|
||||||
ent := FDocType.Entities.Get(PWideChar(n^.FQName^.Key),Length(n^.FQName^.Key)) as TEntityDecl;
|
ent := FDocType.Entities.Get(PWideChar(n^.FQName^.Key),Length(n^.FQName^.Key)) as TEntityDecl;
|
||||||
if ent = nil then
|
if ent = nil then
|
||||||
@ -3754,6 +3807,8 @@ begin
|
|||||||
|
|
||||||
FCurrNode := @FNodeStack[FNesting]; // move off the possible child
|
FCurrNode := @FNodeStack[FNesting]; // move off the possible child
|
||||||
FCurrNode^.FNodeType := ntEndElement;
|
FCurrNode^.FNodeType := ntEndElement;
|
||||||
|
Inc(FTokenStart.LinePos, 2); // move over '</' chars
|
||||||
|
FCurrNode^.FLoc := FTokenStart;
|
||||||
ElName := FCurrNode^.FQName;
|
ElName := FCurrNode^.FQName;
|
||||||
|
|
||||||
CheckName;
|
CheckName;
|
||||||
@ -3766,7 +3821,6 @@ begin
|
|||||||
SkipS;
|
SkipS;
|
||||||
ExpectChar('>');
|
ExpectChar('>');
|
||||||
end;
|
end;
|
||||||
Inc(FTokenStart.LinePos, 2); // move over '</' chars
|
|
||||||
FNext := xtPopElement;
|
FNext := xtPopElement;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3822,7 +3876,6 @@ begin
|
|||||||
|
|
||||||
ExpectEq;
|
ExpectEq;
|
||||||
ExpectAttValue(attrData, Assigned(AttDef) and (AttDef.DataType <> dtCDATA));
|
ExpectAttValue(attrData, Assigned(AttDef) and (AttDef.DataType <> dtCDATA));
|
||||||
attrData^.FLoc2 := FTokenStart;
|
|
||||||
|
|
||||||
if Assigned(attrData^.FNsUri) then
|
if Assigned(attrData^.FNsUri) then
|
||||||
begin
|
begin
|
||||||
|
@ -147,6 +147,15 @@ type
|
|||||||
LinePos: Integer;
|
LinePos: Integer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
IXmlLineInfo = interface(IInterface)['{FD0A892B-B26C-4954-9995-103B2A9D178A}']
|
||||||
|
function GetHasLineInfo: Boolean;
|
||||||
|
function GetLineNumber: Integer;
|
||||||
|
function GetLinePosition: Integer;
|
||||||
|
property HasLineInfo: Boolean read GetHasLineInfo;
|
||||||
|
property LineNumber: Integer read GetLineNumber;
|
||||||
|
property LinePosition: Integer read GetLinePosition;
|
||||||
|
end;
|
||||||
|
|
||||||
{ generic node info record, shared between DOM and reader }
|
{ generic node info record, shared between DOM and reader }
|
||||||
|
|
||||||
PNodeData = ^TNodeData;
|
PNodeData = ^TNodeData;
|
||||||
|
Loading…
Reference in New Issue
Block a user