gpt4 book ai didi

delphi - 如何在 Delphi Chromium Embedded 中按名称获取元素?

转载 作者:行者123 更新时间:2023-12-03 15:13:00 27 4
gpt4 key购买 nike

要使用其 ID 从 TChromium 实例获取当前 Web 文档中嵌入的特定 DOM 节点,请使用 ICefDomDocument.getElementById()。但是如何通过 NAME 属性查找元素呢? Javascript 有 document.getElementsByName() 方法,TWebBrowser(包装 IE)有类似的调用,但我不知道如何使用 TChromium 执行此操作。我需要找到一些具有 NAME 属性但没有 ID 属性的 DOM 元素。我搜索了 ceflib 单元,但没有看到任何可以做到这一点的东西。

附带问题。如果有人有 TChromium“食谱”风格网站或文档的链接,我可以使用它。

更新:在等待答案时,我想出了以下用于执行 getElementsbyName() 的代码。我想要比扫描整个 DOM 树更快的东西。如果您发现代码中有问题,请告诉我:

type
TDynamicCefDomNodeArray = array of ICefDomNode;


// Given a Chromium document interface reference and a NAME attribute to search for,
// return an array of all DOM nodes whose NAME attribute matches the desired.
function getElementsByName(ADocument: ICefDomDocument; theName: string): TDynamicCefDomNodeArray;

// Get all the elements with a particular NAME attribute value and return
// an array of them.
procedure getElementsByName1(intfParentNode: ICefDomNode; theName: string; var aryResults: TDynamicCefDomNodeArray);
var
oldLen: integer;
intfChildNode: ICefDomNode;
theNameAttr: string;
begin
Result := nil;
intfChildNode := nil;

if Assigned(intfParentNode) then
begin
// Attributes are case insensitive.
theNameAttr := intfParentNode.GetElementAttribute('name');

if AnsiSameText(theNameAttr, theName) then
begin
// Name attribute match. Add it to the results array.
oldLen := Length(aryResults);
SetLength(aryResults, oldLen + 1);
aryResults[oldLen] := intfParentNode;
end; // if AnsiSameText(intfParentNode.Name, theName) then

// Does the parent node have children?
if intfParentNode.HasChildren then
begin
intfChildNode := intfParentNode.FirstChild;

// Scan them.
while Assigned(intfChildNode) do
begin
getElementsByName1(intfChildNode, theName, aryResults);

if Assigned(intfChildNode) then
intfChildNode := intfChildNode.NextSibling;
end;
end; // if intfParentNode.HasChildren then
end; // if Assigned(intfParentNode) then
end;

// ---------------------------------------------------------------

var
intfCefDomNode: ICefDomNode;
begin
intfCefDomNode := nil;
Result := nil;

if Assigned(ADocument) then
begin
// Check the header.
intfCefDomNode := ADocument.Document;

if Assigned(intfCefDomNode) then
begin
// Check the parent.
getElementsByName1(intfCefDomNode, theName, Result);
end; // if Assigned(intfCefDomNode) then
end; // if Assigned(ADocoument) then
end;

// ---------------------------------------------------------------

最佳答案

没有像 JavaScript 的 getElementsByName 这样的函数或 MSHTML getElementsByName建于Chromium Embedded此时也不是它的 Delphi 包装器。您只能通过迭代所有 DOM 元素来解决此问题,例如通过创建您自己的 DOM 访问者类,如下所示:

请注意,VisitDom 过程是异步的,因此它会立即返回(实际上是在 DOM 访问者完成其访问之前),并且它会使用 DOM 的快照执行的时间。

type
TElementNameVisitor = class(TCefDomVisitorOwn)
private
FName: string;
protected
procedure visit(const document: ICefDomDocument); override;
public
constructor Create(const AName: string); reintroduce;
end;

procedure ProcessElementsByName(const AFrame: ICefFrame; const AName: string);
var
Visitor: TElementNameVisitor;
begin
if Assigned(AFrame) then
begin
Visitor := TElementNameVisitor.Create(AName);
AFrame.VisitDom(Visitor);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ProcessElementsByName(Chromium1.Browser.MainFrame, 'NameAttributeValue');
end;

{ TDOMElementNameVisitor }

constructor TElementNameVisitor.Create(const AName: string);
begin
inherited Create;
FName := AName;
end;

procedure TElementNameVisitor.visit(const document: ICefDomDocument);

procedure ProcessNode(ANode: ICefDomNode);
var
Node: ICefDomNode;
begin
if Assigned(ANode) then
begin
Node := ANode.FirstChild;
while Assigned(Node) do
begin
if Node.GetElementAttribute('name') = FName then
begin
// do what you need with the Node here
ShowMessage(Node.GetElementAttribute('value'));
end;
ProcessNode(Node);
Node := Node.NextSibling;
end;
end;
end;

begin
ProcessNode(document.Body);
end;

关于delphi - 如何在 Delphi Chromium Embedded 中按名称获取元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10670452/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com