⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs_xml.pas

📁 报表源码 FastReport 3 is new generation of the report generators components. It consists of report engin
💻 PAS
📖 第 1 页 / 共 2 页
字号:

{******************************************}
{                                          }
{             FastScript v1.8              }
{              XML document                }
{                                          }
{  (c) 2003-2005 by Alexander Tzyganenko,  }
{             Fast Reports Inc             }
{                                          }
{******************************************}

unit fs_xml;

interface

{$i fs.inc}

uses
  SysUtils, Classes;

type
  TfsXMLItem = class(TObject)
  private
    FData: Pointer;              { optional item data }
    FItems: TList;               { subitems }
    FName: String;               { item name }
    FParent: TfsXMLItem;         { item parent }
    FText: String;               { item attributes }
    function GetCount: Integer;
    function GetItems(Index: Integer): TfsXMLItem;
    function GetProp(Index: String): String;
    procedure SetProp(Index: String; const Value: String);
    procedure SetParent(const Value: TfsXMLItem);
  public
    destructor Destroy; override;
    procedure AddItem(Item: TfsXMLItem);
    procedure Assign(Item: TfsXMLItem);
    procedure Clear;
    procedure InsertItem(Index: Integer; Item: TfsXMLItem);

    function Add: TfsXMLItem;
    function Find(const Name: String): Integer;
    function FindItem(const Name: String): TfsXMLItem;
    function IndexOf(Item: TfsXMLItem): Integer;
    function PropExists(const Index: String): Boolean;
    function Root: TfsXMLItem;

    property Count: Integer read GetCount;
    property Data: Pointer read FData write FData;
    property Items[Index: Integer]: TfsXMLItem read GetItems; default;
    property Name: String read FName write FName;
    property Parent: TfsXMLItem read FParent write SetParent;
    property Prop[Index: String]: String read GetProp write SetProp;
    property Text: String read FText write FText;
  end;

  TfsXMLDocument = class(TObject)
  private
    FAutoIndent: Boolean;        { use indents when writing document to a file }
    FRoot: TfsXMLItem;           { root item }
  public
    constructor Create;
    destructor Destroy; override;
    procedure Clear;
    procedure SaveToStream(Stream: TStream);
    procedure LoadFromStream(Stream: TStream);
    procedure SaveToFile(const FileName: String);
    procedure LoadFromFile(const FileName: String);

    property AutoIndent: Boolean read FAutoIndent write FAutoIndent;
    property Root: TfsXMLItem read FRoot;
  end;

{ TfsXMLReader and TfsXMLWriter are doing actual read/write to the XML file.
  Read/write process is buffered. }

  TfsXMLReader = class(TObject)
  private
    FBuffer: PChar;
    FBufPos: Integer;
    FBufEnd: Integer;
    FPosition: Int64;
    FSize: Int64;
    FStream: TStream;
    procedure SetPosition(const Value: Int64);
    procedure ReadBuffer;
    procedure ReadItem(var Name, Text: String);
  public
    constructor Create(Stream: TStream);
    destructor Destroy; override;
    procedure RaiseException;
    procedure ReadHeader;
    procedure ReadRootItem(Item: TfsXMLItem);
    property Position: Int64 read FPosition write SetPosition;
    property Size: Int64 read FSize;
  end;

  TfsXMLWriter = class(TObject)
  private
    FAutoIndent: Boolean;
    FBuffer: String;
    FStream: TStream;
    FTempStream: TStream;
    procedure FlushBuffer;
    procedure WriteLn(const s: String);
    procedure WriteItem(Item: TfsXMLItem; Level: Integer = 0);
  public
    constructor Create(Stream: TStream);
    procedure WriteHeader;
    procedure WriteRootItem(RootItem: TfsXMLItem);
    property TempStream: TStream read FTempStream write FTempStream;
  end;


{ StrToXML changes '<', '>', '"', cr, lf symbols to its ascii codes }
function StrToXML(const s: String): String;

{ ValueToXML convert a value to the valid XML string }
function ValueToXML(const Value: Variant): String;

{ XMLToStr is opposite to StrToXML function }
function XMLToStr(const s: String): String;


implementation


function StrToXML(const s: String): String;
const
  SpecChars = ['<', '>', '"', #10, #13];
var
  i: Integer;

  procedure ReplaceChars(var s: String; i: Integer);
  begin
    Insert('#' + IntToStr(Ord(s[i])) + ';', s, i + 1);
    s[i] := '&';
  end;

begin
  Result := s;
  for i := Length(s) downto 1 do
    if s[i] in SpecChars then
      ReplaceChars(Result, i);
end;

function XMLToStr(const s: String): String;
var
  i, j, h, n: Integer;
begin
  Result := s;

  i := 1;
  n := Length(s);
  while i < n do
  begin
    if i + 3 <= n then
      if (Result[i] = '&') and (Result[i + 1] = '#') then
      begin
        j := i + 3;
        while Result[j] <> ';' do
          Inc(j);
        h := StrToInt(Copy(Result, i + 2, j - i - 2));
        Delete(Result, i, j - i);
        Result[i] := Chr(h);
        Dec(n, j - i);
      end;
    Inc(i);
  end;
end;

function ValueToXML(const Value: Variant): String;
begin
  case TVarData(Value).VType of
    varSmallint, varInteger, varByte:
      Result := IntToStr(Value);

    varSingle, varDouble, varCurrency:
      Result := FloatToStr(Value);

    varDate:
      Result := DateToStr(Value);

    varOleStr, varString, varVariant:
      Result := StrToXML(Value);

    varBoolean:
      if Value = True then Result := '1' else Result := '0';

    else
      Result := '';
  end;
end;


{ TfsXMLItem }

destructor TfsXMLItem.Destroy;
begin
  Clear;
  if FParent <> nil then
    FParent.FItems.Remove(Self);
  inherited;
end;

procedure TfsXMLItem.Clear;
begin
  if FItems <> nil then
  begin
    while FItems.Count > 0 do
      TfsXMLItem(FItems[0]).Free;
    FItems.Free;
    FItems := nil;
  end;
end;

function TfsXMLItem.GetItems(Index: Integer): TfsXMLItem;
begin
  Result := TfsXMLItem(FItems[Index]);
end;

function TfsXMLItem.GetCount: Integer;
begin
  if FItems = nil then
    Result := 0 else
    Result := FItems.Count;
end;

function TfsXMLItem.Add: TfsXMLItem;
begin
  Result := TfsXMLItem.Create;
  AddItem(Result);
end;

procedure TfsXMLItem.AddItem(Item: TfsXMLItem);
begin
  if FItems = nil then
    FItems := TList.Create;

  FItems.Add(Item);
  if Item.FParent <> nil then
    Item.FParent.FItems.Remove(Item);
  Item.FParent := Self;
end;

procedure TfsXMLItem.InsertItem(Index: Integer; Item: TfsXMLItem);
begin
  AddItem(Item);
  FItems.Delete(FItems.Count - 1);
  FItems.Insert(Index, Item);
end;

procedure TfsXMLItem.SetParent(const Value: TfsXMLItem);
begin
  if FParent <> nil then
    FParent.FItems.Remove(Self);
  FParent := Value;
end;

function TfsXMLItem.Find(const Name: String): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 0 to Count - 1 do
    if AnsiCompareText(Items[i].Name, Name) = 0 then
    begin
      Result := i;
      break;
    end;
end;

function TfsXMLItem.FindItem(const Name: String): TfsXMLItem;
var
  i: Integer;
begin
  i := Find(Name);
  if i = -1 then
  begin
    Result := Add;
    Result.Name := Name;
  end
  else
    Result := Items[i];
end;

function TfsXMLItem.Root: TfsXMLItem;
begin
  Result := Self;
  while Result.Parent <> nil do
    Result := Result.Parent;
end;

function TfsXMLItem.GetProp(Index: String): String;
var
  i: Integer;
begin
  i := Pos(' ' + AnsiUppercase(Index) + '="', AnsiUppercase(' ' + FText));
  if i <> 0 then
  begin
    Result := Copy(FText, i + Length(Index + '="'), MaxInt);
    Result := XMLToStr(Copy(Result, 1, Pos('"', Result) - 1));
  end
  else
    Result := '';
end;

procedure TfsXMLItem.SetProp(Index: String; const Value: String);
var
  i, j: Integer;
  s: String;
begin
  i := Pos(' ' + AnsiUppercase(Index) + '="', AnsiUppercase(' ' + FText));
  if i <> 0 then
  begin
    j := i + Length(Index + '="');
    while (j <= Length(FText)) and (FText[j] <> '"') do
      Inc(j);
    Delete(FText, i, j - i + 1);
  end
  else
    i := Length(FText) + 1;

  s := Index + '="' + StrToXML(Value) + '"';
  if (i > 1) and (FText[i - 1] <> ' ') then
    s := ' ' + s;
  Insert(s, FText, i);
end;

function TfsXMLItem.PropExists(const Index: String): Boolean;
begin
  Result := Pos(' ' + AnsiUppercase(Index) + '="', ' ' + AnsiUppercase(FText)) > 0;
end;

function TfsXMLItem.IndexOf(Item: TfsXMLItem): Integer;
begin
  Result := FItems.IndexOf(Item);
end;

procedure TfsXMLItem.Assign(Item: TfsXMLItem);

  procedure DoAssign(ItemFrom, ItemTo: TfsXMLItem);
  var
    i: Integer;
  begin
    ItemTo.Name := ItemFrom.Name;
    ItemTo.Text := ItemFrom.Text;
    ItemTo.Data := ItemFrom.Data;
    for i := 0 to ItemFrom.Count - 1 do
      DoAssign(ItemFrom[i], ItemTo.Add);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -