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

📄 xmlblocks.pas

📁 Delphi XML & XPATH源代码
💻 PAS
📖 第 1 页 / 共 4 页
字号:
unit XMLBlocks;

{
  XML Building Blocks
  Plug-and-play components for working with XML expressed as DOM documents.
  Producers generate new XML documents as DOMs.
  Consumers use those DOMs to amend or process them.

  Included are:
  TXBBParser          - generate DOMs from existing documents
  TXBBSQL             - generates DOMs from database queries
  TXBBTextFile        - generates DOMs around a text file's contents
  TXBBComponent       - generates DOMs from Delphi component properties

  TXBBMerge           - combines several DOMs into one new DOM
  TXBBFork            - sends a DOM to several consumers

  TXBBTimestamp       - add a timestamp element to a DOM
  TXBBTransform       - apply an XSL transformation to a DOM

  TXBBWriter          - send a DOM to a file or stream
  TXBBTreeView        - display a DOM in a tree view
  TXBBMemo            - display a DOM in a memo
  TXBBStringGrid      - display a DOM in a string grid
  TXBBWebBrowser      - display a DOM in a Web browser
  TXBBComponentCreate - create a component from the DOM

  Written by Keith Wood (kbwood@iprimus.com.au)
  Version 1.0 - 7 March 2002.
}

interface

uses
  Classes, SysUtils, StrUtils, Math, Graphics, Controls, ComCtrls, StdCtrls,
  ImgList, Grids, DB, DBTables, ShDocVw, ActiveX, XMLDOM;

type
  { Definition for the user of an XML document in DOM format }
  IXMLConsumer = interface
    ['{917863FF-96D1-40F9-9868-926D9C299068}']
    { Pass the DOM document along to be used and start processing it }
    procedure DocumentReady(Document: IDOMDocument);
  end;

  { Definition for the generator of an XML document in DOM format }
  IXMLProducer = interface
    ['{B53AF472-4B85-4F98-98B4-48501C81AE6A}']
    { Generate a new XML document and pass it to the consumer }
    procedure CreateDocument;
    function GetConsumer: IXMLConsumer;
    procedure SetConsumer(const Value: IXMLConsumer);
    { The consumer makes use of the new document }
    property Consumer: IXMLConsumer read GetConsumer write SetConsumer;
  end;

  { An XML Building Blocks specific exception }
  EXBBException = class(Exception)
  end;

  { Event to modify a newly created element }
  TXBBTagCreateEvent = procedure (Sender: TObject; Element: IDOMElement)
    of object;

  { Base class for developing consumers and producers.
    It's producer part (CreateDocument) does nothing. Override this for
    a new producer to actually generate the document and call DocumentReady.
    It's consumer part (DocumentReady) calls ProcessDocument to work on
    the document, then passes it along to any attached consumer.
    ProcessDocument just returns the original document without change.
    Override this for a new consumer. }
  TXMLBuildingBlock = class(TComponent, IXMLConsumer, IXMLProducer)
  private
    FConsumer: IXMLConsumer;
    FOnTagCreate: TXBBTagCreateEvent;
    FTagName: string;
    function GetConsumer: IXMLConsumer;
    procedure SetConsumer(const Value: IXMLConsumer);
  protected
    property Consumer: IXMLConsumer read GetConsumer write SetConsumer;
    property TagName: string read FTagName write FTagName;
    property OnTagCreate: TXBBTagCreateEvent read FOnTagCreate
      write FOnTagCreate;
    procedure DoOnTagCreate(Element: IDOMElement);
    function NewDocument(const TagName: string): IDOMDocument; virtual;
    procedure Notification(AComponent: TComponent; Operation: TOperation);
      override;
    procedure NotifyConsumer(Document: IDOMDocument);
    function ProcessDocument(const Document: IDOMDocument): IDOMDocument; virtual;
  public
    procedure CreateDocument; virtual;
    procedure DocumentReady(Document: IDOMDocument); virtual;
  end;

  { Create a new DOM from an existing XML document.
    The document can come from an existing file (XMLSource),
    from a stream (XMLStream), or from memory (XMLText). }
  TXBBParser = class(TXMLBuildingBlock)
  private
    FXMLSource: TFileName;
    FXMLStream: TStream;
    FXMLText: TStrings;
  public
    constructor Create(AOwner: TComponent); overload; override;
    constructor Create(AOwner: TComponent; const XMLSource: TFileName);
      reintroduce; overload;
    constructor Create(AOwner: TComponent; const XMLStream: TStream);
      reintroduce; overload;
    constructor Create(AOwner: TComponent; const XMLText: TStrings);
      reintroduce; overload;
    destructor Destroy; override;
    procedure CreateDocument; override;
  published
    property Consumer;
    property XMLSource: TFileName read FXMLSource write FXMLSource;
    property XMLStream: TStream read FXMLStream write FXMLStream;
    property XMLText: TStrings read FXMLText write FXMLText;
  end;

  { Event to modify a newly created record element }
  TXBBRecordTagCreateEvent = procedure (Sender: TObject; Element: IDOMElement;
    Dataset: TDataSet) of object;

  TXBBFieldFormat = (xfText, xfElement, xfAttributeOnly);

  { Create a new DOM from an SQL query.
    The DatabaseName and SQL properties retrieve data which is then made
    into an XML document. The top-level tag is named according to the
    TagName property, or from the DatabaseName if this is blank.
    Each row from the query becomes an element under this, using
    RecordTagName as its name, or 'record' if this is blank.
    Fields from the query then become child elements of the record,
    with names taken from the field name, and contents as text or
    CDATA section (if they contain '<' or '>') nodes. }
  TXBBSQL = class(TXMLBuildingBlock)
  private
    FDatabaseName: string;
    FFieldFormat: TXBBFieldFormat;
    FOnRecordTagCreate: TXBBRecordTagCreateEvent;
    FRecordTagName: string;
    FSQL: TStrings;
    procedure GetText(Sender: TField; var Text: String; DisplayText: Boolean);
  public
    constructor Create(AOwner: TComponent); overload; override;
    constructor Create(AOwner: TComponent; const TagName: string);
      reintroduce; overload;
    constructor Create(AOwner: TComponent; const DatabaseName: string;
      const SQL: TStrings; const TagName: string = ''); reintroduce; overload;
    destructor Destroy; override;
    procedure CreateDocument; override;
  published
    property Consumer;
    property DatabaseName: string read FDatabaseName write FDatabaseName;
    property FieldFormat: TXBBFieldFormat read FFieldFormat write FFieldFormat
      default xfText;
    property RecordTagName: string read FRecordTagName write FRecordTagName;
    property SQL: TStrings read FSQL write FSQL;
    property TagName;
    property OnRecordTagCreate: TXBBRecordTagCreateEvent read FOnRecordTagCreate
      write FOnRecordTagCreate;
    property OnTagCreate;
  end;

  { Create a new DOM around the contents of a text file.
    The FileName property locates the file which is then made
    into an XML document. The top-level tag is named according to the
    TagName property, or 'file' if this is blank. It contains a single
    text or CDATA section node (depending on the AsCDATA property)
    that has the file's contents. }
  TXBBTextFile = class(TXMLBuildingBlock)
  private
    FAsCDATA: Boolean;
    FFileName: TFileName;
  public
    constructor Create(AOwner: TComponent; const FileName: TFileName = '';
      const TagName: string = ''); reintroduce; overload;
    procedure CreateDocument; override;
  published
    property AsCDATA: Boolean read FAsCDATA write FAsCDATA default False;
    property Consumer;
    property FileName: TFileName read FFileName write FFileName;
    property TagName;
    property OnTagCreate;
  end;

  { Create a new DOM around the properties of a component.
    Components appear within 'object' elements with 'name' and 'type'
    attributes. Properties appear within embedded 'property' elements
    with 'name' and 'value' attributes. Collections items appear as
    'item' elements within a property. }
  TXBBComponent = class(TXMLBuildingBlock)
  private
    FComponent: TComponent;
  public
    constructor Create(AOwner: TComponent; const TagName: string = '';
      const Component: TComponent = nil); reintroduce; overload;
    procedure CreateDocument; override;
  published
    property Component: TComponent read FComponent write FComponent;
    property Consumer;
    property TagName;
    property OnTagCreate;
  end;

  { Write out the DOM to a given file or stream.
    Set one of FileName or Stream before using this component. }
  TXBBWriter = class(TXMLBuildingBlock)
  private
    FFileName: TFileName;
    FStream: TStream;
  protected
    function ProcessDocument(const Document: IDOMDocument): IDOMDocument;
      override;
  public
    constructor Create(AOwner: TComponent; const FileName: TFileName);
      reintroduce; overload;
    constructor Create(AOwner: TComponent; const Stream: TStream);
      reintroduce; overload;
  published
    property Consumer;
    property FileName: TFileName read FFileName write FFileName;
    property Stream: TStream read FStream write FStream;
  end;

  { Merge several DOM documents together in a new document under a new
    main element (named from the TagName property).
    Set the number of documents to expect with the NumDocuments property.
    When this many have appeared via the DocumentReady method and been
    combined, they are sent on to this component's consumer.
    Reset the component for another combination by setting NumDocuments again. }
  TXBBMerge = class(TXMLBuildingBlock)
  private
    FCountDown: Integer;
    FMergedDocument: IDOMDocument;
    FNumDocuments: Integer;
    procedure SetNumDocuments(Value: Integer);
  public
    constructor Create(AOwner: TComponent; const NumDocuments: Integer = 2;
      const TagName: string = ''); reintroduce; overload;
    procedure DocumentReady(Document: IDOMDocument); override;
  published
    property Consumer;
    property NumDocuments: Integer read FNumDocuments write SetNumDocuments;
    property TagName;
    property OnTagCreate;
  end;

  { A consumer item for a collection. }
  TXBBConsumerCollectionItem = class(TCollectionItem)
  private
    FConsumer: IXMLConsumer;
    FName: string;
    procedure SetConsumer(Value: IXMLConsumer);
    procedure SetName(Value: string);
  protected
    function GetDisplayName: string; override;
  published
    property Consumer: IXMLConsumer read FConsumer write SetConsumer;
    property Name: string read FName write SetName;
  end;

  { A collection of consumers. }
  TXBBConsumerCollection = class(TCollection)
  private
    FOwner: TPersistent;
  protected
    function GetItem(Index: Integer): TXBBConsumerCollectionItem;
    function  GetOwner: TPersistent; override;
    procedure SetItem(Index: Integer; Value: TXBBConsumerCollectionItem);
  public
    constructor Create(Owner: TPersistent);
    function Add: TXBBConsumerCollectionItem;
    function FindItemID(ID: Integer): TXBBConsumerCollectionItem;
    function Insert(Index: Integer): TXBBConsumerCollectionItem;
    property Items[Index: Integer]: TXBBConsumerCollectionItem
      read GetItem write SetItem;
  end;

  { Pass a DOM document off to several consumers. }
  TXBBFork = class(TXMLBuildingBlock)
  private
    FConsumers: TXBBConsumerCollection;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure DocumentReady(Document: IDOMDocument); override;
  published
    property Consumers: TXBBConsumerCollection read FConsumers write FConsumers;
  end;

  { Apply an XSL transformation to a DOM document.
    The document can come from an existing file (XSLSource),
    from a stream (XSLStream), or from memory (XSLText). }
  TXBBTransform = class(TXMLBuildingBlock)
  private
    FXSLSource: TFileName;
    FXSLStream: TStream;
    FXSLText: TStrings;
  protected
    function ProcessDocument(const Document: IDOMDocument): IDOMDocument;
      override;
  public
    constructor Create(AOwner: TComponent); overload; override;
    constructor Create(AOwner: TComponent; const XSLSource: TFileName);
      reintroduce; overload;
    constructor Create(AOwner: TComponent; const XSLStream: TStream);
      reintroduce; overload;
    constructor Create(AOwner: TComponent; const XSLText: TStrings);
      reintroduce; overload;
    destructor Destroy; override;
  published
    property Consumer;
    property XSLSource: TFileName read FXSLSource write FXSLSource;
    property XSLStream: TStream read FXSLStream write FXSLStream;
    property XSLText: TStrings read FXSLText write FXSLText;
  end;

  { Add a timestamp to a DOM. The timestamp appears as a separate element
    named from the TagName property (or 'timestamp' if that is blank)
    that appears first or last under the existing document's
    main element (depending on the InsertAtStart property.
    The Format property defines the appearance of the timestamp and uses the
    same notation as required by the FormatDateTime function.
    Format can be extended to generate multiple date parts beneath the
    timestamp element. Separate sub-elements with vertical bars ( | ),
    and sub-element names from formats with equals ( = ). For example,
    a Format of 'year=yyyy|month=MM|day=dd' creates the following structure:
    <timestamp><year>2002</year><month>03</month><day>07</day></timestamp>.
    Prefix a name with '@' to make it an attribute instead. For example,
    a Format of '@year=yyyy|@month=MM|@day=dd' creates the following structure:
    <timestamp year="2002" month="03" day="07"/>. }
  TXBBTimestamp = class(TXMLBuildingBlock)
  private
    FFormat: string;
    FInsertAtStart: Boolean;
    procedure SetFormat(const Value: string);
  protected
    function ProcessDocument(const Document: IDOMDocument): IDOMDocument;
      override;
  public
    constructor Create(AOwner: TComponent; const Format: string = '';
      const TagName: string = ''); reintroduce; overload;
  published
    property Consumer;
    property Format: string read FFormat write SetFormat;
    property InsertAtStart: Boolean read FInsertAtStart write FInsertAtStart;
    property TagName;
  end;

  { The node types }
  TXBBNodeType = (ntElement, ntAttribute, ntText, ntCDATA, ntEntityReference,
    ntEntity, ntProcessingInstr, ntComment, ntDocument, ntDocumentType,
    ntDocumentFragment, ntNotation);
  { The types of nodes to process }
  TXBBNodeTypes = set of TXBBNodeType;

  { An object wrapper of an interface for use in a tree. }
  TXBBNodePointer = class(TObject)
  public
    Node: IDOMNode;
    constructor Create(Node: IDOMNode);
  end;

  { Display a DOM within a tree view.
    The nodes as selected by the ShowNodes property are inserted into the
    attached tree view (TreeView property). Each node is assigned an
    image index corresponding to its node type. Assign an appropriate
    image list to the tree view to display these. You can use the
    DefaultNodeImages variable from this unit. }
  TXBBTreeView = class(TXMLBuildingBlock)
  private
    FShowNodes: TXBBNodeTypes;
    FTreeView: TTreeView;
    procedure SetTreeView(Value: TTreeView);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation);
      override;
    function ProcessDocument(const Document: IDOMDocument): IDOMDocument;
      override;
  public
    constructor Create(AOwner: TComponent); overload; override;
    constructor Create(AOwner: TComponent; const TreeView: TTreeView);
      reintroduce; overload;
    destructor Destroy; override;
    procedure ClearTree;
  published
    property Consumer;
    property ShowNodes: TXBBNodeTypes read FShowNodes write FShowNodes
      default [ntElement..ntNotation];
    property TreeView: TTreeView read FTreeView write SetTreeView;
  end;

  { Display a DOM within a memo.
    The XML text corresponding to the DOM is displayed in the attached
    memo (Memo property). }
  TXBBMemo = class(TXMLBuildingBlock)
  private
    FMemo: TMemo;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation);
      override;
    function ProcessDocument(const Document: IDOMDocument): IDOMDocument;
      override;
  public
    constructor Create(AOwner: TComponent; const Memo: TMemo = nil);
      reintroduce; overload;
  published
    property Consumer;
    property Memo: TMemo read FMemo write FMemo;
  end;

  { Display a DOM within a string grid.
    The values from the nodes immediately beneath the document element
    in the document provided are displayed in the attached string grid
    (StringGrid property).
    If SingleNode is True (the default), the nodes are shown in two columns.
    The first is the node's name, the second is the node's value.
    If SingleNode is False, the nodes are assumed to be multiple copies of

⌨️ 快捷键说明

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