8

私は Delphi を初めて使用するので、xml の作成を読む必要があります。私のコードは次のとおりです。

function foo.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;
  sl.Assign(res.XML);// sl is empty after this assignment
  //add more elements
  generateDOM(rootNode);

  Result := res;
end;

問題は、子ノードの数は増えますが、res.XML は空です。generateDOM プロシージャの残りの要素は何もしていないように見えることは言うまでもありません。私はあなたの助けをとてもうれしく思います。

4

3 に答える 3

12

免責事項: D2007 でテスト済み。

<label/>この変更された関数に示すように 、コードは実際に XML ( ) を作成します。

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;

しかし、それには多くの注意が必要です:
- ローカルの res 変数は必要ありません。Result を使用するだけです。
- XML を表示するために追加の StringList は必要ありません: Result.Xml.Text -作成した場合は、sl StringListを解放
する ことを忘れないでください。 -返される XmlDocument は関数の外では使用できず、試してみると AV が返されます

なんで?
XMLDocument は、その有効期間を管理するために、 Owner を持つ Componentとして、またはそれ以外の場合はInterfaceとして使用されることを意図しているためです。 Interface を使用して rootNode を保持すると、CreateXmlDocument 関数の最後で破棄されます。のコードを見ると、XMLDocument の所有者 (またはその参照を保持するインターフェイス) がない限り、Destroy を呼び出すトリガーが発生することがわかります。 これが、XMLDocument が有効であり、 CreateXMLDocument 関数内で設定されているのに、 Interface を返すか Owner を指定しない限り、外部では使用できない理由です。
TXMLNode._ReleaseTXMLDocument._Release

以下の代替ソリューションを参照してください。

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;
于 2009-10-08T00:32:42.157 に答える
4

TXMLDocument.AddChild メソッドのDelphi ヘルプには、次のように書かれています (一番下):

注: AddChild を呼び出して、このドキュメントのドキュメント要素に子を追加しないでください。XML ドキュメントにデータを追加するときは、ドキュメント要素の AddChild メソッド、または新しいノードの親となる階層内のノードの AddChild メソッドを使用します。

そして、これはあなたがしていることですよね?:-)

これは、 Delphi XML ドキュメント プログラミングに関する紹介記事で、コード内の rootnode 変数の定義の代わりに TXMLDocument.DocumentElement プロパティを操作する方法を示しています。

于 2009-10-07T17:04:55.077 に答える
2

私の同様の実装では、res を TXMLDocument ではなく IXMLDocument として宣言しています。

var
   XMLDoc: IXMLDocument;
.
.
   XMLDoc := TXMLDocument.Create(nil);
   XMLDoc.Active := True;
.
.
   XMLDoc.SaveToFile(Filename);
   XMLDoc.Active := False;
于 2009-10-07T16:02:31.617 に答える