Nota prawna: Przetestowano za pomocą D2007.
Kod rzeczywiście tworzyć XML (<label/>
), jak pokazano w tym zmodyfikowanym funkcję:
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;
Ale to wymaga dużo uwagi:
- Ty nie potrzebujesz lokalna zmienna res, wystarczy użyć wyniku.
- Nie potrzeba dodatkowego StringList zobaczyć XML: Result.Xml.Text
- Nie zapomnij bezpłatnym StringList sl jeśli utworzyć.
- Zwrócony XmlDocument nie nadaje się do użytku poza funkcją i daje sygnał AV, jeśli spróbujesz.
Dlaczego?
To dlatego XmlDocument jest przeznaczony do stosowania jako komponent z właścicielem, lub jako interfejsu w inny sposób, aby zarządzać swoim żywotność.
Fakt, że używasz Interfejsu do przechowywania rootNode powoduje, że jest on niszczony na końcu funkcji CreateXmlDocument. A jeśli spojrzysz na kod w TXMLNode._Release
, zobaczysz, że uruchamia on TXMLDocument._Release
, który wywołuje Destroy, chyba że istnieje Właściciel dla XMLDocument (lub interfejsu przechowującego odnośnik do niego).
Dlatego właśnie dokument XMLDocument jest poprawny i zapełniony wewnątrz funkcji CreateXMLDocument, ale nie jest dostępny poza nim, chyba że zwrócisz interfejs lub podasz właściciela.
Zobacz alternatywne rozwiązania poniżej:
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;
Byłoby dobrze, gdyby podałeś wersję Delphi używasz. Zobacz moją odpowiedź w przypadku D2007. –