如何在Delphi中创建XML文件

14

我是Delphi的新手,现在我需要创建一个XML。我的代码如下:

unit writexml1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, xmldom, XMLIntf, StdCtrls, msxmldom, XMLDoc;

type
  TForm1 = class(TForm)
    XMLDocument1: TXMLDocument;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.SaveClick(Sender: TObject);
var
  rootName: String;
  childNode: String;
  attrChild: string;
  iXml: IDOMDocument;
  iRoot, iNode, iNode2, iChild, iAttribute: IDOMNode;
  XMLDoc: TXMLDocument;
begin
  XMLDoc.Active := False;
  XMLDoc.XML.Text := '';
  XMLDoc.Active := True;
  XMLDoc.SaveToFile('C:\Documents and Settings\a\Desktop\zulfa.xml');
  iXml := XMLDoc.DOMDocument;
  iRoot := iXml.appendChild(iXml.createElement('xml'));
  iNode := iRoot.appendChild(iXml.createElement('test'));
  iNode.appendChild(iXml.createElement('test2'));
  iChild := iNode.appendChild(iXml.createElement('test3'));
  iChild.appendChild(iXml.createElement('Simple calue'));
  iNode.insertBefore(iXml.createElement('test4'), iChild);
  iNode2 := iNode.cloneNode(True);
  iRoot.appendChild(iNode2);
  iAttribute := iXml.createAttribute('color');
  iAttribute.nodeValue := 'red';
  iNode2.attributes.setNamedItem(iAttribute);
end;

end.
问题在于点击保存按钮时会显示异常,异常信息为:
Project writexml1.exe raised exception class EAccessViolation  with message 
'Access violation at address 004391B9 in module writexml.exe

与您的问题无关,但为什么在XMLDoc中没有任何XML之前就将其内容保存到文件中呢?看起来您的代码永远不会生成包含XML的文件。 - Sam M
4个回答

42

你的代码看起来有点复杂。我建议:忘记TXMLDocumentIDOMDOCUMENT,改用IXMLDOCUMENT(使用方法几乎与TXmlDocument相同,但你不需要组件)。

这段代码应该演示了它是多么简单:

{...}
Var
  XML : IXMLDOCUMENT;
  RootNode, CurNode : IXMLNODE;
begin
  XML := NewXMLDocument;
  XML.Encoding := 'utf-8';
  XML.Options := [doNodeAutoIndent]; // looks better in Editor ;)
  RootNode := XML.AddChild('XML');
  CurNode := RootNode.AddChild('Test');
  CurNode := CurNode.AddChild('Test2');
  CurNode.Text := 'Some Test 2 text';
  CurNode.Attributes['NewAttribute'] := 'Some Test2 Attribute Value';
  XMl.SaveToFile('C:\Documents and Settings\a\Desktop\zulfa.xml');
{...}

这就是生成的文件的样子:

<?xml version="1.0" encoding="utf-8"?>
<XML>
  <Test>
    <Test2 NewAttribute="Some Test2 Attribute Value">Some Test 2 text</Test2>
  </Test>
</XML>

希望这可以帮到你。

提示:此示例仅需要 XMLIntfXmlDoc 两个单元,因此您可以稍微整理一下自己的uses


13
你需要在使用之前创建XMLDoc实例:
XMLDoc := TXMLDocument.Create(...);
try
  ... do stuff with XMLDOC
finally
  XMLDoc.Free;
end;

9
要注意,使用nil所有者动态创建 TXMLDocument 将使其作为接口而不是对象。在此类实例上调用 Free() 会非常糟糕。如果要使用 Free(),则必须提供一个非 nil 所有者(在这种情况下,Free() 是多余的,因为当所有者被释放时,它会自动释放 TXMLDocument)。如果你使用 nil 所有者动态分配 TXMLDocument,你必须将其赋值给一个 IXMLDocument 变量,在这种情况下请使用 NewXMLDocument() 而不是 TXMLDocument.Create(nil) - Remy Lebeau
@remy 我编辑了答案并加入了构造函数。但我不知道要传递什么参数。因此......原始答案缺乏细节。 - David Heffernan
1
像其他组件一样,TXMLDocument 的构造函数需要一个 TComponent 所有者作为输入。如果您指定了非 nil 的所有者,则所有者将负责释放 TXMLDocument。如果您指定了 nil 的所有者,则 TXMLDocument 将没有所有者,您需要负责释放它。但是,在后一种情况下,TXMLDocument 是特殊的,因为当它具有 nil 所有者时,它不像普通组件那样工作,而是作为引用计数接口,因此您必须涉及引用计数系统以正确释放它。 - Remy Lebeau
@Remy:当我通过NewXmlDocument()分配XML文档时,如何在不再需要它时释放实例? - truthseeker
2
@truthseeker:NewXmlDocument() 返回一个引用计数的 IXMLDocument 接口。当没有对它的引用时,它会自动释放。你可以让它正常超出范围,或者如果你想更早地释放它,可以将其赋值为 nil - Remy Lebeau

13
SaveClick() 声明了一个本地的 XMLDoc 变量,在使用之前没有分配一个有效的 TXMLDocument 对象。你在 TForm 上有一个单独的 XMLDocument1 组件,但是你没有使用它。去掉 XMLDoc 并使用 XMLDocument1 代替。
另外,你直接访问了底层的 DOMDocument。使用 TXMLDocument 自己的方法来构建 XML,除非你需要访问供应商特定的功能(在这种情况下你不需要)。尝试这样做:
procedure TForm1.SaveClick(Sender: TObject); 
var 
  iRoot, iNode, iNode2, iChild: IXMLNode; 
begin 
  XMLDocument1.Active := False;
  XMLDocument1.XML.Text := '';    
  XMLDocument1.Active := True;
  iRoot := XMLDocument.AddChild('xml'); 
  iNode := iRoot.AddChild('test'); 
  iNode.AddChild('test2'); 
  iChild := iNode.AddChild('test3'); 
  iChild.Text := 'Simple value'; 
  iNode.AddChild('test4', iNode.ChildNodes.IndexOf(iChild)); 
  iNode2 := iNode.CloneNode(True); 
  iRoot.ChildNodes.Add(iNode2); 
  iNode2.Attributes['color'] := 'red'; 
  XMLDocument1.SaveToFile('C:\Documents and Settings\a\Desktop\zulfa.xml'); 
  XMLDocument1.Active := False;
end; 

这将生成以下的XML:

<?xml version="1.0" encoding="utf-8"?>
<xml>
  <test>
    <test2 />     
    <test4 />
    <test3>Simple value</test3>
  </test>
  <test color="red">
    <test2 />     
    <test4 />
    <test3>Simple value</test3>
  </test>
</xml>

话虽如此,像@knowledgestacker建议的那样使用IXMLDocument而不是TXMLDocument通常是更好的选择。


0

我编写了一个库来管理和简化与XML文件的工作,你可以在这里查看

不确定你想创建什么样的结构,但这里有一个例子:

uses
  ..., IXMLData;

procedure TForm1.Button3Click(Sender: TObject);
var
  d : TIXMLDoc;
  n1, n2 : IXMLNode;
begin
  d := TIXMLDoc.Create('XML');  //By default it uses utf-8 encoding but you specify other encoding as well
  n1 := d.addNode('Test');
  n2 := d.addNode(n1,'Test2');  //add node Test2 as child of node Test
  n2.Attributes['NewAttribute'] := 'Some Test2 Attribute Value';
  n2.Text := 'Some Test 2 text';
  d.SaveTofile('C:\Documents and Settings\a\Desktop\zulfa.xml');  
end;

它将生成以下XML:

<XML>
  <Test>
    <Test2 NewAttribute="Some Test2 Attribute Value">Some Test 2 text</Test2>
  </Test>
</XML>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接