2011-12-06 19 views
6

我在運行時創建TXMLDocument的實例,來加載和分析XML文件。你可以檢查下面的代碼:德爾福 - 在運行時創建TXMLDocument的生成AV,與形式組件工作

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. 

問題是,這是生成AV。正如您可能已經看到的,在組件位於窗體上之前(// XMLDocument1:TXMLDocument;)。

爲什麼當組件是代碼是工作的形式,但是當我在運行時創建它,它產生AV?

LE: 解決:基於答案/意見和德爾福幫助:

XMLDocument1 : IXMLDocument; //not TXMLDocument 

XMLDocument1 := LoadXMLDocument(...); 

FreeAndNil;// must be deleted 
+3

使用[IXMLDocument](http://docwiki.embarcadero.com/VCL/en/XMLIntf.IXMLDocument)和作爲構造[NewXMLDocument](http://docwiki.embarcadero.com/VCL/en/ XMLDoc.NewXMLDocument)。 – TLama

+0

AV在哪裏發生? – Kromster

+1

在關閉和釋放XMLDocument1之前,您應該在循環之後執行'ANode:= nil;'釋放節點實例。 –

回答

14

據我所知,你應該使用接口IDoc: IXMLDocument;代替。

從文檔:

當TXMLDocument的是沒有所有者創建的,它的行爲就像一個 接口對象。也就是說,當所有對其接口的引用都是 發佈時,TXMLDocument實例會自動釋放。當與一個用戶創建 TXMLDocument的,但是,它的行爲就像任何其他 成分,是由它的擁有者釋放。

換句話說,用nil業主創造一個TXMLDocument實例時,通話Free()FreeAndNil()的實例,你必須的對象分配給IXMLDocument變量,因此其當前活動參考計數管理得當。

+4

換句話說,創建一個帶有'nil'業主一個'TXMLDocument'實例時,*不*調用'免費()'或'FreeAndNil()'的實例,你*必須*分配對象一個'IXMLDocument'變量,所以它現在有效的引用計數是正確管理的。 –

2

您需要在運行時創建時,它提供一個OwnerTXMLDocument

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

是的,的確,這個鞋底的問題,但所有這些代碼將被放入一個特殊的類,在一個單位:) +1 – RBA