2012-05-20 42 views
5

Để có được một nút DOM cụ thể được nhúng trong tài liệu web hiện tại từ một cá thể TChromium, sử dụng ID của nó, bạn sử dụng ICefDomDocument.getElementById(). Nhưng làm thế nào để bạn tìm thấy các yếu tố của thuộc tính NAME? Javascript có phương thức document.getElementsByName() và TWebBrowser (bao bọc IE) có một cuộc gọi tương tự, nhưng tôi không thể tìm ra cách làm điều này với TChromium. Tôi cần phải tìm một số phần tử DOM có thuộc tính NAME nhưng không có thuộc tính ID. Tôi đã tìm kiếm đơn vị ceflib và không thấy bất kỳ thứ gì có thể thực hiện được.Làm thế nào để có được các yếu tố theo tên trong Delphi Chromium nhúng?

Câu hỏi phụ. Nếu có ai có liên kết đến trang web kiểu "công thức nấu ăn" hoặc tài liệu TChromium thì tôi có thể sử dụng nó.

CẬP NHẬT: Trong khi đợi câu trả lời, tôi đã đưa ra mã sau đây để thực hiện getElementsbyName(). Tôi muốn cái gì đó nhanh hơn quét toàn bộ cây DOM. Nếu bạn nhìn thấy một cái gì đó sai trong các mã cho tôi biết:

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; 

// --------------------------------------------------------------- 
+0

Tôi không nghĩ rằng nó là khôn ngoan để trộn và kết hợp công nghệ 10 năm với công cụ hiện đại và mong đợi nó trở thành một giải pháp tìm thấy và ổn định. Trong trường hợp cụ thể này, TChromium không hỗ trợ Delph 6. http://code.google.com/p/delphichromiumembedded/ –

+0

@Jeroen, ['TChromium'] (http://code.google.com/p/delphichromiumembedded /) không hỗ trợ Delphi 6 mặc dù (không có gói cho nó), nhưng nó không có nghĩa là nó không thể làm việc ở đó. Tôi có Delphi 2009, mà cũng không được hỗ trợ, nhưng nhìn vào nguồn, không có gì có thể ức chế việc sử dụng có ;-) – TLama

+0

@TLama nếu tâm trí của tôi phục vụ tôi đủ tốt, Delphi 7 giới thiệu khá một vài sửa chữa liên quan đến gói COM stuff. Đó có thể là lý do để không hỗ trợ Delphi 6. Tôi khuyên bạn nên Robert xác minh giả định này với nhóm TChromium. –

Trả lời

3

Không có chức năng giống như của getElementsByName JavaScript hoặc MSHTML getElementsByName xây dựng trong Chromium Embedded cũng không wrapper Delphi của nó vào lúc này. Bạn có thể giải quyết vấn đề này chỉ bằng cách lặp qua tất cả các phần tử DOM, ví dụ: bằng cách tạo lớp khách truy cập DOM của riêng bạn như sau:

Xin lưu ý rằng thủ tục VisitDom không đồng bộ, vì vậy nó trả về ngay lập tức (thực tế trước khi DOM truy cập xong visit) và nó hoạt động với ảnh chụp nhanh 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; 
+1

re: phát minh lại bánh xe. Không có mục đích, chỉ sử dụng những gì tôi tìm thấy khi nghiên cứu sử dụng Chromium với Delphi (xem trả lời của tôi cho nhận xét của bạn về bài đăng chính). –

+0

Vì vậy, tôi mang nó đến lượt truy cập cuộc gọi với một hậu duệ TCefDomVisitorOwn triển khai mẫu Khách truy cập? Nói cách khác, CEF sẽ áp dụng mẫu đó cho tất cả các nút trong DOM, xử lý gốc đệ quy thông qua cây nút cho bạn? Đó là rất mát mẻ nếu như vậy nhưng tôi muốn được hoàn toàn chắc chắn vì vậy tôi yêu cầu xác nhận. –

+0

Không, sự lặp lại bạn phải tự mình làm. Sự khác biệt của việc sử dụng phương thức 'VisitDom' là nó tạo một bản sao (ảnh chụp nhanh) của trạng thái DOM hiện tại. Trong ví dụ của tôi, 'TElementNameVisitor.visit' làm việc với một bản sao của tài liệu, chứ không phải với bản thân tài liệu (có thể được thay đổi tại thời điểm bạn lặp lại). Tôi không biết nếu nó nhanh hơn, nó chỉ an toàn hơn. – TLama

Các vấn đề liên quan