如何在XML文档中写入多条记录?Delphi代码问题求助
Delphi XML保存数组记录仅保留最后一条的问题修复
问题说明
尝试将记录数组中的word和boolean值保存到XML文档时,执行后仅保留了数组的最后一条记录——循环中仅修改了第一个节点的属性,未创建新节点。
原Delphi代码
procedure AddArrayToXMLFile(const Array : array of TKeycodeRecord; const Name : string); var XMLFile : IXMLDocument; NameNode, ArrayFieldNode: IXMLNode; i : integer; begin if FileExists(ArrayXMLFilePath) then begin XMLFile := LoadXMLDocument(ArrayXMLFilePath); end else begin XMLFile := NewXMLDocument; NameNode := XMLFile.AddChild(Name); ArrayFieldNode := NameNode.AddChild('child'); end; for i := 0 to Length(Array) - 1 do begin ArrayFieldNode.Attributes['keycode'] := Array[i].keycode; ArrayFieldNode.Attributes['shiftState'] := Array[i].shiftState; end; XMLFile.SaveToFile(ArrayXMLFilePath); end;
当前执行结果
<?xml version="1.0"?> <TestName><child keycode="48" shiftState="false"/></TestName>
期望结果(二选一)
形式一:多根节点形式(不符合XML标准规范)
<?xml version="1.0"?> <TestName><child keycode="52" shiftState="false"/></TestName> <TestName><child keycode="70" shiftState="true"/></TestName> <TestName><child keycode="75" shiftState="false"/></TestName> <TestName><child keycode="49" shiftState="false"/></TestName> <TestName><child keycode="48" shiftState="false"/></TestName>
形式二:单根节点下多子节点形式(推荐,符合XML规范)
<?xml version="1.0"?> <TestName> <child keycode="48" shiftState="false"/> <child keycode="49" shiftState="false"/> <child keycode="48" shiftState="false"/> </TestName>
问题原因及修复方案
核心原因
原代码中ArrayFieldNode仅在XML初始化时创建一次,循环中反复修改同一个节点的属性,最终只会保留最后一次赋值的结果。
方案一:实现多根节点形式(不推荐)
标准XML要求必须有且仅有一个根节点,此形式会导致多数XML解析器报错。若确需此结构,需放弃IXMLDocument,改用文本拼接写入:
procedure AddArrayToXMLFile(const Array : array of TKeycodeRecord; const Name : string); var SL: TStringList; i: Integer; begin SL := TStringList.Create; try if FileExists(ArrayXMLFilePath) then SL.LoadFromFile(ArrayXMLFilePath) else SL.Add('<?xml version="1.0"?>'); for i := 0 to Length(Array) - 1 do begin SL.Add(Format('<%s><child keycode="%d" shiftState="%s"/></%s>', [Name, Array[i].keycode, BoolToStr(Array[i].shiftState, True), Name])); end; SL.SaveToFile(ArrayXMLFilePath); finally SL.Free; end; end;
方案二:实现单根节点多子节点形式(推荐)
此方案符合XML规范,后续解析更便捷:
procedure AddArrayToXMLFile(const Array : array of TKeycodeRecord; const Name : string); var XMLFile : IXMLDocument; NameNode, ArrayFieldNode: IXMLNode; i : integer; begin if FileExists(ArrayXMLFilePath) then begin XMLFile := LoadXMLDocument(ArrayXMLFilePath); // 获取或创建指定名称的根节点 NameNode := XMLFile.DocumentElement; if NameNode.NodeName <> Name then NameNode := XMLFile.AddChild(Name); end else begin XMLFile := NewXMLDocument; XMLFile.Encoding := 'UTF-8'; // 建议指定编码 NameNode := XMLFile.AddChild(Name); end; for i := 0 to Length(Array) - 1 do begin // 每次循环创建新的child节点 ArrayFieldNode := NameNode.AddChild('child'); ArrayFieldNode.Attributes['keycode'] := Array[i].keycode; ArrayFieldNode.Attributes['shiftState'] := Array[i].shiftState; end; XMLFile.SaveToFile(ArrayXMLFilePath); end;
内容的提问来源于stack exchange,提问作者Ineffable21
相关产品推荐
相关产品推荐

