我想使用以下格式在Delphi 10.1中创建XML文件
<EmployeeDB>
<Employees>
<Employee e.id="1">
<eName>value from Edit Box edtName</eName>
<ePlace>value from Edit Box edtPlace</ePlace>
</Employee >
<Employee e.id="2">
<eName>value from Edit Box edtName</eName>
<ePlace>value from Edit Box edtPlace</ePlace>
</Employee >
<Employee e.id="3">
<eName>value from Edit Box edtName</eName>
<ePlace>value from Edit Box edtPlace</ePlace>
</Employee >
</Employees>
</EmployeeDB>
我想从注册表单中获取数据,当单击“确定”按钮时,它应该将编辑框,RadioButtons等数据添加到XML文件中。
我是Delphi Programming的新手,帮我整理一下。
我尝试用这种方式编写代码:
unit XMLTrail;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, XMLIntf, XMLDoc, ComObj, xmldom,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
Tfrm_XMLTrail = class(TForm)
edt_eID: TEdit;
edtName: TEdit;
edtPlace: TEdit;
Memo1: TMemo;
btnAdd: TButton;
procedure btn_AddClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure LoadXML;
procedure SaveXML;
public
{ Public declarations }
XMLDoc1: TXmlDocument;
iNode, Root1, Root2, Child_Attrib_Name, Child_Attrib_Place: IXmlNode;
function GetEmployeeDBNode(XMLDoc: TXmlDocument): IXmlNode;
function GetEmployeesNode(EmployeeDBNode: IXmlNode): IXmlNode;
end;
var
frm_XMLTrail: Tfrm_XMLTrail;
implementation
{$R *.dfm}
const
scXmlTemplate = '<EmployeeDB>'#13#10 + ' <Employees>'#13#10 +
' </Employees>'#13#10 + '</EmployeeDB>';
scXmlFileName =
'C:\Users\Rajesh\Documents\Embarcadero\Studio\Projects\Samples\XML trail\Win32\Debug\nicexml.xml';
procedure Tfrm_XMLTrail.btn_AddClick(Sender: TObject);
begin
XMLDoc1.Active := true;
iNode := XMLDoc1.DocumentElement;
Root1 := iNode.ChildNodes.FindNode('Employees');
Root2 := Root1.AddChild('Employee');
Root2.Attributes['e.id'] := edt_eID.Text;
Child_Attrib_Name := Root2.AddChild('eName');
Child_Attrib_Name.Text := edtName.Text;
Child_Attrib_Place := Root2.AddChild('ePlace');
Child_Attrib_Place.Text := edtPlace.Text;
XMLDoc1.Active := true;
XMLDoc1.SaveToFile(scXmlFileName);
end;
procedure Tfrm_XMLTrail.FormCreate(Sender: TObject);
begin
XMLDoc1 := TXmlDocument.Create(nil);
if not FileExists(scXmlFileName) then
begin
// XMLDoc1 := TXmlDocument.Create(nil);
XMLDoc1.Active := true;
XMLDoc1.Options := [doNodeAutoIndent];
iNode := XMLDoc1.AddChild('UmangEmployeeDB');
Root1 := iNode.AddChild('Employees');
end
else
begin
LoadXML;
end;
end;
procedure Tfrm_XMLTrail.LoadXML;
begin
XMLDoc1.LoadFromFile(scXmlFileName);
Memo1.Lines.Text := XMLDoc1.XML.Text;
// SaveXML;
// Memo1.Lines.LoadFromFile(scXmlFileName);
// XMLDoc1 := TXmlDocument.Create(nil);
// Assert(Root1 <> Nil);
end;
procedure Tfrm_XMLTrail.SaveXML;
begin
Memo1.Lines.SaveToFile(scXmlFileName);
end;
end.
但是它返回了如下的XML文件:
<EmployeeDB>
<Employees>
<Employee e.id="2">
<eName>sssss</eName>
<ePlace>fgr</ePlace>
</Employee>
<Employee e.id="2">
<eName>sssss</eName>
<ePlace>fgr</ePlace>
</Employee>
</Employees>
</EmployeeDB>
应用程序的UI就像这个Image。
输入数据后单击“确定”按钮时,每次单击“确定”按钮时,都应通过创建新的<Employee/>
节点将数据写入XML文件。
答案 0 :(得分:2)
我通常不喜欢提交第二个答案但你似乎没有遵循 我在第一篇文章中所说的话。
下面是一个示例项目,它生成一个新的Xml文件并添加一个新的Employee 每次单击btnAdd按钮时节点。希望代码中的注释足以让您前进。
请注意,此项目使用MSXML.Pas单元中定义的Xml接口, 不使用XmlDoc单元。
unit XmlGenerateu;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, MSXML;
type
TForm1 = class(TForm)
Memo1: TMemo;
edtName: TEdit;
edtPlace: TEdit;
btnAdd: TButton;
procedure btnAddClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
procedure LoadXML;
procedure SaveXML;
procedure GenerateXML;
function CreateEmployeeNode: IXmlDomElement;
protected
public
XMLDoc : IXmlDomDocument;
EmployeesNode : IXmlDomNode;
NewEmployeeNode : IXmlDomNode;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
const
scXmlTemplate =
'<EmployeeDB>'#13#10
+ ' <Employees>'#13#10
+ ' </Employees>'#13#10
+ '</EmployeeDB>';
scXmlFileName = 'C:\Temp\Employees.Xml';
procedure TForm1.btnAddClick(Sender: TObject);
begin
NewEmployeeNode := CreateEmployeeNode;
Memo1.Lines.Text := XmlDoc.xml;
SaveXML;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
LoadXML;
end;
procedure TForm1.LoadXML;
begin
// If there is no existing Xml file create it from our Xml template
// and save it to disk
if not FileExists(scXmlFileName) then begin
Memo1.Lines.Text := scXmlTemplate;
SaveXML;
end;
Memo1.Lines.LoadFromFile(scXmlFileName);
// Create the XmlDoc object
XmlDoc := CoDomDocument.Create;
// Load it from Memo1
Assert(XmlDoc.LoadXml(Memo1.Lines.Text));
// Find the Employees node
EmployeesNode := XmlDoc.selectSingleNode('/EmployeeDB/Employees');
// Complain if we didn't find it
Assert(EmployeesNode <> Nil);
end;
procedure TForm1.SaveXML;
begin
Memo1.Lines.SaveToFile(scXmlFileName);
end;
function TForm1.CreateEmployeeNode : IXmlDomElement;
var
EmployeeID : Integer;
NameElement,
PlaceElement : IXmlDomElement;
begin
// First, generate the ID for the new Employee
EmployeeID := EmployeesNode.childNodes.length + 1;
// Next, get the XmlDoc to create a new Element
Result := XmlDoc.createElement('Employee');
// Set the new Element's ID attribute
Result.setAttribute('e.id', IntToStr(EmployeeID));
// Put the new Employee node at the end of the list of Employee nodes
EmployeesNode.appendChild(Result);
// Finally, createt eName and ePlace children of the new Employee
NameElement := XmlDoc.createElement('eName');
NameElement.text := edtName.Text;
Result.appendChild(NameElement);
PlaceElement := XmlDoc.createElement('ePlace');
PlaceElement.text := edtPlace.Text;
Result.appendChild(PlaceElement);
end;
<强>更新强>
您在评论中询问是否可以使用TXmlDocument代替 MSXML.Pas单元中的接口。我认为这将是一个很好的自我指导 练习所以我不打算用完整的代码来做,但这里有一些提示。
需要进行一些细节更改,例如如何从中加载XMLDocument Memo1,但主要的变化是如何找到Employees节点 的XML文档。最简单的方法是使用XPath查询(请参阅 上面的代码中的SelectSingleNode)但涉及使用相同的XML接口 就像在MSXML.Pas中一样,如果你想这样做,你也可以避免使用 TXMLDocument的。如果你想避免使用XPath,那么你可以编写两个函数, 返回EmployeeDB和Employees节点。这些可能看起来像这样
function TForm1.GetEmployeeDBNode(XmlDoc : TXmlDocument) : IXmlNode;
begin
Result := XmlDoc.DocumentElement;
Assert(Result <> Nil);
Assert(Result.NodeName = 'EmployeeDB');
end;
function TForm1.GetEmployeesNode(EmployeeDBNode : IXmlNode) : IXmlNode;
begin
Result := EmployeeDBNode.ChildNodes.First;
Assert(Result <> Nil);
Assert(Result.NodeName = 'Employees');
end;
您可以在CreateEmployeeNode
的改编版本中使用这些功能
通过在节点上调用AddChild('Employee')来添加新的Employee节点
由GetEmployeesNode返回。
顺便说一下,编写这些假定XML文档具有固定结构的函数的需要说明了为什么使用XPath更为可取,因为它更容易适应不同的XML结构,例如,如果EmployeeDB嵌入在一些更大的Xml结构中。使用XPath,这只需要更改XPath查询字符串。
答案 1 :(得分:1)
必须以这种方式修改代码,使用TXMLDocument创建XML文档,并在运行时将子元素附加到同一文档。谢谢你@MartynA先生的帮助..
unit XMLTrail;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, XMLIntf, XMLDoc, ComObj, xmldom,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
Tfrm_XMLTrail = class(TForm)
edt_eID: TEdit;
edtName: TEdit;
edtPlace: TEdit;
Memo1: TMemo;
btnAdd: TButton;
procedure btn_AddClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure LoadXML;
procedure SaveXML;
public
{ Public declarations }
gXMLDoc1: TXmlDocument;
giNode, gRoot1, gRoot2, gChild_Attrib_Name, gChild_Attrib_Place: IXmlNode;
function GetEmployeeDBNode(XMLDoc: TXmlDocument): IXmlNode;
function GetEmployeesNode(EmployeeDBNode: IXmlNode): IXmlNode;
function GetEmployeeNodes(EmployeeNodes: IXmlNode): IXmlNode;
end;
var
frm_XMLTrail: Tfrm_XMLTrail;
implementation
{$R *.dfm}
const
scXmlTemplate = '<EmployeeDB>'#13#10 + ' <Employees>'#13#10 +
' </Employees>'#13#10 + '</EmployeeDB>';
scXmlFileName =
'..\nicexml.xml';
procedure Tfrm_XMLTrail.btn_AddClick(Sender: TObject);
begin
gXMLDoc1.Active := true;
giNode := gXMLDoc1.DocumentElement;
gRoot1 := giNode.ChildNodes.FindNode('Employees');
gRoot2 := gRoot1.AddChild('Employee');
gRoot2.Attributes['e.id'] := edt_eID.Text;
gChild_Attrib_Name := gRoot2.AddChild('eName');
gChild_Attrib_Name.Text := edtName.Text;
gChild_Attrib_Place := gRoot2.AddChild('ePlace');
gChild_Attrib_Place.Text := edtPlace.Text;
gXMLDoc1.Active := true;
gXMLDoc1.XML.Text := XMLDoc.FormatXMLData(gXMLDoc1.XML.Text);
Memo1.Lines.Text := gXMLDoc1.XML.Text;
SaveXML;
end;
procedure Tfrm_XMLTrail.FormCreate(Sender: TObject);
begin
gXMLDoc1 := TXmlDocument.Create(self);
if not FileExists(scXmlFileName) then
begin
// XMLDoc1 := TXmlDocument.Create(nil);
gXMLDoc1.Active := true;
gXMLDoc1.Options := [doNodeAutoIndent];
giNode := gXMLDoc1.AddChild('EmployeeDB');
gRoot1 := giNode.AddChild('Employees');
end
else
begin
LoadXML;
end;
end;
procedure Tfrm_XMLTrail.LoadXML;
begin
gXMLDoc1.LoadFromFile(scXmlFileName);
gXMLDoc1.Active := true;
Memo1.Lines.Text := gXMLDoc1.XML.Text;
end;
procedure Tfrm_XMLTrail.SaveXML;
begin
Memo1.Lines.SaveToFile(scXmlFileName);
end;
function Tfrm_XMLTrail.GetEmployeeDBNode(XMLDoc: TXmlDocument): IXmlNode;
begin
Result := XMLDoc.DocumentElement;
Assert(Result <> Nil);
Assert(Result.NodeName = 'EmployeeDB');
end;
function Tfrm_XMLTrail.GetEmployeesNode(EmployeeDBNode: IXmlNode): IXmlNode;
begin
Result := EmployeeDBNode.ChildNodes.First;
Assert(Result <> Nil);
Assert(Result.NodeName = 'Employees');
end;
function Tfrm_XMLTrail.GetEmployeeNodes(EmployeeNodes: IXmlNode): IXmlNode;
begin
Result := EmployeeNodes.ChildNodes.First;
Assert(Result <> Nil);
Assert(Result.NodeName = 'Employee');
end;
end.