Clause de non-responsabilité: Testé avec D2007.
Votre code ne crée en effet le XML (<label/>
) comme indiqué dans cette fonction modifiée:
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;
Mais il demande beaucoup de remarques :
- Vous ne ont pas besoin variable locale res, il suffit d'utiliser le résultat.
- Vous n'avez pas besoin d'un StringList supplémentaire pour voir le XML: Result.Xml.Text
- N'oubliez pas de Gratuit le sl StringList si vous en créez un.
- Le document XmlDocument que vous renvoyez est inutilisable en dehors de la fonction et donne un AV si vous essayez.
Pourquoi?
C'est parce qu'un XMLDocument est destiné à être utilisé comme composant avec un propriétaire, ou comme interface autrement, afin de gérer sa vie .
Le fait que vous utilisiez une interface pour stocker rootNode entraîne sa destruction à la fin de la fonction CreateXmlDocument. Et si vous regardez le code dans TXMLNode._Release
, vous verrez qu'il déclenche TXMLDocument._Release
qui appelle Destroy sauf s'il y a un propriétaire pour XMLDocument (ou une interface contenant une référence).
C'est pourquoi le XMLDocument est valide et rempli à l'intérieur de la fonction CreateXMLDocument mais n'est pas disponible à l'extérieur, sauf si vous renvoyez une interface ou fournissez un propriétaire.
Voir les solutions de rechange ci-dessous:
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;
Ce serait bien si vous avez fourni la version Delphi que vous utilisez. Voir ma réponse dans le cas de D2007. –