mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 16:09:17 +02:00
* xmlread.pp: separated DOM-specific code into DoStartElement(); introduced FNameTable.
git-svn-id: trunk@16270 -
This commit is contained in:
parent
4e39959ca1
commit
b066395a2b
@ -280,6 +280,7 @@ type
|
|||||||
TXMLReader = class
|
TXMLReader = class
|
||||||
private
|
private
|
||||||
FSource: TXMLCharSource;
|
FSource: TXMLCharSource;
|
||||||
|
FNameTable: THashTable;
|
||||||
FCtrl: TDOMParser;
|
FCtrl: TDOMParser;
|
||||||
FXML11: Boolean;
|
FXML11: Boolean;
|
||||||
FState: TXMLReadState;
|
FState: TXMLReadState;
|
||||||
@ -394,6 +395,7 @@ type
|
|||||||
procedure ParseMarkupDecl; // [29]
|
procedure ParseMarkupDecl; // [29]
|
||||||
procedure ParseStartTag; // [39]
|
procedure ParseStartTag; // [39]
|
||||||
procedure ParseEndTag; // [42]
|
procedure ParseEndTag; // [42]
|
||||||
|
procedure DoStartElement;
|
||||||
procedure DoEndElement;
|
procedure DoEndElement;
|
||||||
procedure ParseAttribute(ElDef: TElementDecl);
|
procedure ParseAttribute(ElDef: TElementDecl);
|
||||||
procedure ParseContent; // [43]
|
procedure ParseContent; // [43]
|
||||||
@ -1313,8 +1315,8 @@ begin
|
|||||||
FStdPrefix_xml := FNSHelper.GetPrefix(@PrefixDefault, 3);
|
FStdPrefix_xml := FNSHelper.GetPrefix(@PrefixDefault, 3);
|
||||||
FStdPrefix_xmlns := FNSHelper.GetPrefix(@PrefixDefault, 5);
|
FStdPrefix_xmlns := FNSHelper.GetPrefix(@PrefixDefault, 5);
|
||||||
|
|
||||||
FStdUri_xmlns := doc.Names.FindOrAdd(PWideChar(stduri_xmlns), Length(stduri_xmlns));
|
FStdUri_xmlns := FNameTable.FindOrAdd(PWideChar(stduri_xmlns), Length(stduri_xmlns));
|
||||||
FStdUri_xml := doc.Names.FindOrAdd(PWideChar(stduri_xml), Length(stduri_xml));
|
FStdUri_xml := FNameTable.FindOrAdd(PWideChar(stduri_xml), Length(stduri_xml));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1322,6 +1324,7 @@ procedure TXMLReader.ProcessXML(ASource: TXMLCharSource);
|
|||||||
begin
|
begin
|
||||||
doc := TXMLDocument.Create;
|
doc := TXMLDocument.Create;
|
||||||
doc.documentURI := ASource.SystemID; // TODO: to be changed to URI or BaseURI
|
doc.documentURI := ASource.SystemID; // TODO: to be changed to URI or BaseURI
|
||||||
|
FNameTable := doc.Names;
|
||||||
FState := rsProlog;
|
FState := rsProlog;
|
||||||
FNesting := 0;
|
FNesting := 0;
|
||||||
FCurrNode := @FNodeStack[0];
|
FCurrNode := @FNodeStack[0];
|
||||||
@ -1343,6 +1346,7 @@ end;
|
|||||||
procedure TXMLReader.ProcessFragment(ASource: TXMLCharSource; AOwner: TDOMNode);
|
procedure TXMLReader.ProcessFragment(ASource: TXMLCharSource; AOwner: TDOMNode);
|
||||||
begin
|
begin
|
||||||
doc := AOwner.OwnerDocument;
|
doc := AOwner.OwnerDocument;
|
||||||
|
FNameTable := doc.Names;
|
||||||
FState := rsRoot;
|
FState := rsRoot;
|
||||||
FNesting := 0;
|
FNesting := 0;
|
||||||
FCurrNode := @FNodeStack[0];
|
FCurrNode := @FNodeStack[0];
|
||||||
@ -1926,7 +1930,7 @@ begin
|
|||||||
if not SkipUntilSeq(GT_Delim, '?') then
|
if not SkipUntilSeq(GT_Delim, '?') then
|
||||||
FatalError('Unterminated processing instruction', -1);
|
FatalError('Unterminated processing instruction', -1);
|
||||||
SetNodeInfoWithValue(ntProcessingInstruction,
|
SetNodeInfoWithValue(ntProcessingInstruction,
|
||||||
doc.Names.FindOrAdd(FName.Buffer, FName.Length));
|
FNameTable.FindOrAdd(FName.Buffer, FName.Length));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLReader.CreatePINode;
|
procedure TXMLReader.CreatePINode;
|
||||||
@ -2165,7 +2169,7 @@ var
|
|||||||
p: PHashItem;
|
p: PHashItem;
|
||||||
begin
|
begin
|
||||||
CheckName;
|
CheckName;
|
||||||
p := doc.Names.FindOrAdd(FName.Buffer, FName.Length);
|
p := FNameTable.FindOrAdd(FName.Buffer, FName.Length);
|
||||||
Result := TElementDecl(p^.Data);
|
Result := TElementDecl(p^.Data);
|
||||||
if Result = nil then
|
if Result = nil then
|
||||||
begin
|
begin
|
||||||
@ -2343,7 +2347,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
CheckName;
|
CheckName;
|
||||||
ExpectWhitespace;
|
ExpectWhitespace;
|
||||||
attrName := doc.Names.FindOrAdd(FName.Buffer, FName.Length);
|
attrName := FNameTable.FindOrAdd(FName.Buffer, FName.Length);
|
||||||
AttDef := TAttributeDef.Create(attrName, FColonPos);
|
AttDef := TAttributeDef.Create(attrName, FColonPos);
|
||||||
try
|
try
|
||||||
AttDef.ExternallyDeclared := FSource.DTDSubsetType <> dsInternal;
|
AttDef.ExternallyDeclared := FSource.DTDSubsetType <> dsInternal;
|
||||||
@ -2656,6 +2660,7 @@ end;
|
|||||||
procedure TXMLReader.ProcessDTD(ASource: TXMLCharSource);
|
procedure TXMLReader.ProcessDTD(ASource: TXMLCharSource);
|
||||||
begin
|
begin
|
||||||
doc := TXMLDocument.Create;
|
doc := TXMLDocument.Create;
|
||||||
|
FNameTable := doc.Names;
|
||||||
FDocType := TDOMDocumentTypeEx.Create(doc);
|
FDocType := TDOMDocumentTypeEx.Create(doc);
|
||||||
// TODO: DTD labeled version 1.1 will be rejected - must set FXML11 flag
|
// TODO: DTD labeled version 1.1 will be rejected - must set FXML11 flag
|
||||||
doc.AppendChild(FDocType);
|
doc.AppendChild(FDocType);
|
||||||
@ -2675,6 +2680,28 @@ begin
|
|||||||
cur.AppendChild(doc.CreateEntityReference(s));
|
cur.AppendChild(doc.CreateEntityReference(s));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TXMLReader.DoStartElement;
|
||||||
|
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;
|
||||||
|
if Assigned(FCurrNode^.FNsUri) then
|
||||||
|
NewElem.SetNSI(FCurrNode^.FNsUri^.Key, FCurrNode^.FColonPos+1);
|
||||||
|
|
||||||
|
for i := 1 to FAttrCount do
|
||||||
|
begin
|
||||||
|
Attr := LoadAttribute(doc, @FNodeStack[FNesting+i]);
|
||||||
|
NewElem.SetAttributeNode(Attr);
|
||||||
|
// Attach element to ID map entry if necessary
|
||||||
|
if Assigned(FNodeStack[FNesting+i].FIDEntry) then
|
||||||
|
FNodeStack[FNesting+i].FIDEntry^.Data := NewElem;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
// The code below does the bulk of the parsing, and must be as fast as possible.
|
// The code below does the bulk of the parsing, and must be as fast as possible.
|
||||||
// To minimize CPU cache effects, methods from different classes are kept together
|
// To minimize CPU cache effects, methods from different classes are kept together
|
||||||
@ -2743,6 +2770,8 @@ begin
|
|||||||
CreatePINode;
|
CreatePINode;
|
||||||
xtComment:
|
xtComment:
|
||||||
DoComment(FCurrNode^.FValueStart, FCurrNode^.FValueLength);
|
DoComment(FCurrNode^.FValueStart, FCurrNode^.FValueLength);
|
||||||
|
xtElement:
|
||||||
|
DoStartElement;
|
||||||
xtEndElement:
|
xtEndElement:
|
||||||
DoEndElement;
|
DoEndElement;
|
||||||
xtDoctype:
|
xtDoctype:
|
||||||
@ -2942,13 +2971,10 @@ end;
|
|||||||
// Element name already in FNameBuffer
|
// Element name already in FNameBuffer
|
||||||
procedure TXMLReader.ParseStartTag; // [39] [40] [44]
|
procedure TXMLReader.ParseStartTag; // [39] [40] [44]
|
||||||
var
|
var
|
||||||
NewElem: TDOMElement;
|
|
||||||
Attr: TDOMAttr;
|
|
||||||
ElDef: TElementDecl;
|
ElDef: TElementDecl;
|
||||||
IsEmpty: Boolean;
|
IsEmpty: Boolean;
|
||||||
ElName: PHashItem;
|
ElName: PHashItem;
|
||||||
b: TBinding;
|
b: TBinding;
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
if FState > rsRoot then
|
if FState > rsRoot then
|
||||||
FatalError('Only one top-level element allowed', FName.Length)
|
FatalError('Only one top-level element allowed', FName.Length)
|
||||||
@ -2962,11 +2988,8 @@ begin
|
|||||||
// we're about to process a new set of attributes
|
// we're about to process a new set of attributes
|
||||||
Inc(FAttrTag);
|
Inc(FAttrTag);
|
||||||
|
|
||||||
NewElem := doc.CreateElementBuf(FName.Buffer, FName.Length);
|
|
||||||
FCursorStack[FNesting].InternalAppend(NewElem);
|
|
||||||
|
|
||||||
// Remember the hash entry, we'll need it often
|
// Remember the hash entry, we'll need it often
|
||||||
ElName := NewElem.NSI.QName;
|
ElName := FNameTable.FindOrAdd(FName.Buffer, FName.Length);
|
||||||
|
|
||||||
// Find declaration for this element
|
// Find declaration for this element
|
||||||
ElDef := TElementDecl(ElName^.Data);
|
ElDef := TElementDecl(ElName^.Data);
|
||||||
@ -2982,7 +3005,6 @@ begin
|
|||||||
FPrefixedAttrs := 0;
|
FPrefixedAttrs := 0;
|
||||||
FSpecifiedAttrs := 0;
|
FSpecifiedAttrs := 0;
|
||||||
PushVC(ElDef); // this increases FNesting
|
PushVC(ElDef); // this increases FNesting
|
||||||
FCursorStack[FNesting] := NewElem;
|
|
||||||
|
|
||||||
FCurrNode^.FQName := ElName;
|
FCurrNode^.FQName := ElName;
|
||||||
FCurrNode^.FNodeType := ntElement;
|
FCurrNode^.FNodeType := ntElement;
|
||||||
@ -3031,28 +3053,15 @@ begin
|
|||||||
FTokenStart := FCurrNode^.FLoc;
|
FTokenStart := FCurrNode^.FLoc;
|
||||||
FatalError('Unbound element name prefix "%s"', [FCurrNode^.FPrefix^.Key],-1);
|
FatalError('Unbound element name prefix "%s"', [FCurrNode^.FPrefix^.Key],-1);
|
||||||
end;
|
end;
|
||||||
FCurrNode^.FNsUri := doc.Names.FindOrAdd(PWideChar(b.uri), Length(b.uri));
|
FCurrNode^.FNsUri := FNameTable.FindOrAdd(PWideChar(b.uri), Length(b.uri));
|
||||||
NewElem.SetNSI(b.uri, FCurrNode^.FColonPos+1);
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
b := FNSHelper.DefaultNSBinding;
|
b := FNSHelper.DefaultNSBinding;
|
||||||
if Assigned(b) then
|
if Assigned(b) then
|
||||||
begin
|
FCurrNode^.FNsUri := FNameTable.FindOrAdd(PWideChar(b.uri), Length(b.uri));
|
||||||
FCurrNode^.FNsUri := doc.Names.FindOrAdd(PWideChar(b.uri), Length(b.uri));
|
|
||||||
NewElem.SetNSI(b.uri, FCurrNode^.FColonPos+1);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
|
|
||||||
for i := 1 to FAttrCount do
|
|
||||||
begin
|
|
||||||
Attr := LoadAttribute(doc, @FNodeStack[FNesting+i]);
|
|
||||||
NewElem.SetAttributeNode(Attr);
|
|
||||||
// Attach element to ID map entry if necessary
|
|
||||||
if Assigned(FNodeStack[FNesting+i].FIDEntry) then
|
|
||||||
FNodeStack[FNesting+i].FIDEntry^.Data := NewElem;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if not IsEmpty then
|
if not IsEmpty then
|
||||||
begin
|
begin
|
||||||
@ -3119,7 +3128,7 @@ end;
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
CheckName;
|
CheckName;
|
||||||
attrName := doc.Names.FindOrAdd(FName.Buffer, FName.Length);
|
attrName := FNameTable.FindOrAdd(FName.Buffer, FName.Length);
|
||||||
attrData := AllocAttributeData(attrName);
|
attrData := AllocAttributeData(attrName);
|
||||||
attrData^.FColonPos := FColonPos;
|
attrData^.FColonPos := FColonPos;
|
||||||
StoreLocation(attrData^.FLoc);
|
StoreLocation(attrData^.FLoc);
|
||||||
@ -3264,7 +3273,7 @@ function TXMLReader.AddBinding(attrData: PNodeData): Boolean;
|
|||||||
var
|
var
|
||||||
nsUri, Pfx: PHashItem;
|
nsUri, Pfx: PHashItem;
|
||||||
begin
|
begin
|
||||||
nsUri := doc.Names.FindOrAdd(PWideChar(attrData^.FValueStr), Length(attrData^.FValueStr));
|
nsUri := FNameTable.FindOrAdd(PWideChar(attrData^.FValueStr), Length(attrData^.FValueStr));
|
||||||
if attrData^.FColonPos > 0 then
|
if attrData^.FColonPos > 0 then
|
||||||
Pfx := FNSHelper.GetPrefix(@attrData^.FQName^.key[7], Length(attrData^.FQName^.key)-6)
|
Pfx := FNSHelper.GetPrefix(@attrData^.FQName^.key[7], Length(attrData^.FQName^.key)-6)
|
||||||
else
|
else
|
||||||
@ -3320,7 +3329,7 @@ begin
|
|||||||
if FNsAttHash.Locate(@b.uri, @AttrName^.Key[J], Length(AttrName^.Key) - J+1) then
|
if FNsAttHash.Locate(@b.uri, @AttrName^.Key[J], Length(AttrName^.Key) - J+1) then
|
||||||
DoErrorPos(esFatal, 'Duplicate prefixed attribute', attrData^.FLoc);
|
DoErrorPos(esFatal, 'Duplicate prefixed attribute', attrData^.FLoc);
|
||||||
|
|
||||||
attrData^.FNsUri := doc.Names.FindOrAdd(PWideChar(b.uri), Length(b.uri));
|
attrData^.FNsUri := FNameTable.FindOrAdd(PWideChar(b.uri), Length(b.uri));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user