You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:28:11