AsphyreXML.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:12k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit AsphyreXML;
  2. //---------------------------------------------------------------------------
  3. // AsphyreXML.pas                                       Modified: 08-Jan-2007
  4. // Asphyre XML wrapper                                            Version 1.0
  5. //---------------------------------------------------------------------------
  6. // Note: This component doesn't read or write data parts of XML and is
  7. // primarily used to read nodes and their attributes only. This is because
  8. // Asphyre does not use data parts of XML files.
  9. //---------------------------------------------------------------------------
  10. // The contents of this file are subject to the Mozilla Public License
  11. // Version 1.1 (the "License"); you may not use this file except in
  12. // compliance with the License. You may obtain a copy of the License at
  13. // http://www.mozilla.org/MPL/
  14. //
  15. // Software distributed under the License is distributed on an "AS IS"
  16. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  17. // License for the specific language governing rights and limitations
  18. // under the License.
  19. //---------------------------------------------------------------------------
  20. interface
  21. //---------------------------------------------------------------------------
  22. uses
  23.  Types, Classes, SysUtils, LibXMLParser;
  24. //---------------------------------------------------------------------------
  25. type
  26.  PXMLNodeField = ^TXMLNodeField;
  27.  TXMLNodeField = record
  28.   Name : string;
  29.   Value: string;
  30.  end;
  31. //---------------------------------------------------------------------------
  32.  TXMLNode = class
  33.  private
  34.   FName: string;
  35.   Nodes: array of TXMLNode;
  36.   Fields: array of TXMLNodeField;
  37.   function GetChildCount(): Integer;
  38.   function GetChild(Num: Integer): TXMLNode;
  39.   function GetChildNode(const Name: string): TXMLNode;
  40.   function GetFieldCount(): Integer;
  41.   function GetField(Num: Integer): PXMLNodeField;
  42.   function GetFieldValue(const Name: string): Variant;
  43.   procedure SetFieldValue(const Name: string; const Value: Variant);
  44.   function SubCode(Spacing: Integer): string;
  45.  public
  46.   property Name: string read FName;
  47.   property ChildCount: Integer read GetChildCount;
  48.   property Child[Num: Integer]: TXMLNode read GetChild;
  49.   property ChildNode[const Name: string]: TXMLNode read GetChildNode;
  50.   property FieldCount: Integer read GetFieldCount;
  51.   property Field[Num: Integer]: PXMLNodeField read GetField;
  52.   property FieldValue[const Name: string]: Variant read GetFieldValue write SetFieldValue;
  53.   function AddChild(const Name: string): TXMLNode;
  54.   function FindChildByName(const Name: string): Integer;
  55.   function AddField(const Name: string; const Value: Variant): PXMLNodeField;
  56.   function FindFieldByName(const Name: string): Integer;
  57.   function GetCode(): string;
  58.   procedure SaveToFile(const FileName: string);
  59.   function SaveToStream(const Key: string; OutStream: TStream): Boolean;
  60.   constructor Create(const AName: string);
  61.   destructor Destroy(); override;
  62.  end;
  63. //---------------------------------------------------------------------------
  64. function LoadXMLFromFile(const FileName: string): TXMLNode;
  65. function LoadXMLFromStream(InStream: TStream): TXMLNode;
  66. //---------------------------------------------------------------------------
  67. implementation
  68. //---------------------------------------------------------------------------
  69. function Spaces(Num: Integer): string;
  70. var
  71.  i: Integer;
  72. begin
  73.  Result:= '';
  74.  for i:= 0 to Num - 1 do
  75.   Result:= Result + ' ';
  76. end;
  77. //---------------------------------------------------------------------------
  78. constructor TXMLNode.Create(const AName: string);
  79. begin
  80.  inherited Create();
  81.  FName:= LowerCase(AName);
  82. end;
  83. //---------------------------------------------------------------------------
  84. destructor TXMLNode.Destroy();
  85. var
  86.  i: Integer;
  87. begin
  88.  for i:= 0 to Length(Nodes) - 1 do
  89.   if (Nodes[i] <> nil) then
  90.    begin
  91.     Nodes[i].Free();
  92.     Nodes[i]:= nil;
  93.    end;
  94.  SetLength(Nodes, 0);
  95.  inherited;
  96. end;
  97. //---------------------------------------------------------------------------
  98. function TXMLNode.GetChildCount(): Integer;
  99. begin
  100.  Result:= Length(Nodes);
  101. end;
  102. //---------------------------------------------------------------------------
  103. function TXMLNode.GetChild(Num: Integer): TXMLNode;
  104. begin
  105.  if (Num >= 0)and(Num < Length(Nodes)) then
  106.   Result:= Nodes[Num] else Result:= nil;
  107. end;
  108. //---------------------------------------------------------------------------
  109. function TXMLNode.FindChildByName(const Name: string): Integer;
  110. var
  111.  i: Integer;
  112. begin
  113.  Result:= -1;
  114.  for i:= 0 to Length(Nodes) - 1 do
  115.   if (Nodes[i].Name = Name) then
  116.    begin
  117.     Result:= i;
  118.     Break;
  119.    end;
  120. end;
  121. //---------------------------------------------------------------------------
  122. function TXMLNode.GetChildNode(const Name: string): TXMLNode;
  123. var
  124.  Index: Integer;
  125. begin
  126.  Index:= FindChildByName(Name);
  127.  if (Index <> -1) then Result:= Nodes[Index] else Result:= nil;
  128. end;
  129. //---------------------------------------------------------------------------
  130. function TXMLNode.GetFieldCount(): Integer;
  131. begin
  132.  Result:= Length(Fields);
  133. end;
  134. //---------------------------------------------------------------------------
  135. function TXMLNode.GetField(Num: Integer): PXMLNodeField;
  136. begin
  137.  if (Num >= 0)and(Num < Length(Fields)) then
  138.   Result:= @Fields[Num] else Result:= nil;
  139. end;
  140. //---------------------------------------------------------------------------
  141. function TXMLNode.FindFieldByName(const Name: string): Integer;
  142. var
  143.  i: Integer;
  144. begin
  145.  Result:= -1;
  146.  for i:= 0 to Length(Fields) - 1 do
  147.   if (Fields[i].Name = Name) then
  148.    begin
  149.     Result:= i;
  150.     Break;
  151.    end;
  152. end;
  153. //---------------------------------------------------------------------------
  154. function TXMLNode.GetFieldValue(const Name: string): Variant;
  155. var
  156.  Index: Integer;
  157. begin
  158.  Index:= FindFieldByName(Name);
  159.  if (Index <> -1) then Result:= Fields[Index].Value else Result:= '';
  160. end;
  161. //---------------------------------------------------------------------------
  162. procedure TXMLNode.SetFieldValue(const Name: string; const Value: Variant);
  163. var
  164.  Index: Integer;
  165. begin
  166.  Index:= FindFieldByName(Name);
  167.  if (Index <> -1) then Fields[Index].Value:= Value else AddField(Name, Value);
  168. end;
  169. //---------------------------------------------------------------------------
  170. function TXMLNode.AddChild(const Name: string): TXMLNode;
  171. var
  172.  Index: Integer;
  173. begin
  174.  Index:= Length(Nodes);
  175.  SetLength(Nodes, Index + 1);
  176.  Nodes[Index]:= TXMLNode.Create(Name);
  177.  Result:= Nodes[Index];
  178. end;
  179. //---------------------------------------------------------------------------
  180. function TXMLNode.AddField(const Name: string;
  181.  const Value: Variant): PXMLNodeField;
  182. var
  183.  Index: Integer;
  184. begin
  185.  Index:= Length(Fields);
  186.  SetLength(Fields, Index + 1);
  187.  Fields[Index].Name := Name;
  188.  Fields[Index].Value:= Value;
  189.  Result:= @Fields[Index];
  190. end;
  191. //---------------------------------------------------------------------------
  192. function TXMLNode.SubCode(Spacing: Integer): string;
  193. var
  194.  st: string;
  195.  i: Integer;
  196. begin
  197.  st:= Spaces(Spacing) + '<' + FName;
  198.  if (Length(Fields) > 0) then
  199.   begin
  200.    st:= st + ' ';
  201.    for i:= 0 to Length(Fields) - 1 do
  202.     begin
  203.      st:= st + Fields[i].Name + '="' + Fields[i].Value + '"';
  204.      if (i < Length(Fields) - 1) then st:= st + ' ';
  205.     end;
  206.   end;
  207.  if (Length(Nodes) > 0) then
  208.   begin
  209.    st:= st + '>'#13#10;
  210.    for i:= 0 to Length(Nodes) - 1 do
  211.     st:= st + Nodes[i].SubCode(Spacing + 1);
  212.    st:= st + Spaces(Spacing) + '</' + FName + '>'#13#10; 
  213.   end else st:= st + ' />'#13#10;
  214.  Result:= st; 
  215. end;
  216. //---------------------------------------------------------------------------
  217. function TXMLNode.GetCode(): string;
  218. begin
  219.  Result:= SubCode(0);
  220. end;
  221. //---------------------------------------------------------------------------
  222. procedure TXMLNode.SaveToFile(const FileName: string);
  223. var
  224.  Strings: TStrings;
  225. begin
  226.  Strings:= TStringList.Create();
  227.  Strings.Text:= GetCode();
  228.  try
  229.   Strings.SaveToFile(FileName);
  230.  finally
  231.   Strings.Free();
  232.  end;
  233. end;
  234. //---------------------------------------------------------------------------
  235. function TXMLNode.SaveToStream(const Key: string; OutStream: TStream): Boolean;
  236. var
  237.  Strings: TStrings;
  238. begin
  239.  Strings:= TStringList.Create();
  240.  Strings.Text:= GetCode();
  241.  Result:= True;
  242.  try
  243.   try
  244.    Strings.SaveToStream(OutStream);
  245.   except
  246.    Result:= False;
  247.   end;
  248.  finally
  249.   Strings.Free();
  250.  end;
  251. end;
  252. //--------------------------------------------------------------------------
  253. function LoadEmptyRootNode(Parser: TXMLParser): TXMLNode;
  254. var
  255.  i: Integer;
  256. begin
  257.  Result:= TXMLNode.Create(Parser.CurName);
  258.  with Parser.CurAttr do
  259.   for i:= 0 to Count - 1 do
  260.    Result.AddField(Name(i), Value(i));
  261. end;
  262. //---------------------------------------------------------------------------
  263. procedure LoadNodeBody(TopNode: TXMLNode; Parser: TXMLParser);
  264. var
  265.  Aux: TXMLNode;
  266.  i: Integer;
  267. begin
  268.  with Parser.CurAttr do
  269.   for i:= 0 to Count - 1 do
  270.    TopNode.AddField(Name(i), Value(i));
  271.  while (Parser.Scan()) do
  272.   case Parser.CurPartType of
  273.    ptEndTag:
  274.     Break;
  275.    ptEmptyTag:
  276.     begin
  277.      Aux:= TopNode.AddChild(Parser.CurName);
  278.      with Parser.CurAttr do
  279.       for i:= 0 to Count - 1 do
  280.        Aux.AddField(Name(i), Value(i));
  281.     end;
  282.    ptStartTag:
  283.     begin
  284.      Aux:= TopNode.AddChild(Parser.CurName);
  285.      LoadNodeBody(Aux, Parser);
  286.     end;
  287.   end;
  288. end;
  289. //---------------------------------------------------------------------------
  290. function LoadRootNode(Parser: TXMLParser): TXMLNode;
  291. var
  292.  Aux: TXMLNode;
  293.  i: Integer;
  294. begin
  295.  Result:= TXMLNode.Create(Parser.CurName);
  296.  // -> read attributes of root node
  297.  with Parser.CurAttr do
  298.   for i:= 0 to Count - 1 do
  299.    Result.AddField(Name(i), Value(i));
  300.  // -> parse the body
  301.  while (Parser.Scan()) do
  302.   case Parser.CurPartType of
  303.    // exit out of root node
  304.    ptEndTag:
  305.     Break;
  306.    // empty node inside of root node
  307.    ptEmptyTag:
  308.     begin
  309.      Aux:= Result.AddChild(Parser.CurName);
  310.      with Parser.CurAttr do
  311.       for i:= 0 to Count - 1 do
  312.        Aux.AddField(Name(i), Value(i));
  313.     end;
  314.    // new node owned by root node
  315.    ptStartTag:
  316.     begin
  317.      Aux:= Result.AddChild(Parser.CurName);
  318.      LoadNodeBody(Aux, Parser);
  319.     end;
  320.   end;
  321. end;
  322. //---------------------------------------------------------------------------
  323. function LoadXMLFromFile(const FileName: string): TXMLNode;
  324. var
  325.  Parser: TXMLParser;
  326. begin
  327.  Result:= nil;
  328.  Parser:= TXMLParser.Create();
  329.  try
  330.   Parser.LoadFromFile(FileName, fmOpenRead or fmShareDenyWrite);
  331.   Parser.Normalize:= False;
  332.   Parser.StartScan();
  333.   while (Parser.Scan()) do
  334.    case Parser.CurPartType of
  335.     ptEmptyTag:
  336.      begin
  337.       Result:= LoadEmptyRootNode(Parser);
  338.       Break;
  339.      end;
  340.     ptStartTag:
  341.      begin
  342.       Result:= LoadRootNode(Parser);
  343.       Break;
  344.      end;
  345.    end;
  346.  finally
  347.   Parser.Free();
  348.  end;
  349. end;
  350. //---------------------------------------------------------------------------
  351. function LoadXMLFromStream(InStream: TStream): TXMLNode;
  352. var
  353.  Strings: TStrings;
  354.  Parser : TXMLParser;
  355. begin
  356.  Result:= nil;
  357.  Strings:= TStringList.Create();
  358.  Parser:= TXMLParser.Create();
  359.  try
  360.   try
  361.    Strings.LoadFromStream(InStream);
  362.    Parser.LoadFromBuffer(PChar(Strings.Text));
  363.    Parser.Normalize:= False;
  364.    Parser.StartScan();
  365.    while (Parser.Scan()) do
  366.     case Parser.CurPartType of
  367.      ptEmptyTag:
  368.       begin
  369.        Result:= LoadEmptyRootNode(Parser);
  370.        Break;
  371.       end;
  372.      ptStartTag:
  373.       begin
  374.        Result:= LoadRootNode(Parser);
  375.        Break;
  376.       end;
  377.     end;
  378.   except
  379.    Result.Free();
  380.    Result:= nil;
  381.   end;
  382.  finally
  383.   Strings.Free();
  384.   Parser.Free();
  385.  end;
  386. end;
  387. //---------------------------------------------------------------------------
  388. end.