-->

发出建立使用TXMLDocument的XML文档(Issue building an XML doc

2019-07-21 07:25发布

我是新来的德尔福,现在我要读创建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过程中元素的其余部分似乎并没有被做任何事情。 我会很高兴与你的帮助。

Answer 1:

免责声明:与D2007测试。

代码确实创建XML( <label/>如图此修正函数:

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;

但它要求大量的言论
- 你并不需要一个本地资源变量,只是使用的结果。
- 你并不需要一个额外的StringList看到XML:Result.Xml.Text
-不要忘记,如果你创建一个免费的SL的StringList。
- 您返回XmlDocument的是不可用的功能之外,如果你试图给出一个AV。

为什么?
这是因为一个XMLDocument意图被用作组件与所有者 ,或作为接口 ,否则,以管理其寿命
您使用的接口来保存根节点的事实使其在CreateXmlDocument函数结束时被销毁。 如果你看一下代码TXMLNode._Release ,你会发现它触发TXMLDocument._Release这就要求销毁除非有XmlDocument的(或保持对它的引用接口)的所有者。
这就是为什么XmlDocument的有效和填充CreateXMLDocument功能内,但不可用之外,除非你返回一个接口或提供者

请参见下面替代解决方案

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;


Answer 2:

在Delphi帮助 TXMLDocument.AddChild方法的说(底部):

注意:不要叫的AddChild一个孩子添加到这个文档的文档元素。 当将数据添加到XML文档,使用文档元素或在层次结构中的节点应该是这样的新节点的父节点的AddChild方法。

这是你在做什么吗? :-)

以下是有关的介绍文章德尔福XML文档程序 ,并显示您如何与TXMLDocument.DocumentElement属性,而不是你在代码中根节点变量的定义工作。



Answer 3:

在我类似的实现,我宣布水库作为IXMLDocument而不是TXMLDocument的。

var
   XMLDoc: IXMLDocument;
.
.
   XMLDoc := TXMLDocument.Create(nil);
   XMLDoc.Active := True;
.
.
   XMLDoc.SaveToFile(Filename);
   XMLDoc.Active := False;


文章来源: Issue building an XML document using TXMLDocument