responsabilidad: Probado con D2007.
Su código no crear de hecho el XML (<label/>
) como se muestra en esta función modificada:
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;
pero requiere una gran cantidad de observaciones :
- Usted no necesita una variable de res local, solo use el resultado.
- No necesita StringList adicional para ver el XML: Result.Xml.Text
- No se olvide de gratuito sl StringList si crea uno.
- El XmlDocument que regrese no se puede utilizar fuera de la función y da un AV si intenta.
¿Por qué?
Es porque un XMLDocument está destinado a ser usado como un componente con un propietario, o como una Interface de otro modo, con el fin de gestionar su vida.
El hecho de que utilice una interfaz para contener rootNode hace que se destruya al final de la función CreateXmlDocument. Y si mira el código en TXMLNode._Release
, verá que desencadena TXMLDocument._Release
que llama Destrucción a menos que haya un Propietario para el XMLDocument (o una interfaz que contenga una referencia).
Esta es la razón por la XMLDocument es válida y poblada dentro de la función CreateXMLDocument pero no está disponible fuera de ella a menos que devuelva una interfaz o proporcionar un Propietario.
Ver las soluciones alternas a continuación:
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;
sería bueno si proporcionó la versión de Delphi que está utilizando. Ver mi respuesta en caso de D2007. –