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