目前,XML 和 JSON 格式已成为计算机系统间数据存储和信息交换的主要标准。应用户要求,FastScript 中已添加用于处理 XML 和 JSON 的类。在本文中,我们将深入研究如何使用这些类,探索它们的属性和方法,以及如何使用脚本从代码创建报告。
XML 格式
为了在脚本中使用 XML,需要使用两个类。这两个类专注于最高速度和低内存消耗。

TfrXMLDocument – 封装 XML 文档功能的类。它包含以下属性和方法。
类的属性和方法 | 描述 |
procedure SaveToStream(Stream: TStream); | 将 XML 保存到传递的流中。 |
procedure LoadFromStream(Stream: TStream; AllowPartialLoading: Boolean = False); | 从传递的流中加载 XML。 |
procedure SaveToFile(const FileName: string); | 将 XML 保存到具有指定名称的文件中。 |
procedure LoadFromFile(const FileName: string); | 从具有指定名称的文件中加载 XML。 |
procedure Clear; | 删除树中除根节点之外的所有 XML 节点。节点的内容不会被清除。 |
property Root: TfrXMLItem; | 允许访问树的根元素。 |
property AsText: string; | 允许您获取和设置 XML 作为字符串(例如,使用此属性,您可以使用报告变量将 XML 传递给报告脚本)。 |
property AutoIndent: Boolean; | 确定如何生成输出 XML:作为单行还是作为缩进文本。 |
TfrXMLNode – 封装 XML 文档节点属性的类。
您无法直接创建此类型的对象。它是通过调用要添加子元素的元素的 Add() 方法来创建的。让我们仔细看看 TfrXMLNode 类的属性和方法。
类的属性和方法 | 描述 |
function Add(AName:string):TfrXMLItem; | 创建具有指定名称的子 TfrXMLItem 并返回它。 |
procedure Clear; | 清除子元素列表。 |
procedure InsertItem(Index:integer; AItem: TfrXMLItem); | 将子元素插入到指定位置。该元素可能属于另一个文档。 |
function Find(AName:string):Integer; | 在子元素中搜索指定名称的 TfrXMLItem 并返回。如果未找到,则返回 -1。如果有多个指定名称的元素,则返回第一个。 |
function FindItem(AName:string):TfrXMLItem; | 在子元素中搜索指定名称的 TfrXMLItem 并返回。如果未找到,则创建并返回一个指定名称的新元素。如果有多个指定名称的元素,则返回第一个。 |
function Root: TfrXMLItem; | 返回文档的根元素。 |
property Count:Integer; | 返回元素的子节点的数量。 |
property Items[AIndex:Integer]: TfrXMLItem; | 根据索引返回子元素。 |
property Prop[AName:string]:string; | 返回或设置具有指定名称的节点属性的值。 |
property Name: string; | 元素的标签名称。 |
property Parent: TfrXMLItem; | 父元素的名称。Root 为 nil。 |
property Text:string; | 包含节点参数列表的字符串,格式为 Name1="Value1" Name2="Value2"… 此字符串中的特殊字符用引号引起来。 |
procedure Delete(AIndex: Integer); | 删除具有 AIndex 的子元素。 |
procedure DeleteProp(const APropName: string); | 删除具有指定名称的节点的属性。 |
property Value: string; | 位于元素的开始和结束标记之间的文本。 |
function PropExists(APropName:string):Boolean; | 帮助确定元素是否具有指定名称的属性。 |
function IndexOf(AItem: TfrXMLItem):Integer; | 返回传递元素的索引。 |
function GetPropNames(ANames:TStrings); | 使用 TfrXMLItem 属性的名称填充传递的字符串列表。 |
让我们尝试使用用于处理 XML 的类来构建一个报表。例如,我们将在报表中显示来自“country.xml”文件的数据,但我们不会使用 TClientDataSet,而是直接访问 XML 文件。我们创建一个新报表,进入编辑模式,将 MasterData 添加到报表中。并在顶部添加几个 Memo 来显示数据。我们还将为 MasterData 对象创建一个 OnBeforePrint 事件。
最终的报告脚本代码将如下所示:
var doc: TfrXMLDocument;
item: TfrXMLItem;
IIndex: Integer;
procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
var cur: TfrXMLItem;
S: string;
begin
cur := item[IIndex];
mmNum.Text := cur.Prop['Code'];
mmName.Text := cur.Prop['Name'];
mmCapital.Text := cur.Prop['Capital'];
mmArea.Text := cur.Prop['Area'];
mmPopulation.Text := cur.Prop['Population'];
mmContinent.Text := cur.Prop['Continent'];
Inc(IIndex);
end;
begin
Doc := TfrXMLDocument.Create;
Doc.LoadFromFile('..\..\Data\country.xml');
item := Doc.Root[1];
IIndex := 0;
MasterData1.RowCount := item.count;
end.
让我们继续运行报告。为了更易于阅读,我们还添加了列标题。

JSON 格式
让我们顺利地从 XML 过渡到 JSON 格式。为了在 FastReport 中使用 JSON,还需要用到两个类—— TfrJSON和TfrJSONArray。在本例中,这两个类只是 Delphi 平台中 System.JSON 类或 Lazarus 中类似类的包装器。

TfrJSONObject — 封装用于处理 JSON 对象的函数的类。
类的属性和方法 | 描述 |
function Create(const JSONstring: string); | 创建一个 JSON 对象并根据提供的字符串填充它。 |
function IsValid:Boolean; | 如果对象包含有效的 JSON,则返回 True。 |
procedure LodFromFile(const AFilName:string); | 从指定文件加载数据。如果对象包含数据,则数据将会丢失。 |
procedure LoadFromtStream(const AStream:TStream); | 从提供的流中加载数据。如果对象包含数据,则数据将会丢失。 |
function ToString:string; | 返回包含 JSON 对象的文本表示形式的字符串。 |
procedure SaveToFile(const AFileName: string); | 将 JSON 对象的文本表示保存到文件。 |
procedure SaveToStream(AStream: TStream | 将 JSON 对象的文本表示保存到流中。 |
function IsNameExists(const AName:string); | 如果对象具有指定名称的属性,则返回 True。 |
function IsNameValueExists(const Name, Value: string): boolean; | 如果对象具有指定名称的属性并且其值与指定值匹配,则返回 True。 |
function Count:Integer; | 返回 JSON 对象中的属性总数。 |
property Names[AIndex:Integer]:string; | 返回指定索引处的属性的名称。 |
Property ValueType[IndexOrName:Variant]:TfrJSONType; | 返回指定索引或名称处属性的类型。该类型可以是以下值之一: - jsUnknown - 属性类型未知(发生解析错误或缺少具有此类索引或名称的属性)。- jsNumber - 属性为数字类型。- jsString - 属性为字符串类型。- jsBoolean - 属性为布尔类型 (true/false)。- jsNull - 属性类型为空(未分配值)。- jsList - 属性类型为 JSON 数组。- jsObject - 属性类型为嵌套 JSON 对象。 |
以下属性允许您以某种形式检索 JSON 对象的值。在所有这些属性中,索引都是通过属性列表中的属性编号或其名称执行的。请注意AsString['1'] <> AsString[1]。此外,如果您尝试使用不合适的方法获取属性值,则可能会发生错误并返回错误的属性值。例如,如果属性的类型为“Object”或“Array”,那么当您尝试使用 AsString 属性获取其值时,您将得到一个空字符串。在其他情况下,AsString 将返回属性值的字符串表示形式。
类的属性和方法 | 描述 |
property AsObject[IndexOrName: Variant]: TfrxJSON; | 允许您检索嵌套的 JSON 对象。 |
property AsArray[IndexOrName: Variant]: TfrJSONArray; | 允许您检索嵌套的 JSON 数组。 |
Property AsString[IndexOrName: Variant]: string; | 允许您以字符串形式检索属性值。此检索方法适用于除对象和数组之外的其他类型的属性。对于布尔值,将返回包含“True”或“False”值的字符串。对于包含小数部分的数字,无论区域设置如何,始终使用点作为小数部分的分隔符。 |
property AsNumber[IndexOrName: Variant]: Extended; | 允许您以数字形式检索属性的值。如果属性为非数字类型,则返回 0。 |
property AsBoolean[IndexOrName: Variant]: Boolean; | 允许您以布尔值的形式检索属性的值。如果属性属于其他类型,则返回 False。 |
要返回 null 类型的字段,您需要付出一些努力。目前没有专门的方法来实现这一点。但是,您可以使用 ValueType 属性,该属性会为 null 类型的字段返回 jsNull;或者使用 AsString 属性,该属性会返回字符串“null”。
让我们仔细看看操作对象属性的方法。
类方法 | 描述 |
Procedure Delete(AName: String); | 从对象中删除具有指定名称的属性。 |
function AddObject(const AName: string): Integer | 向对象添加具有指定名称的子空对象。 |
function AddArray(const AName: string): Integer; | 将具有指定名称的空数组添加到对象。 |
function AddString(const AName, AValue: string): Integer; | 将具有指定名称的字符串添加到对象。 |
function AddBool(const AName: string; AValue: boolean): Integer; | 将具有指定名称的布尔值添加到对象。 |
function AddNumber(const AName: string; AValue:Extended): Integer; | 将具有指定名称的数值实数添加到对象。 |
function AddInteger(const AName: string; AValue:Integer): Integer; | 将具有指定名称的数字整数值添加到对象。 |
function AddNull(const AName: string): Integer; | 向对象添加具有指定名称的空值。 |
该方法返回一个整数,它是所有字段列表中添加的元素的索引。
所有向对象添加字段的方法都不会控制现有同名字段的存在。此过程由使用此类的程序员负责。这种控制对于防止输出 JSON 中出现多个同名字段至关重要。在这种情况下,系统的行为是不确定的——它取决于进一步解析接收 JSON 的解析器。这意味着可以使用任何同名的值!
TJSONArray类封装了用于处理 JSON 数组的方法和属性。主要属性原则上相同,但只能通过索引访问它们。仅支持访问元素、获取元素值或删除元素的操作。您无法移动数组中的元素或更改其类型。让我们来研究一下此类中用于获取元素值的属性和方法。
类的属性和方法 | 描述 |
function Count:Integer; | 返回数组中的元素数量。 |
property ValueType[AIndex: Integer]: TfrJSONType; | 返回具有指定索引的数组元素的类型。 |
property AsObject[AIndex: Integer]: TfrJSONObject; | 返回一个对象,以 JSON 对象的形式提供对数组元素的访问。 |
Property AsArray[AIndex: Integer]: TfrJSONArray | 返回一个对象,以 JSON 数组的形式提供对数组元素的访问。 |
property AsString[AIndex: Integer]: string; | 以字符串形式返回数组元素的值。 |
property AsNumber[AIndex: Integer]: Extended; | 以数字形式返回数组元素的值。 |
property AsBoolean[AIndex: Integer]: Boolean; | 以布尔值形式返回数组元素的值。 |
处理数组时,就像处理对象一样,提取元素值时需要谨慎。根据值的类型,使用适当的方法来检索它。
下面介绍操作 JSON 数组元素的方法。
类的属性和方法 | 描述 |
procedure Delete(AIndex:Integer); | 删除指定索引处的数组元素。 |
function AddObject: Integer; | 将嵌套的 JSON 对象添加到数组末尾。 |
function AddArray: Integer; | 将嵌套的 JSON 数组添加到数组末尾。 |
function AddString(const AValue: string): Integer; | 将字符串添加到数组末尾。 |
function AddBool(AValue: boolean): Integer; | 将布尔值添加到数组末尾。 |
function AddNumber(AValue:Extended): Integer; | 将浮点数添加到数组的末尾。 |
function AddInteger(AValue: Integer): Integer; | 将一个整数添加到数组的末尾。 |
function AddNull: Integer; | 将 null 添加到数组末尾。 |
所有这些方法都返回添加到数组的元素的位置。您无法将元素插入到数组的中间;这是 System.JSON 基类的限制。
使用类访问 JSON 的细节
使用对象时,务必记住,使用包装对象后,必须将其从代码中全部删除。
请注意,如果您想要获取子对象或数组,但实际获取的是一个标量值或根本没有值,则该属性将返回 nil,并且在进一步访问该属性时将引发异常。请避免使用不适用于元素中存储的特定类型值的方法来检索这些值。
重要的是要注意,对象的属性名称区分大小写,这意味着“Item1”和“item1”被视为不同的名称!
只有当对象元素的值类型与元素定义的类型匹配时,您才能为其设置值。如果您需要重新定义元素的类型,请删除该元素,然后添加一个具有相同名称且类型为所需元素的新元素。无法为数组元素输入新值。您需要删除 JSON 数组,然后使用所需的值重新创建它。
让我们使用上面描述中的类并编写一个脚本,从 XML 文件中提取数据(不带类型信息)并将其放入 JSON 对象中。
procedure XMLToJSON;
var XML: TfrXMLDocument;
xi, xi1: TfrXMLItem;
I, J: Integer;
JO: TfrJSONObject;
JA, JA1: TfrJSONArray;
SL: TStringList;
begin
XML:=TfrXMLDocument.Create;
XML.LoadFromFile('.\..\..\data\country.xml');
JO:=TfrJSONObject.Create('{}');
JO.AddArray('data');
JA:=JO.AsArray['data'];
xi:=X.Root[1];
xi1:=xi.Items[0];
SL:=TStringList.Create;
xi1.GetParamNames(SL);
for I:=0 to xi.Count - 1 do begin
xi1:=xi.Items[I];
JA1:=JA.AsArray[JA.AddArray];
for J:=0 to SL.Count-1 do
JA1.AddString(xi1.Prop[SL[J]]);
JA1.Free;
end;
JA.Free;
JO.SaveToFile('.\..\..\data\country.json');
JO.Free;
SL.Free;
end;
并且让我们尝试根据获得的数据构建一份报告(首先,在报告页面上放置适当的 MasterData 和 Memo 组件):
var J:TfrJSONObject;
A:TfrJSONArray;
curr:Integer;
procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
var A1:TfrJSONArray;
begin
A1:=A.AsArray(curr);
Memo1.Memo.Text:=A1.AsString[0];
Memo2.Memo.Text:=A1.AsString[1];
Memo3.Memo.Text:=A1.AsString[2];
Memo4.Memo.Text:=A1.AsString[3];
Memo5.Memo.Text:=A1.AsString[4];
Memo6.Memo.Text:=A1.AsString[5];
A1.Free;
curr := curr + 1;
end;
begin
J:=TfrJSONObject.Create('');
J.LoadFromFile('.\..\..\data\country.json');
A:=J.AsArray[0];
MasterData1.RowCount:=A.Count;
curr:=0;
end.

您还可以在 Delphi 代码中使用这些对象 - 只需在 uses 语句中包含 frXML 和 frJSON 模块。
结论
在本文中,我们探讨了在 FastReport 中使用类来处理 JSON 和 XML。如果您不仅使用报表,还使用 Delphi 和 Lazarus,那么使用这些类将有助于最大限度地减少在环境之间切换时出现的问题——您的体验将在两个 IDE 上保持一致。
_________________________________________________________
关于慧都科技:
慧都科技是一家行业数字化解决方案公司,长期专注于软件、油气与制造行业。公司基于深入的业务理解与管理洞察,以系统化的业务建模驱动技术落地,帮助企业实现智能化运营与长期竞争优势。在软件工程领域,我们提供开发控件、研发管理、代码开发、部署运维等软件开发全链路所需的产品,提供正版授权采购、技术选型、个性化维保等服务,帮助客户实现技术合规、降本增效与风险可控。慧都科技是FastReports的在中国区的合作伙伴,FastReports作为图表报表领域的优秀产品,帮助企业实现轻松构建高性能的表格及图表。
下载或体验FastReport产品,请联系在线客服咨询,或拨打产品热线:023-68661681
欢迎加入FastReport技术QQ群:170305738,与更多小伙伴探讨报表开发技能。
欢迎任何形式的转载,但请务必注明出处,尊重他人劳动成果
转载请注明:文章转载自:FastReport控件中文网 [https://www.fastreportcn.com/]
本文地址:https://www.fastreportcn.com/post/3748.html