* (re)Build element ID list at end of parse. Fixes issue #39391

This commit is contained in:
Michaël Van Canneyt 2023-10-16 17:07:17 +02:00
parent c0354d0975
commit 9588204585
2 changed files with 45 additions and 0 deletions

View File

@ -522,6 +522,8 @@ type
// Extensions to DOM interface:
constructor Create; virtual;
destructor Destroy; override;
procedure RebuildIDsOfElement(aRoot: TDOMElement);
procedure RebuildIDList;
function CloneNode(deep: Boolean): TDOMNode; overload; override;
property Names: THashTable read FNames;
property IDs: THashTable read FIDList write FIDList;
@ -2261,6 +2263,43 @@ begin
// (because children reference the nametable)
end;
procedure TDOMDocument.RebuildIDsOfElement(aRoot: TDOMElement);
var
i: Integer;
AttribNode: TDOMNode;
id: DOMString;
Item: PHashItem;
begin
if aRoot=Nil then
exit;
for i := 0 to aRoot.Attributes.Length - 1 do
begin
AttribNode := aRoot.Attributes.Item[i];
if LowerCase(AttribNode.NodeName) = 'id' then
begin
id := AttribNode.TextContent;
Item := FIDList.FindOrAdd(PWideChar(id), Length(id));
Item^.Data := aRoot;
break;
end;
end;
for i := 0 to aRoot.ChildNodes.Count - 1 do
begin
if aroot.ChildNodes[i] is TDOMElement then
RebuildIDsOfElement(TDOMElement(aroot.ChildNodes[i]));
end;
end;
procedure TDOMDocument.RebuildIDList;
begin
if not Assigned(FIDList) then
FIDList := THashTable.Create(256, False);
FIDList.Clear;
RebuildIDsOfElement(Self.DocumentElement);
end;
function TDOMDocument.CloneNode(deep: Boolean): TDOMNode;
type
TDOMDocumentClass = class of TDOMDocument;

View File

@ -114,6 +114,7 @@ type
constructor Create(AReader: THTMLReader; ADocument: TDOMDocument);
constructor CreateFragment(AReader: THTMLReader; AFragmentRoot: TDOMNode);
destructor Destroy; override;
Property Document : TDOMDocument Read FDocument;
end;
@ -781,6 +782,7 @@ begin
Converter := THTMLToDOMConverter.Create(Reader, ADoc);
try
Reader.ParseStream(f);
Converter.Document.RebuildIDList;
finally
Converter.Free;
end;
@ -811,6 +813,10 @@ begin
Converter := THTMLToDOMConverter.CreateFragment(Reader, AParentNode);
try
Reader.ParseStream(f);
if aParentNode is TDOMElement then
Converter.Document.RebuildIDsOfElement(aParentNode as TDOMElement)
else
Converter.Document.RebuildIDList;
finally
Converter.Free;
end;