2011-12-06 36 views
6

Tôi đang tạo một thể hiện của TXMLDocument khi chạy, để tải và phân tích cú pháp tệp XML. Bạn có thể kiểm tra mã bên dưới:Delphi - TXMLTài liệu được tạo tại thời gian chạy tạo AV, với thành phần trên biểu mẫu đang hoạt động

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, xmldom, XMLIntf, msxmldom, XMLDoc, StdCtrls; 

type 
    Txml = class(TForm) 
// XMLDocument1: TXMLDocument; 
    Memo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    xml: Txml; 

implementation 

{$R *.dfm} 

procedure Txml.FormCreate(Sender: TObject); 
var i,j:integer; 
     aNode:IXMLNode; 
     ws:String; 
     XMLDocument1:TXMLDocument; 
begin 
Memo1.Lines.Clear; 
XMLDocument1 := TXMLDocument.Create(nil); 
try 
    XMLDocument1.LoadFromFile('C:\a.xml'); 
    XMLDocument1.Active := true; 
    aNode := XMLDocument1.ChildNodes.First; 
    while aNode<>nil do 
    begin 
    for i := 0 to aNode.ChildNodes.Count-1 do 
    begin 
    if aNode.ChildNodes[i].NodeName = 'Role' then 
     begin 
     Memo1.Lines.Add('Tag - '+aNode.ChildNodes[i].ChildNodes['Tag'].Text); 
     for j := 0 to aNode.ChildNodes[i].ChildNodes.Count-1 do 
     if aNode.ChildNodes[i].ChildNodes[j].HasChildNodes then 
     begin 
      ws := VarToStr(aNode.ChildNodes[i].ChildNodes[j].ChildValues['Tag']); 
      if trim(ws)<>'' then 
      Memo1.Lines.Add(ws); 
      ws := VarToStr(aNode.ChildNodes[i].ChildNodes[j].ChildValues['Value']); 
      if trim(ws)<>'' then 
      Memo1.Lines.Add(ws); 
     end; 
     end; 
    end; 
    aNode := aNode.NextSibling; 
    end; 
    XMLDocument1.Active := false; 
finally 
    FreeAndNil(XMLDocument1); 
end; 
end; 

end. 

Vấn đề là tạo ra AV. Như bạn có thể đã thấy, trước khi thành phần có trên biểu mẫu (// XMLDocument1: TXMLDocument;).

Tại sao khi thành phần ở trên biểu mẫu mã đang hoạt động, nhưng khi tôi tạo mã trong thời gian chạy, nó tạo AV?

LE: giải pháp: dựa trên các câu trả lời/bình luận và Delphi Trợ giúp:

XMLDocument1 : IXMLDocument; //not TXMLDocument 

XMLDocument1 := LoadXMLDocument(...); 

FreeAndNil;// must be deleted 
+3

Sử dụng [IXMLDocument] (http://docwiki.embarcadero.com/VCL/en/XMLIntf.IXMLDocument) và như constructor [NewXMLDocument] (http://docwiki.embarcadero.com/VCL/en/ XMLDoc.NewXMLDocument). – TLama

+0

AV xảy ra ở đâu? – Kromster

+1

Bạn nên làm 'ANode: = nil;' sau vòng lặp để giải phóng thể hiện nút trước khi đóng và giải phóng 'XMLDocument1'. –

Trả lời

14

Từ những gì tôi biết bạn nên sử dụng giao diện IDoc: IXMLDocument; để thay thế.

Từ tài liệu:

Khi TXMLDocument được tạo ra mà không có một Chủ đầu tư, nó hoạt động như một đối tượng giao tiếp . Đó là, khi tất cả các tham chiếu đến giao diện của nó là được phát hành, cá thể TXMLDocument được tự động giải phóng. Khi TXMLTài liệu được tạo với Chủ sở hữu, tuy nhiên, nó hoạt động giống như bất kỳ thành phần nào khác của và được Chủ sở hữu giải phóng.

Nói cách khác, khi tạo một trường hợp TXMLDocument với Chủ đầu tư nil, không gọi Free() hoặc FreeAndNil() trên ví dụ, và bạn phải gán đối tượng để một biến IXMLDocument nên tham khảo bây giờ hoạt động của nó đếm được quản lý đúng cách.

+4

Nói cách khác, khi tạo một cá thể 'TXMLDocument' với một' nil' Owner, * không * gọi 'Free()' hoặc 'FreeAndNil()' trên cá thể, và bạn * phải * gán đối tượng cho một biến 'IXMLDocument' để số tham chiếu hiện đang hoạt động của nó được quản lý đúng cách. –

2

Bạn cần cung cấp Owner đến TXMLDocument khi tạo trong thời gian chạy.

XMLDocument1 := TXMLDocument.Create(xml); 
+1

vâng, thực sự, điều này giải quyết vấn đề, nhưng tất cả mã này sẽ được đặt vào một lớp đặc biệt, bên trong một đơn vị :) +1 – RBA

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