Repository URL to install this package:
|
Version:
3.2.0 ▾
|
unit extjsxml;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, httpdefs, fpextjs, dom, xmlread, xmlwrite, fpwebdata, db;
Type
{ TExtJSXMLWebdataInputAdaptor }
TExtJSXMLWebdataInputAdaptor = CLass(TCustomWebdataInputAdaptor)
private
FDE: String;
FRE: String;
FREEL: String;
FXML : TXMLDocument;
FDocRoot : TDOMElement;
FRoot : TDOMElement;
FCurrentRow : TDOMElement;
FIDValue : TDOMElement;
function isDocumentStored: boolean;
function IsRecordStored: boolean;
function isRootStored: boolean;
function CheckData: Boolean;
protected
Public
Constructor Create(AOwner : TComponent); override;
Destructor destroy; override;
Function TryFieldValue(Const AFieldName : String; out AValue : String) : Boolean; override;
Property DocumentElement : String Read FDE Write FDE stored isDocumentStored;
Property RootElement : String Read FRE Write FRE stored isRootStored;
Property RecordElement : String Read FREEL Write FREEL stored IsRecordStored;
end;
{ TExtJSJSONDataFormatter }
{ TExtJSXMLDataFormatter }
TXMLElementEvent = Procedure (Sender : TObject; AElement : TDOMElement) of object;
TXMLExceptionObjectEvent = Procedure(Sender : TObject; E : Exception; AResponse : TDOMElement) of Object;
TExtJSXMLDataFormatter = Class(TExtJSDataFormatter)
private
FAfterDataToXML: TXMLElementEvent;
FAfterRowToXML: TXMLElementEvent;
FBeforeDataToXML: TXMLElementEvent;
FBeforeRowToXML: TXMLElementEvent;
FDP: String;
FOnErrorResponse: TXmlExceptionObjectEvent;
FReP: String;
FRP: String;
function IsDocumentStored: boolean;
function IsRecordStored: boolean;
function IsRootStored: boolean;
protected
Function CreateAdaptor(ARequest : TRequest) : TCustomWebdataInputAdaptor; override;
Procedure DoExceptionToStream(E : Exception; ResponseContent : TStream); override;
Function GetDataContentType : String; override;
function RowToXML(Doc: TXMLDocument): TDOMelement;
Procedure DoBeforeRow(ARow : TDOMElement); virtual;
Procedure DoAfterRow(ARow : TDOMElement); virtual;
Procedure DoBeforeData(Data : TDOMElement); virtual;
Procedure DoAfterData(Data: TDOMElement); virtual;
procedure DatasetToStream(Stream: TStream); override;
public
Constructor Create(AOwner : TComponent); override;
published
Property RootProperty : String Read FRP Write FRP Stored IsRootStored;
Property RecordProperty : String Read FReP Write FReP Stored IsRecordStored;
Property DocumentProperty : String Read FDP Write FDP Stored IsDocumentStored;
// Called before row element (passed to handler) is filled with fields.
Property BeforeRowToXML : TXMLElementEvent Read FBeforeRowToXML Write FBeforeRowToXML;
// Called after row element (passed to handler) was filled with fields.
Property AfterRowToXML : TXMLElementEvent Read FAfterRowToXML Write FAfterRowToXML;
// Called before any rows are added to root element (passed to handler).
Property BeforeDataToXML : TXMLElementEvent Read FBeforeDataToXML Write FBeforeDataToXML;
// Called after all rows are appended to root element (passed to handler).
Property AfterDataToXML : TXMLElementEvent Read FAfterDataToXML Write FAfterDataToXML;
// Called when an exception is caught and formatted.
Property OnErrorResponse : TXmlExceptionObjectEvent Read FOnErrorResponse Write FOnErrorResponse;
end;
implementation
{ $define wmdebug}
{$ifdef wmdebug}
uses dbugintf;
{$endif wmdebug}
Resourcestring
SerrNoExceptionMessage = 'No exception to take error message from.';
Const
// For TExtJSXMLDataFormatter.
SDefDocumentProperty = 'xrequest';
SDefRecordProperty = 'row';
SDefRootProperty = 'dataset';
// Fpr TExtJSXMLWebdataInputAdaptor
SDefRootElement = SDefRootProperty;
SDefRecordElement = SDefRecordProperty;
SDefDocumentElement = SDefDocumentProperty;
function TExtJSXMLDataFormatter.IsRootStored: boolean;
begin
Result:=RootProperty<>SDefRootProperty;
end;
function TExtJSXMLDataFormatter.CreateAdaptor(ARequest: TRequest
): TCustomWebdataInputAdaptor;
Var
R : TExtJSXMLWebdataInputAdaptor;
begin
R:=TExtJSXMLWebdataInputAdaptor.Create(Self);
R.Request:=ARequest;
R.DocumentElement:=Self.DocumentProperty;
R.RootElement:=Self.RootProperty;
R.RecordElement:=Self.RecordProperty;
Result:=R;
end;
function TExtJSXMLDataFormatter.IsRecordStored: boolean;
begin
Result:=RecordProperty<>SDefRecordProperty;
end;
function TExtJSXMLDataFormatter.IsDocumentStored: boolean;
begin
Result:=DocumentProperty<>SDefDocumentProperty
end;
procedure TExtJSXMLDataFormatter.DoExceptionToStream(E: Exception;
ResponseContent: TStream);
Var
Xml : TXMLDocument;
El,C : TDOMElement;
begin
XML:=TXMLDocument.Create;
try
El:=XML.CreateElement(RootProperty);
XML.AppendChild(El);
El[SuccessProperty]:='false';
C:=XML.CreateElement(SuccessProperty);
C.AppendChild(XML.CreateTextNode('false'));
El.AppendChild(c);
C:=XML.CreateElement(MessageProperty);
El.AppendChild(C);
If Assigned(E) then
C.AppendChild(XML.CreateTextNode(E.Message))
else
C.AppendChild(XML.CreateTextNode(SerrNoExceptionMessage));
If Assigned(FOnErrorResponse) then
FOnErrorResponse(Self,E,El);
WriteXMLFile(XML,ResponseContent);
Finally
XML.Free;
end;
end;
function TExtJSXMLDataFormatter.GetDataContentType: String;
begin
Result:='text/xml';
end;
Function TExtJSXMLDataFormatter.RowToXML(Doc : TXMLDocument) : TDOMelement;
Var
E : TDOMElement;
F : TField;
I : Integer;
S : String;
begin
Result:=Doc.CreateElement(RecordProperty);
try
DoBeforeRow(Result);
For I:=0 to Dataset.Fields.Count-1 do
begin
F:=Dataset.Fields[i];
E:=Doc.CreateElement(F.FieldName);
If F.DataType in [ftMemo, ftFmtMemo, ftWideMemo, ftBlob ] then
S:=F.AsString
else
S:=F.DisplayText;
If (OnTranscode<>Nil) then
OnTranscode(Self,F,S,True);
E.AppendChild(Doc.CreateTextNode(S));
Result.AppendChild(E);
end;
DoAfterRow(Result);
except
Result.Free;
Raise;
end;
end;
procedure TExtJSXMLDataFormatter.DoBeforeRow(ARow: TDOMElement);
begin
If Assigned(FBEforeRowToXml) then
FBEforeRowToXml(Self,ARow);
end;
procedure TExtJSXMLDataFormatter.DoAfterRow(ARow: TDOMElement);
begin
If Assigned(FAfterRowToXml) then
FAfterRowToXml(Self,ARow);
end;
procedure TExtJSXMLDataFormatter.DoBeforeData(Data: TDOMElement);
begin
If Assigned(FBeforeDataToXML) then
FBeforeDataToXML(Self,Data);
end;
procedure TExtJSXMLDataFormatter.DoAfterDAta(Data: TDOMElement);
begin
If Assigned(FAfterDataToXML) then
FAfterDataToXML(Self,Data);
end;
procedure TExtJSXMLDataFormatter.DatasetToStream(Stream: TStream);
Var
Xml : TXMLDocument;
E,C : TDOMElement;
i,RCount,ACount : Integer;
DS : TDataset;
begin
RCount:=0;
ACount:=0;
DS:=Dataset;
XML:=TXMLDocument.Create;
try
E:=XML.CreateElement(RootProperty);
XML.AppendChild(E);
DoBeforeData(E);
// Go to start
ACount:=PageStart;
While (Not DS.EOF) and (ACount>0) do
begin
DS.Next;
Dec(ACount);
Inc(RCount);
end;
ACount:=PageSize;
While (not DS.EOF) and ((PageSize=0) or (ACount>0)) do
begin
Inc(RCount);
Dec(ACount);
E.AppendChild(RowToXML(XML));
DS.Next;
end;
If (PageSize>0) then
While (not DS.EOF) do
begin
Inc(RCount);
DS.Next;
end;
C:=XML.CreateElement(TotalProperty);
C.AppendChild(XML.CreateTextNode(IntToStr(RCount)));
E.AppendChild(C);
C:=XML.CreateElement(SuccessProperty);
C.AppendChild(XML.CreateTextNode('true'));
E.AppendChild(C);
DoAfterData(E);
WriteXMLFile(XML,Stream);
finally
XML.Free;
end;
end;
constructor TExtJSXMLDataFormatter.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
RootProperty:=SDefRootProperty;
RecordProperty:=SDefRecordProperty;
DocumentProperty:=SDefDocumentProperty
end;
{ TExtJSXMLWebdataInputAdaptor }
function TExtJSXMLWebdataInputAdaptor.isDocumentStored: boolean;
begin
Result:=DocumentElement<>SDefDocumentElement;
end;
function TExtJSXMLWebdataInputAdaptor.IsRecordStored: boolean;
begin
Result:=RecordElement<>SDefRecordElement;
end;
function TExtJSXMLWebdataInputAdaptor.isRootStored: boolean;
begin
Result:=RootElement<>SDefRootElement;
end;
function TExtJSXMLWebdataInputAdaptor.CheckData: Boolean;
Var
S : String;
T : TStringSTream;
E : TDomElement;
P : Integer;
begin
{$ifdef wmdebug}senddebug('Check data: '+Request.Content);{$endif}
Result:=Assigned(FXML);
If Not (Result) then
begin
S:=Request.ContentType;
P:=Pos(';',S);
If (P<>0) then
S:=Copy(S,1,P-1);
{$ifdef wmdebug}senddebug('Check data: '+S);{$endif}
Result:=CompareText(S,'application/x-www-form-urlencoded')=0;
If not Result then
begin
T:=TStringStream.Create(Request.Content);
try
XmlRead.ReadXMLFile(FXML,T);
If (DocumentElement<>'') and (FXML.DocumentElement.NodeName=DocumentElement) then
begin
{$ifdef wmdebug}senddebug('Document element is ExtJS DocumentElement');{$endif}
FDocRoot:=FXML.DocumentElement;
E:=FDocRoot;
end
else if (DocumentElement<>'') then
begin
//FXML.
{$ifdef wmdebug}senddebug('Looking for ExtJS Documentelement "'+DocumentElement+'" in XML.DocumentElement');{$endif}
FDocRoot:=FXML.DocumentElement.FindNode(DocumentElement) as TDOMElement;
E:=FDocRoot;
end;
{$ifdef wmdebug}senddebug('Looking for DocRoot element "'+RootElement+'" in FDocRoot');{$endif}
If Assigned(FDocRoot) then
FRoot:=FDocRoot
else
FRoot:=FXML.FindNode(RootElement) as TDomElement;
{$ifdef wmdebug}senddebug('Looking for current record element "'+RecordElement+'" in FRoot');{$endif}
If Assigned(FRoot) then
begin
FCurrentRow:=FRoot.FindNode(RecordElement) as TDomElement;
If Not Assigned(FCurrentRow) then
FIDValue:=FRoot.FindNode('ID') as TDomElement;
end
else
begin
{$ifdef wmdebug}senddebug('Looking for current record element "'+RecordElement+'" in document');{$endif}
FCurrentRow:=FXML.FindNode(RecordElement) as TDomElement;
end;
If (FCurrentRow=Nil) and (FXML.DocumentElement.NodeName=RecordElement) then
begin
{$ifdef wmdebug}senddebug('Documentelement is record element "'+RecordElement+'"');{$endif}
FCurrentRow:=FXML.DocumentElement;
end;
{$ifdef wmdebug}senddebug('Have current row: "'+IntToStr(Ord(Assigned(FCurrentRow)))+'"');{$endif}
Result:=True;
finally
T.free;
end;
end;
end;
end;
function TExtJSXMLWebdataInputAdaptor.TryFieldValue(const AFieldName: String;
out AValue: String): Boolean;
Var
I : Integer;
E : TDOMElement;
N : TDOMNode;
begin
Result:=False;
if CheckData then
begin
If Assigned(FIDValue) and (0=CompareText(AFieldName,'ID')) then
begin
AValue:=FIDValue.NodeValue;
Result:=True;
end
else if Assigned(FCurrentRow) then
begin
E:=FCurrentRow.FindNode(AFieldName) as TDomElement;
Result:=Assigned(E);
if result then
begin
N:=E.FirstChild;
If Assigned(N) then
AValue:=N.NodeValue;
end;
end;
end;
end;
constructor TExtJSXMLWebdataInputAdaptor.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
RootElement:=SDefRootElement;
RecordElement:=SDefRecordElement;
DocumentElement:=SDefDocumentElement;
end;
destructor TExtJSXMLWebdataInputAdaptor.destroy;
begin
FreeAndNil(FXML);
inherited destroy;
end;
initialization
WebDataProviderManager.RegisterInputAdaptor('ExtJS - XML',TExtJSXMLWebdataInputAdaptor);
WebDataProviderManager.RegisterDataProducer('ExtJS - XML',TExtJSXMLDataFormatter);
finalization
WebDataProviderManager.UnRegisterInputAdaptor('ExtJS - XML');
WebDataProviderManager.UnRegisterDataProducer('ExtJS - XML')
end.