【问题标题】:Delphi Modify Existing XML Document StructureDelphi 修改现有 XML 文档结构
【发布时间】:2017-03-01 21:09:11
【问题描述】:

我有一个包含嵌套表的现有 XML 文档。我想打开它,读入并修改结构(即添加或删除列/字段)。忽略嵌套表,这是一个完整的 XML 测试文档:

<DATAPACKET Version="2.0">
  <METADATA>
    <FIELDS>
      <FIELD attrname="StringField" fieldtype="string" WIDTH="20" /> 
      <FIELD attrname="IntField" fieldtype="i4" /> 
    </FIELDS>
    <PARAMS CHANGE_LOG="1 0 4 2 0 4" /> 
  </METADATA>
  <ROWDATA>
    <ROW RowState="4" StringField="String" IntField="234" /> 
    <ROW RowState="4" StringField="234" IntField="24" /> 
  </ROWDATA>
</DATAPACKET>

以下代码在打开时抛出未找到“testField”的异常,可能是因为它在基础 XML 文件中不存在。

ClientDataSet1.Close;

with TStringField.Create(ClientDataSet1) do 
begin
  FieldName := 'testField';
  DataSet := ClientDataSet1; 
end; 

with ClientDataSet1 do 
begin 
  CreateDataSet; 
  Open; 
end; 

如果我添加:

with ClientDataSet1 do
begin
  FieldDefs.Clear;
  Fields.Clear;
end;

不会引发异常,但前两个字段会消失,除非我输入一些数据,否则新结构不会写入 XML doc 文件。

<DATAPACKET Version="2.0">
  <METADATA>
    <FIELDS>
      <FIELD attrname="testField" fieldtype="string" WIDTH="20" /> 
    </FIELDS>
    <PARAMS CHANGE_LOG="1 0 4" /> 
  </METADATA>
  <ROWDATA>
    <ROW RowState="4" testField="12321" /> 
  </ROWDATA>
</DATAPACKET>

是否有标准或推荐的方法可以在不丢失数据的情况下向现有 XML 文档添加字段?

干杯, 制革商

【问题讨论】:

  • 嗯,这取决于。有很多选择。
  • 您应该在您的 q 中添加一个完整 XML 文档的最小示例,包括您添加的字段。如果操作正确,这种 XML 修改通常不会出现问题,但您需要清除 CDS 上的所有持久 TField 和 TFieldDef,否则您很可能会收到报告的错误。
  • 并且无论如何,请保持最小,例如仅使用两个字段的单个测试数据集。不要发布包含 30 列和 500 条记录的整个海量 XML 数据集。
  • 大卫,比如....?
  • MartynA,我明天将尝试清除持久性字段和定义。谢谢。您可以提供任何链接作为示例吗?我遇到的所有似乎都是针对新的 XMLdocs,而不是扩展现有的。

标签: xml delphi xml-parsing tclientdataset


【解决方案1】:

您的方法并不正确;对于初学者,CreateDataSet 完全删除之前在 ClientDataSet 中的所有数据

接下来的事情是您不想使用持久字段和/或 FieldDefs 就位,因此在您进行更改时清除它们。之后是否创建它们取决于您,但如果您要在代码中创建 TField,您应该为 XML 元数据中的 每个 字段创建一个,从 CDS 中的空字段列表开始。

下面的示例项目应该向您展示如何获得您所追求的。它

  • 从 TMemo、Memo1 中的 XML 加载数据集。在我的,我只是复制 并从您的 q 中粘贴 XML。这一步基本上是为了显示数据集 已正确填充;

  • 然后,AddFieldToXML 中的代码将新字段添加到 XML 中的元数据和 将结果复制到 Memo2,并将其保存到磁盘。注意:正如所写,它不 将任何数据写入新字段,但您应该能够了解如何 从AddFieldToXML 执行此操作。

最后,它通过从改变的 XML 加载 CDS 来关闭并重新打开它

代码:

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, DBCtrls, Grids, DBGrids, DB, DBClient, MSXML;

type
  TForm1 = class(TForm)
    CDS1: TClientDataSet;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  public
    ExistingFN : String;
    NewFN : String;
    procedure AddFieldToXML;
    procedure LoadNewData;
  end;
[...]
procedure TForm1.FormCreate(Sender: TObject);
begin
  ExistingFN :=  'C:\Temp\Data.XML';
  NewFN := 'C:\Temp\NewData.XML';

  Memo1.Lines.SaveToFile(ExistingFN);

  CDS1.Fields.Clear;
  CDS1.FieldDefs.Clear;
  CDS1.LoadFromFile(ExistingFN);

end;

procedure TForm1.AddFieldToXML;
var
  XmlDoc: IXMLDOMDocument;
  NodeList : IXmlDOMNodeList;
  Node,
  NewNode : IXmlDomNode;
  E : IXmlDomElement;
  PathQuery : String;
begin
  PathQuery := '/DATAPACKET/METADATA/FIELDS';

  Memo2.Lines.Clear;
  XmlDoc := CoDOMDocument.Create; //CreateOleObject('Microsoft.XMLDOM') as IXMLDOMDocument;
  XmlDoc.Async := False;
  XmlDoc.LoadXML(Memo1.Lines.Text);
  if xmlDoc.parseError.errorCode <> 0 then
    raise Exception.Create('XML Load error:' + xmlDoc.parseError.reason);

  NodeList := XmlDoc.documentElement.SelectNodes(PathQuery);

  if NodeList.length > 0 then begin
    E := XMLDoc.createElement('FIELD');
    NewNode := E as IXMLDomNode;
    E.setAttribute('attrname', 'testField');
    E.setAttribute('fieldtype', 'string');
    E.setAttribute('WIDTH', '20');
    NodeList.item[0].appendChild(NewNode);
  end;
  Memo2.Lines.Text := XMLDoc.documentElement.xml;
  Memo2.Lines.SaveToFile(NewFN);
end;

procedure TForm1.LoadNewData;
begin
  CDS1.Close;
  CDS1.Fields.Clear;
  CDS1.FieldDefs.Clear;
  CDS1.LoadFromFile(NewFN);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  AddFieldToXML;
  LoadNewData;
end;

将新的 XML 保存到磁盘后,可以通过右键单击 CDS 并使用 Load from MyBase file(对于 D7,以后版本类似)将其加载到 IDE 中的 CDS,然后创建持久 TField如果你愿意。

XML 代码适用于 D7 附带的 MSXML.Pas 版本,顺便说一句。我倾向于发布 D7 的代码,除非 q 需要更高版本的 Delphi。

【讨论】:

  • @user2765744:嗯,这对您的问题有帮助吗?
猜你喜欢
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 2012-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多