mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 06:49:13 +02:00
* xmlread.pp, remove FCursorStack and resort back to a single cursor node. But this time it is simply a local variable.
git-svn-id: trunk@16962 -
This commit is contained in:
parent
547a1b289c
commit
9ca12c0377
@ -254,7 +254,6 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
TNodeDataDynArray = array of TNodeData;
|
TNodeDataDynArray = array of TNodeData;
|
||||||
TDOMNodeDynArray = array of TDOMNode_WithChildren;
|
|
||||||
TValidatorDynArray = array of TElementValidator;
|
TValidatorDynArray = array of TElementValidator;
|
||||||
|
|
||||||
TXMLReadState = (rsProlog, rsDTD, rsAfterDTD, rsRoot, rsEpilog);
|
TXMLReadState = (rsProlog, rsDTD, rsAfterDTD, rsRoot, rsEpilog);
|
||||||
@ -348,7 +347,6 @@ type
|
|||||||
FPrefixedAttrs: Integer;
|
FPrefixedAttrs: Integer;
|
||||||
FSpecifiedAttrs: Integer;
|
FSpecifiedAttrs: Integer;
|
||||||
FNodeStack: TNodeDataDynArray;
|
FNodeStack: TNodeDataDynArray;
|
||||||
FCursorStack: TDOMNodeDynArray;
|
|
||||||
FValidators: TValidatorDynArray;
|
FValidators: TValidatorDynArray;
|
||||||
FAttrChunks: TFPList;
|
FAttrChunks: TFPList;
|
||||||
FFreeAttrChunk: PNodeData;
|
FFreeAttrChunk: PNodeData;
|
||||||
@ -378,20 +376,20 @@ type
|
|||||||
procedure ExpectAttValue(attrData: PNodeData; NonCDATA: Boolean); // [10]
|
procedure ExpectAttValue(attrData: PNodeData; NonCDATA: Boolean); // [10]
|
||||||
procedure ParseComment(discard: Boolean); // [15]
|
procedure ParseComment(discard: Boolean); // [15]
|
||||||
procedure ParsePI; // [16]
|
procedure ParsePI; // [16]
|
||||||
procedure CreatePINode;
|
function CreatePINode: TDOMNode;
|
||||||
procedure ParseXmlOrTextDecl(TextDecl: Boolean);
|
procedure ParseXmlOrTextDecl(TextDecl: Boolean);
|
||||||
procedure ExpectEq;
|
procedure ExpectEq;
|
||||||
procedure ParseDoctypeDecl; // [28]
|
procedure ParseDoctypeDecl; // [28]
|
||||||
procedure ParseMarkupDecl; // [29]
|
procedure ParseMarkupDecl; // [29]
|
||||||
procedure ParseStartTag; // [39]
|
procedure ParseStartTag; // [39]
|
||||||
procedure ParseEndTag; // [42]
|
procedure ParseEndTag; // [42]
|
||||||
procedure DoStartElement;
|
function DoStartElement: TDOMElement;
|
||||||
procedure HandleEntityStart;
|
procedure HandleEntityStart;
|
||||||
procedure HandleEntityEnd;
|
procedure HandleEntityEnd;
|
||||||
procedure ResolveEntity;
|
procedure ResolveEntity;
|
||||||
procedure DoStartEntity;
|
procedure DoStartEntity;
|
||||||
procedure ParseAttribute(ElDef: TElementDecl);
|
procedure ParseAttribute(ElDef: TElementDecl);
|
||||||
procedure ParseContent; // [43]
|
procedure ParseContent(parent: TDOMNode_WithChildren); // [43]
|
||||||
function Read: Boolean;
|
function Read: Boolean;
|
||||||
function ResolvePredefined: Boolean;
|
function ResolvePredefined: Boolean;
|
||||||
function EntityCheck(NoExternals: Boolean = False): TEntityDecl;
|
function EntityCheck(NoExternals: Boolean = False): TEntityDecl;
|
||||||
@ -422,12 +420,8 @@ type
|
|||||||
procedure ValidationErrorWithName(const Msg: string; LineOffs: Integer = -1);
|
procedure ValidationErrorWithName(const Msg: string; LineOffs: Integer = -1);
|
||||||
procedure DTDReloadHook;
|
procedure DTDReloadHook;
|
||||||
procedure ConvertSource(SrcIn: TXMLInputSource; out SrcOut: TXMLCharSource);
|
procedure ConvertSource(SrcIn: TXMLInputSource; out SrcOut: TXMLCharSource);
|
||||||
// Some SAX-alike stuff (at a very early stage)
|
function DoCDSect(ch: PWideChar; Count: Integer): TDOMNode;
|
||||||
procedure DoText(ch: PWideChar; Count: Integer; Whitespace: Boolean=False);
|
|
||||||
procedure DoComment(ch: PWideChar; Count: Integer);
|
|
||||||
procedure DoCDSect(ch: PWideChar; Count: Integer);
|
|
||||||
procedure DoNotationDecl(const aName, aPubID, aSysID: WideString);
|
procedure DoNotationDecl(const aName, aPubID, aSysID: WideString);
|
||||||
procedure DoEntityReference;
|
|
||||||
public
|
public
|
||||||
doc: TDOMDocument;
|
doc: TDOMDocument;
|
||||||
constructor Create; overload;
|
constructor Create; overload;
|
||||||
@ -1248,7 +1242,6 @@ begin
|
|||||||
FNamePages := @NamePages;
|
FNamePages := @NamePages;
|
||||||
SetLength(FNodeStack, 16);
|
SetLength(FNodeStack, 16);
|
||||||
SetLength(FValidators, 16);
|
SetLength(FValidators, 16);
|
||||||
SetLength(FCursorStack, 16);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TXMLReader.Create(AParser: TDOMParser);
|
constructor TXMLReader.Create(AParser: TDOMParser);
|
||||||
@ -1324,14 +1317,14 @@ begin
|
|||||||
FState := rsProlog;
|
FState := rsProlog;
|
||||||
FNesting := 0;
|
FNesting := 0;
|
||||||
FCurrNode := @FNodeStack[0];
|
FCurrNode := @FNodeStack[0];
|
||||||
FCursorStack[0] := doc;
|
|
||||||
FFragmentMode := False;
|
FFragmentMode := False;
|
||||||
NSPrepare;
|
NSPrepare;
|
||||||
Initialize(ASource);
|
Initialize(ASource);
|
||||||
if FSource.FXMLVersion <> xmlVersionUnknown then
|
if FSource.FXMLVersion <> xmlVersionUnknown then
|
||||||
TDOMTopNodeEx(TDOMNode(doc)).FXMLVersion := FSource.FXMLVersion;
|
TDOMTopNodeEx(TDOMNode(doc)).FXMLVersion := FSource.FXMLVersion;
|
||||||
TDOMTopNodeEx(TDOMNode(doc)).FXMLEncoding := FSource.FXMLEncoding;
|
TDOMTopNodeEx(TDOMNode(doc)).FXMLEncoding := FSource.FXMLEncoding;
|
||||||
ParseContent;
|
FNext := xtText;
|
||||||
|
ParseContent(doc);
|
||||||
|
|
||||||
if FState < rsRoot then
|
if FState < rsRoot then
|
||||||
FatalError('Root element is missing');
|
FatalError('Root element is missing');
|
||||||
@ -1352,7 +1345,6 @@ begin
|
|||||||
FState := rsRoot;
|
FState := rsRoot;
|
||||||
FNesting := 0;
|
FNesting := 0;
|
||||||
FCurrNode := @FNodeStack[0];
|
FCurrNode := @FNodeStack[0];
|
||||||
FCursorStack[0] := AOwner as TDOMNode_WithChildren;
|
|
||||||
FFragmentMode := True;
|
FFragmentMode := True;
|
||||||
FXML11 := doc.InheritsFrom(TXMLDocument) and (TXMLDocument(doc).XMLVersion = '1.1');
|
FXML11 := doc.InheritsFrom(TXMLDocument) and (TXMLDocument(doc).XMLVersion = '1.1');
|
||||||
NSPrepare;
|
NSPrepare;
|
||||||
@ -1369,7 +1361,8 @@ begin
|
|||||||
TDOMTopNodeEx(AOwner).FXMLVersion := FSource.FXMLVersion;
|
TDOMTopNodeEx(AOwner).FXMLVersion := FSource.FXMLVersion;
|
||||||
TDOMTopNodeEx(AOwner).FXMLEncoding := FSource.FXMLEncoding;
|
TDOMTopNodeEx(AOwner).FXMLEncoding := FSource.FXMLEncoding;
|
||||||
end;
|
end;
|
||||||
ParseContent;
|
FNext := xtText;
|
||||||
|
ParseContent(aOwner as TDOMNode_WithChildren);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TXMLReader.CheckName(aFlags: TCheckNameFlags): Boolean;
|
function TXMLReader.CheckName(aFlags: TCheckNameFlags): Boolean;
|
||||||
@ -1929,17 +1922,13 @@ begin
|
|||||||
FNameTable.FindOrAdd(FName.Buffer, FName.Length));
|
FNameTable.FindOrAdd(FName.Buffer, FName.Length));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLReader.CreatePINode;
|
function TXMLReader.CreatePINode: TDOMNode;
|
||||||
var
|
var
|
||||||
NameStr, ValueStr: WideString;
|
NameStr, ValueStr: WideString;
|
||||||
PINode: TDOMProcessingInstruction;
|
|
||||||
begin
|
begin
|
||||||
SetString(NameStr, FName.Buffer, FName.Length);
|
SetString(NameStr, FName.Buffer, FName.Length);
|
||||||
SetString(ValueStr, FValue.Buffer, FValue.Length);
|
SetString(ValueStr, FValue.Buffer, FValue.Length);
|
||||||
// SAX: ContentHandler.ProcessingInstruction(Name, Value);
|
result := Doc.CreateProcessingInstruction(NameStr, ValueStr);
|
||||||
|
|
||||||
PINode := Doc.CreateProcessingInstruction(NameStr, ValueStr);
|
|
||||||
FCursorStack[FNesting].InternalAppend(PINode);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -2550,7 +2539,7 @@ begin
|
|||||||
if FSource.FBuf^ = '?' then
|
if FSource.FBuf^ = '?' then
|
||||||
begin
|
begin
|
||||||
ParsePI;
|
ParsePI;
|
||||||
CreatePINode;
|
doc.AppendChild(CreatePINode);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@ -2764,11 +2753,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLReader.DoEntityReference;
|
|
||||||
begin
|
|
||||||
FCursorStack[FNesting].AppendChild(doc.CreateEntityReference(FCurrNode^.FQName^.Key));
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TXMLReader.HandleEntityStart;
|
procedure TXMLReader.HandleEntityStart;
|
||||||
begin
|
begin
|
||||||
{ FNesting+1 is available due to overallocation in AllocNodeData() }
|
{ FNesting+1 is available due to overallocation in AllocNodeData() }
|
||||||
@ -2782,7 +2766,6 @@ end;
|
|||||||
procedure TXMLReader.HandleEntityEnd;
|
procedure TXMLReader.HandleEntityEnd;
|
||||||
begin
|
begin
|
||||||
FValidators[FNesting-1] := FValidators[FNesting];
|
FValidators[FNesting-1] := FValidators[FNesting];
|
||||||
FCursorStack[FNesting-1] := FCursorStack[FNesting];
|
|
||||||
ContextPop(True);
|
ContextPop(True);
|
||||||
PopVC;
|
PopVC;
|
||||||
FCurrNode := @FNodeStack[FNesting+1];
|
FCurrNode := @FNodeStack[FNesting+1];
|
||||||
@ -2817,31 +2800,27 @@ begin
|
|||||||
|
|
||||||
{ Compensate for an extra entry in node stack }
|
{ Compensate for an extra entry in node stack }
|
||||||
FValidators[FNesting] := FValidators[FNesting-1];
|
FValidators[FNesting] := FValidators[FNesting-1];
|
||||||
FCursorStack[FNesting] := FCursorStack[FNesting-1];
|
|
||||||
UpdateConstraints;
|
UpdateConstraints;
|
||||||
FNext := xtText;
|
FNext := xtText;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLReader.DoStartElement;
|
function TXMLReader.DoStartElement: TDOMElement;
|
||||||
var
|
var
|
||||||
NewElem: TDOMElement;
|
|
||||||
Attr: TDOMAttr;
|
Attr: TDOMAttr;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
with FCurrNode^.FQName^ do
|
with FCurrNode^.FQName^ do
|
||||||
NewElem := doc.CreateElementBuf(PWideChar(Key), Length(Key));
|
Result := doc.CreateElementBuf(PWideChar(Key), Length(Key));
|
||||||
FCursorStack[FNesting-1].InternalAppend(NewElem);
|
|
||||||
FCursorStack[FNesting] := NewElem;
|
|
||||||
if Assigned(FCurrNode^.FNsUri) then
|
if Assigned(FCurrNode^.FNsUri) then
|
||||||
NewElem.SetNSI(FCurrNode^.FNsUri^.Key, FCurrNode^.FColonPos+1);
|
Result.SetNSI(FCurrNode^.FNsUri^.Key, FCurrNode^.FColonPos+1);
|
||||||
|
|
||||||
for i := 1 to FAttrCount do
|
for i := 1 to FAttrCount do
|
||||||
begin
|
begin
|
||||||
Attr := LoadAttribute(doc, @FNodeStack[FNesting+i]);
|
Attr := LoadAttribute(doc, @FNodeStack[FNesting+i]);
|
||||||
NewElem.SetAttributeNode(Attr);
|
Result.SetAttributeNode(Attr);
|
||||||
// Attach element to ID map entry if necessary
|
// Attach element to ID map entry if necessary
|
||||||
if Assigned(FNodeStack[FNesting+i].FIDEntry) then
|
if Assigned(FNodeStack[FNesting+i].FIDEntry) then
|
||||||
FNodeStack[FNesting+i].FIDEntry^.Data := NewElem;
|
FNodeStack[FNesting+i].FIDEntry^.Data := Result;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2898,33 +2877,57 @@ const
|
|||||||
ntText
|
ntText
|
||||||
);
|
);
|
||||||
|
|
||||||
procedure TXMLReader.ParseContent;
|
procedure TXMLReader.ParseContent(parent: TDOMNode_WithChildren);
|
||||||
|
var
|
||||||
|
cursor: TDOMNode_WithChildren;
|
||||||
|
element: TDOMElement;
|
||||||
begin
|
begin
|
||||||
FNext := xtText;
|
cursor := parent;
|
||||||
while Read do
|
while Read do
|
||||||
begin
|
begin
|
||||||
if FValidate then
|
if FValidate then
|
||||||
ValidateCurrentNode;
|
ValidateCurrentNode;
|
||||||
|
|
||||||
case FCurrNode^.FNodeType of
|
case FCurrNode^.FNodeType of
|
||||||
ntText, ntWhitespace:
|
ntText:
|
||||||
DoText(FValue.Buffer, FValue.Length, FCurrNode^.FNodeType = ntWhitespace);
|
cursor.InternalAppend(doc.CreateTextNodeBuf(FValue.Buffer, FValue.Length, False));
|
||||||
|
|
||||||
|
ntWhitespace:
|
||||||
|
if FPreserveWhitespace then
|
||||||
|
cursor.InternalAppend(doc.CreateTextNodeBuf(FValue.Buffer, FValue.Length, FCurrContentType = ctChildren))
|
||||||
|
else
|
||||||
|
Continue;
|
||||||
|
|
||||||
ntCDATA:
|
ntCDATA:
|
||||||
DoCDSect(FValue.Buffer, FValue.Length);
|
cursor.InternalAppend(DoCDSect(FValue.Buffer, FValue.Length));
|
||||||
|
|
||||||
ntProcessingInstruction:
|
ntProcessingInstruction:
|
||||||
CreatePINode;
|
cursor.InternalAppend(CreatePINode);
|
||||||
|
|
||||||
ntComment:
|
ntComment:
|
||||||
DoComment(FCurrNode^.FValueStart, FCurrNode^.FValueLength);
|
if FIgnoreComments then
|
||||||
|
Continue
|
||||||
|
else
|
||||||
|
cursor.InternalAppend(doc.CreateCommentBuf(FCurrNode^.FValueStart, FCurrNode^.FValueLength));
|
||||||
ntElement:
|
ntElement:
|
||||||
DoStartElement;
|
|
||||||
ntEndElement:
|
|
||||||
;
|
|
||||||
ntDocumentType:
|
|
||||||
begin
|
begin
|
||||||
if not FCanonical then
|
element := DoStartElement;
|
||||||
doc.AppendChild(TDOMDocumentType.Create(doc, FDocType));
|
cursor.InternalAppend(element);
|
||||||
|
cursor := element;
|
||||||
|
Continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
ntEndElement:
|
||||||
|
cursor := TDOMNode_WithChildren(cursor.ParentNode);
|
||||||
|
|
||||||
|
ntDocumentType:
|
||||||
|
if FCanonical then
|
||||||
|
Continue
|
||||||
|
else
|
||||||
|
cursor.InternalAppend(TDOMDocumentType.Create(doc, FDocType));
|
||||||
|
|
||||||
ntEntityReference:
|
ntEntityReference:
|
||||||
DoEntityReference;
|
cursor.InternalAppend(doc.CreateEntityReference(FCurrNode^.FQName^.Key));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -3080,6 +3083,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
if FValue.Length <> 0 then
|
if FValue.Length <> 0 then
|
||||||
begin
|
begin
|
||||||
|
if FState <> rsRoot then
|
||||||
|
if nonWs then
|
||||||
|
FatalError('Illegal at document level', -1)
|
||||||
|
else
|
||||||
|
Break;
|
||||||
|
|
||||||
SetNodeInfoWithValue(textNodeTypes[nonWs]);
|
SetNodeInfoWithValue(textNodeTypes[nonWs]);
|
||||||
FNext := tok;
|
FNext := tok;
|
||||||
Result := True;
|
Result := True;
|
||||||
@ -3538,42 +3547,15 @@ begin
|
|||||||
DoErrorPos(esError, 'Notation ''%s'' is not declared', [Value], Loc);
|
DoErrorPos(esError, 'Notation ''%s'' is not declared', [Value], Loc);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLReader.DoText(ch: PWideChar; Count: Integer; Whitespace: Boolean);
|
|
||||||
var
|
|
||||||
TextNode: TDOMText;
|
|
||||||
begin
|
|
||||||
if FState <> rsRoot then
|
|
||||||
if not Whitespace then
|
|
||||||
FatalError('Illegal at document level', -1)
|
|
||||||
else
|
|
||||||
Exit;
|
|
||||||
|
|
||||||
if (Whitespace and (not FPreserveWhitespace)) or (Count = 0) then
|
function TXMLReader.DoCDSect(ch: PWideChar; Count: Integer): TDOMNode;
|
||||||
Exit;
|
|
||||||
|
|
||||||
TextNode := Doc.CreateTextNodeBuf(ch, Count, Whitespace and (FCurrContentType = ctChildren));
|
|
||||||
FCursorStack[FNesting].InternalAppend(TextNode);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TXMLReader.DoComment(ch: PWideChar; Count: Integer);
|
|
||||||
var
|
|
||||||
Node: TDOMComment;
|
|
||||||
begin
|
|
||||||
if (not FIgnoreComments) and (FState <> rsDTD) then
|
|
||||||
begin
|
|
||||||
Node := Doc.CreateCommentBuf(ch, Count);
|
|
||||||
FCursorStack[FNesting].InternalAppend(Node);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TXMLReader.DoCDSect(ch: PWideChar; Count: Integer);
|
|
||||||
var
|
var
|
||||||
s: WideString;
|
s: WideString;
|
||||||
begin
|
begin
|
||||||
Assert(not FCDSectionsAsText, 'Should not be called when CDSectionsAsText=True');
|
Assert(not FCDSectionsAsText, 'Should not be called when CDSectionsAsText=True');
|
||||||
|
|
||||||
SetString(s, ch, Count);
|
SetString(s, ch, Count);
|
||||||
FCursorStack[FNesting].InternalAppend(doc.CreateCDATASection(s));
|
result := doc.CreateCDATASection(s);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLReader.DoNotationDecl(const aName, aPubID, aSysID: WideString);
|
procedure TXMLReader.DoNotationDecl(const aName, aPubID, aSysID: WideString);
|
||||||
@ -3695,9 +3677,8 @@ begin
|
|||||||
FCurrNode^.FNsUri := nil;
|
FCurrNode^.FNsUri := nil;
|
||||||
FCurrNode^.FIDEntry := nil;
|
FCurrNode^.FIDEntry := nil;
|
||||||
|
|
||||||
if FNesting >= Length(FCursorStack) then
|
if FNesting >= Length(FValidators) then
|
||||||
begin
|
begin
|
||||||
SetLength(FCursorStack, FNesting * 2);
|
|
||||||
SetLength(FValidators, FNesting * 2);
|
SetLength(FValidators, FNesting * 2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user