Disclaimer: Testato con D2007.
il codice fa infatti creare il XML (<label/>
) come mostrato in questa funzione modificata:
function createXMLDocument(): TXMLDocument;
var
res: TXMLDocument;
rootNode: IXMLNode;
sl : TStringList;
begin
res := TXMLDocument.Create(nil);
res.Active := true;
rootNode := res.AddChild('label');
// create string for debug purposes
sl := TStringList.Create; // not needed
sl.Assign(res.XML); // Not true: sl is empty after this assignment
ShowMessage(sl.text);// sl is NOT empty!
sl.Free; // don't forget to free it! use try..finally.. to guarantee it!
//add more elements
// generateDOM(rootNode);
Result := res;
end;
Ma richiede un sacco di osservazioni:
- Non hanno bisogno di un variabile res locale, basta usare il risultato.
- Non è necessario un elenco di stringhe aggiuntivo per visualizzare il codice XML: Result.Xml.Text
- Non dimenticare di gratuito sl StringList se ne crei uno.
- Il documento Xml che si restituisce non è utilizzabile fuori dalla funzione e fornisce un AV se si prova.
Perché?
E 'a causa di un XMLDocument è destinato ad essere usato come componente con un proprietario, o come un interfaccia in caso contrario, al fine di gestire la propria vita .
Il fatto che si utilizzi un'interfaccia per contenere rootNode ne provoca la distruzione al termine della funzione CreateXmlDocument. E se guardate il codice in TXMLNode._Release
, vedrete che si innesca TXMLDocument._Release
che chiama Destroy a meno che non ci sia un proprietario per XMLDocument (o un'interfaccia che contiene un riferimento ad esso).
Questo è il motivo per cui XMLDocument è valido e compilato all'interno della funzione CreateXMLDocument ma non è disponibile al di fuori di esso a meno che non si restituisca un'interfaccia o si fornisca un proprietario.
visualizzare le soluzioni alternative sotto:
function createXMLDocumentWithOwner(AOwner: TComponent): TXMLDocument;
var
rootNode: IXMLNode;
begin
Assert(AOwner <> nil, 'createXMLDocumentWithOwner cannot accept a nil Owner');
Result := TXMLDocument.Create(AOwner);
Result.Active := True;
rootNode := Result.AddChild('label');
OutputDebugString(PChar(Result.Xml.Text));
//add more elements
// generateDOM(rootNode);
end;
function createXMLDocumentInterface(): IXMLDocument;
var
rootNode: IXMLNode;
begin
Result := TXMLDocument.Create(nil);
Result.Active := True;
rootNode := Result.AddChild('label');
OutputDebugString(PChar(Result.Xml.Text));
//add more elements
// generateDOM(rootNode);
end;
procedure TForm7.Button1Click(Sender: TObject);
var
doc: TXmlDocument;
doc2: IXMLDocument;
begin
ReportMemoryLeaksOnShutdown := True;
doc := createXMLDocument;
// ShowMessage(doc.XML.Text); // cannot use it => AV !!!!
// already freed, cannot call doc.Free;
doc := createXMLDocumentWithOwner(self);
ShowMessage(doc.XML.Text);
doc2 := createXMLDocumentInterface;
ShowMessage(doc2.XML.Text);
end;
fonte
2009-10-08 00:32:42
sarebbe bene se hai fornito la versione di Delphi che si sta utilizzando. Vedi la mia risposta in caso di D2007. –