You've already forked lazarus-ccr
SOAP "ID" and "href" handling in the serialized xml stream.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@730 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -39,6 +39,7 @@ const
|
|||||||
|
|
||||||
sHEADER = 'Header';
|
sHEADER = 'Header';
|
||||||
sENVELOPE = 'Envelope';
|
sENVELOPE = 'Envelope';
|
||||||
|
sHREF = 'href';
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -60,7 +61,8 @@ type
|
|||||||
FScopeObject: TDOMNode;
|
FScopeObject: TDOMNode;
|
||||||
FScopeType: TScopeType;
|
FScopeType: TScopeType;
|
||||||
protected
|
protected
|
||||||
function GetItemsCount() : Integer;virtual;
|
function GetItemsCount : Integer;virtual;
|
||||||
|
function GetActualNodeIfIsHRef(const ANode : TDOMNode) : TDOMNode;
|
||||||
Public
|
Public
|
||||||
constructor Create(AScopeObject : TDOMNode;AScopeType : TScopeType);
|
constructor Create(AScopeObject : TDOMNode;AScopeType : TScopeType);
|
||||||
function FindNode(var ANodeName : string):TDOMNode;virtual;abstract;
|
function FindNode(var ANodeName : string):TDOMNode;virtual;abstract;
|
||||||
@ -437,6 +439,9 @@ type
|
|||||||
|
|
||||||
function BoolToSoapBool(const AValue : Boolean) : string;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
function BoolToSoapBool(const AValue : Boolean) : string;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||||
|
|
||||||
|
resourcestring
|
||||||
|
SERR_NodeNotFoundByID = 'Node not found with this ID in the document : %s.';
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
Uses {$IFDEF WST_DELPHI}XMLDoc,XMLIntf,{$ELSE}XMLWrite, XMLRead,wst_fpc_xml,{$ENDIF}
|
Uses {$IFDEF WST_DELPHI}XMLDoc,XMLIntf,{$ELSE}XMLWrite, XMLRead,wst_fpc_xml,{$ENDIF}
|
||||||
StrUtils, imp_utils;
|
StrUtils, imp_utils;
|
||||||
@ -457,6 +462,41 @@ begin
|
|||||||
Result := GetNodeItemsCount(ScopeObject);
|
Result := GetNodeItemsCount(ScopeObject);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TStackItem.GetActualNodeIfIsHRef(const ANode: TDOMNode): TDOMNode;
|
||||||
|
var
|
||||||
|
locAttrs : TDOMNamedNodeMap;
|
||||||
|
|
||||||
|
function FollowIfNeeded() : TDOMNode;
|
||||||
|
var
|
||||||
|
locNode : TDOMNode;
|
||||||
|
locHRefValue : DOMString;
|
||||||
|
begin
|
||||||
|
locNode := locAttrs.GetNamedItem(sHREF);
|
||||||
|
if ( locNode = nil ) or ( Length(locNode.NodeValue) = 0 ) then begin
|
||||||
|
Result := ANode;
|
||||||
|
end else begin
|
||||||
|
locHRefValue := locNode.NodeValue;
|
||||||
|
if ( locHRefValue[1] = '#' ) then
|
||||||
|
locHRefValue := Copy(locHRefValue,2,Length(locHRefValue));
|
||||||
|
Result := SelectSingleNode(Format('//*[@id=%s]',[locHRefValue]),locNode.OwnerDocument,True);
|
||||||
|
//ANode.OwnerDocument.GetElementById(locHRefValue);
|
||||||
|
if ( Result = nil ) then
|
||||||
|
raise ESOAPException.CreateFmt(SERR_NodeNotFoundByID,[locHRefValue]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if ( ANode = nil ) then begin
|
||||||
|
Result := nil;
|
||||||
|
end else begin
|
||||||
|
locAttrs := ANode.Attributes;
|
||||||
|
if ( locAttrs <> nil ) and ( locAttrs.Length > 0 ) then
|
||||||
|
Result := FollowIfNeeded()
|
||||||
|
else
|
||||||
|
Result := ANode;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TStackItem.Create(AScopeObject: TDOMNode; AScopeType: TScopeType);
|
constructor TStackItem.Create(AScopeObject: TDOMNode; AScopeType: TScopeType);
|
||||||
begin
|
begin
|
||||||
FScopeObject := AScopeObject;
|
FScopeObject := AScopeObject;
|
||||||
@ -503,6 +543,7 @@ begin
|
|||||||
{$ELSE}
|
{$ELSE}
|
||||||
Result := ScopeObject.FindNode(ANodeName);
|
Result := ScopeObject.FindNode(ANodeName);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
Result := GetActualNodeIfIsHRef(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TAbstractArrayStackItem }
|
{ TAbstractArrayStackItem }
|
||||||
@ -549,6 +590,7 @@ begin
|
|||||||
Result:= FItemList.Item[FIndex];
|
Result:= FItemList.Item[FIndex];
|
||||||
Inc(FIndex);
|
Inc(FIndex);
|
||||||
ANodeName := Result.NodeName;
|
ANodeName := Result.NodeName;
|
||||||
|
Result := GetActualNodeIfIsHRef(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TSOAPBaseFormatter }
|
{ TSOAPBaseFormatter }
|
||||||
|
@ -135,6 +135,22 @@ type
|
|||||||
procedure read_header_simple_content_2();
|
procedure read_header_simple_content_2();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
THRefTestSession = class(TBaseComplexRemotable)
|
||||||
|
private
|
||||||
|
FSessionID : string;
|
||||||
|
FPartnerID : integer;
|
||||||
|
published
|
||||||
|
property SessionID : string read FSessionID write FSessionID;
|
||||||
|
property PartnerID : integer read FPartnerID write FPartnerID;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TTest_SoapFormatterClient }
|
||||||
|
|
||||||
|
TTest_SoapFormatterClient = class(TTestCase)
|
||||||
|
published
|
||||||
|
procedure test_soap_href_id();
|
||||||
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
uses
|
uses
|
||||||
object_serializer, server_service_soap, test_suite_utils, soap_formatter;
|
object_serializer, server_service_soap, test_suite_utils, soap_formatter;
|
||||||
@ -607,6 +623,57 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TTest_SoapFormatterClient }
|
||||||
|
|
||||||
|
procedure TTest_SoapFormatterClient.test_soap_href_id();
|
||||||
|
const
|
||||||
|
XML_SOURCE =
|
||||||
|
'<?xml version="1.0"?>' + sLineBreak +
|
||||||
|
'<SOAP-ENV:Envelope ' + sLineBreak +
|
||||||
|
' xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" ' + sLineBreak +
|
||||||
|
' xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' + sLineBreak +
|
||||||
|
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' + sLineBreak +
|
||||||
|
' xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">' + sLineBreak +
|
||||||
|
' ' + sLineBreak +
|
||||||
|
' <SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' + sLineBreak +
|
||||||
|
' <NS1:GetSessionResponse xmlns:NS1="urn:WS_PlotjetIntfU-IWS_Plotjet" xmlns:NS2="urn:WS_PlotjetIntfU">' + sLineBreak +
|
||||||
|
' <NS2:TSession id="1" xsi:type="NS2:TSession">' + sLineBreak +
|
||||||
|
' <SessionID xsi:type="xsd:string">Some GID</SessionID>' + sLineBreak +
|
||||||
|
' <PartnerID xsi:type="xsd:int">12</PartnerID>' + sLineBreak +
|
||||||
|
' </NS2:TSession>' + sLineBreak +
|
||||||
|
' <return href="#1"/>' + sLineBreak +
|
||||||
|
' </NS1:GetSessionResponse>' + sLineBreak +
|
||||||
|
' </SOAP-ENV:Body>' + sLineBreak +
|
||||||
|
'</SOAP-ENV:Envelope>';
|
||||||
|
var
|
||||||
|
f : IFormatterClient;
|
||||||
|
strm : TMemoryStream;
|
||||||
|
strBuffer : ansistring;
|
||||||
|
cctx : ICallContext;
|
||||||
|
locReturn : THRefTestSession;
|
||||||
|
locStrPrmName : string;
|
||||||
|
begin
|
||||||
|
f := soap_formatter.TSOAPFormatter.Create() as IFormatterClient;
|
||||||
|
strm := TMemoryStream.Create();
|
||||||
|
try
|
||||||
|
strBuffer := XML_SOURCE;
|
||||||
|
strm.Write(strBuffer[1],Length(strBuffer));
|
||||||
|
strm.Position := 0;
|
||||||
|
f.LoadFromStream(strm);
|
||||||
|
cctx := TSimpleCallContext.Create() as ICallContext;
|
||||||
|
f.BeginCallRead(cctx);
|
||||||
|
locReturn := nil;
|
||||||
|
locStrPrmName := 'return';
|
||||||
|
f.Get(TypeInfo(THRefTestSession),locStrPrmName,locReturn);
|
||||||
|
CheckNotNull(locReturn,'return');
|
||||||
|
CheckEquals('Some GID',locReturn.SessionID,'SessionID');
|
||||||
|
CheckEquals(12,locReturn.PartnerID,'PartnerID');
|
||||||
|
f.EndScopeRead();
|
||||||
|
finally
|
||||||
|
FreeAndNil(strm);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
|
|
||||||
GetTypeRegistry().Register(TSampleSimpleContentHeaderBlock_A.GetNameSpace(),TypeInfo(TSampleSimpleContentHeaderBlock_A));
|
GetTypeRegistry().Register(TSampleSimpleContentHeaderBlock_A.GetNameSpace(),TypeInfo(TSampleSimpleContentHeaderBlock_A));
|
||||||
@ -618,9 +685,11 @@ initialization
|
|||||||
GetTypeRegistry().Register(TNameSpaceB_Class.GetNameSpace(),TypeInfo(TNameSpaceB_Class));
|
GetTypeRegistry().Register(TNameSpaceB_Class.GetNameSpace(),TypeInfo(TNameSpaceB_Class));
|
||||||
GetTypeRegistry().Register(TNameSpaceC_Class.GetNameSpace(),TypeInfo(TNameSpaceC_Class));
|
GetTypeRegistry().Register(TNameSpaceC_Class.GetNameSpace(),TypeInfo(TNameSpaceC_Class));
|
||||||
GetTypeRegistry().Register(ns_soap_test,TypeInfo(TSOAPTestEnum));
|
GetTypeRegistry().Register(ns_soap_test,TypeInfo(TSOAPTestEnum));
|
||||||
|
GetTypeRegistry().Register('urn:WS_PlotjetIntfU',TypeInfo(THRefTestSession),'TSession');
|
||||||
|
|
||||||
RegisterTest('Serializer',TTest_SoapFormatterServerNameSpace.Suite);
|
RegisterTest('Serializer',TTest_SoapFormatterServerNameSpace.Suite);
|
||||||
RegisterTest('Serializer',TTest_SoapFormatterHeader.Suite);
|
RegisterTest('Serializer',TTest_SoapFormatterHeader.Suite);
|
||||||
|
RegisterTest('Serializer',TTest_SoapFormatterClient.Suite);
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -34,7 +34,15 @@ type
|
|||||||
|
|
||||||
function FilterList(const ALIst : IDOMNodeList; const ANodeName : DOMString):IDOMNodeList;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
function FilterList(const ALIst : IDOMNodeList; const ANodeName : DOMString):IDOMNodeList;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||||
function FilterList(const ANode : TDOMNode; const ANodeName : DOMString):IDOMNodeList;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
function FilterList(const ANode : TDOMNode; const ANodeName : DOMString):IDOMNodeList;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||||
|
function SelectSingleNode(
|
||||||
|
const AXPathExpression : DOMString;
|
||||||
|
const AContextNode : TDOMNode;
|
||||||
|
const AErrorIfMore : Boolean
|
||||||
|
) : TDOMNode;
|
||||||
|
|
||||||
|
resourcestring
|
||||||
|
SERR_XpathExpectingOneNode = 'Xpath expression expecting a single node while got %d node : %s.';
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
uses XmlDoc;
|
uses XmlDoc;
|
||||||
|
|
||||||
@ -168,7 +176,7 @@ type
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function FilterList(const ALIst : IDOMNodeList; const ANodeName : widestring):IDOMNodeList ;
|
function FilterList(const ALIst : IDOMNodeList; const ANodeName : DOMString):IDOMNodeList ;
|
||||||
begin
|
begin
|
||||||
Result := TDOMNodeSelectListImp.Create(ALIst,ANodeName);
|
Result := TDOMNodeSelectListImp.Create(ALIst,ANodeName);
|
||||||
end;
|
end;
|
||||||
@ -178,6 +186,25 @@ begin
|
|||||||
Result := FilterList(ANode.ChildNodes,ANodeName);
|
Result := FilterList(ANode.ChildNodes,ANodeName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function SelectSingleNode(
|
||||||
|
const AXPathExpression : DOMString;
|
||||||
|
const AContextNode : TDOMNode;
|
||||||
|
const AErrorIfMore : Boolean
|
||||||
|
) : TDOMNode;
|
||||||
|
var
|
||||||
|
locSelect : IDOMNodeSelect;
|
||||||
|
ns : TDOMNodeList;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
locSelect := AContextNode as IDOMNodeSelect;
|
||||||
|
ns := locSelect.selectNodes(AXPathExpression);
|
||||||
|
if ( ns <> nil ) and ( ns.length > 0 ) then begin
|
||||||
|
if AErrorIfMore and ( ns.length > 1 ) then
|
||||||
|
raise Exception.CreateFmt(SERR_XpathExpectingOneNode,[ns.length,AXPathExpression]);
|
||||||
|
Result := ns[0];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDOMNodeSelectListImp }
|
{ TDOMNodeSelectListImp }
|
||||||
|
|
||||||
constructor TDOMNodeSelectListImp.Create(
|
constructor TDOMNodeSelectListImp.Create(
|
||||||
|
@ -24,6 +24,12 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function FilterList(const ANode : TDOMNode; const ANodeName : DOMString) : TDOMNodeList ;
|
function FilterList(const ANode : TDOMNode; const ANodeName : DOMString) : TDOMNodeList ;
|
||||||
|
function SelectSingleNode(
|
||||||
|
const AXPathExpression : DOMString;
|
||||||
|
const AContextNode : TDOMNode;
|
||||||
|
const AErrorIfMore : Boolean
|
||||||
|
) : TDOMNode;
|
||||||
|
|
||||||
|
|
||||||
function GetNodeItemsCount(const ANode : TDOMNode): Integer;
|
function GetNodeItemsCount(const ANode : TDOMNode): Integer;
|
||||||
function GetNodeListCount(ANodeList : TDOMNodeList) : Integer ;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
function GetNodeListCount(ANodeList : TDOMNodeList) : Integer ;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||||
@ -36,8 +42,13 @@ type
|
|||||||
|
|
||||||
function NodeToBuffer(ANode : TDOMNode):string ;
|
function NodeToBuffer(ANode : TDOMNode):string ;
|
||||||
|
|
||||||
|
resourcestring
|
||||||
|
SERR_NoNodeXpathExpression = 'This XPath expression does not correspond to node(s) : %s.';
|
||||||
|
SERR_XpathExpectingOneNode = 'Xpath expression expecting a single node while got %d node : %s.';
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
uses XMLWrite;
|
uses
|
||||||
|
XMLWrite, xpath;
|
||||||
|
|
||||||
function GetNodeItemsCount(const ANode : TDOMNode): Integer;
|
function GetNodeItemsCount(const ANode : TDOMNode): Integer;
|
||||||
var
|
var
|
||||||
@ -109,6 +120,29 @@ begin
|
|||||||
Result := TDOMNodeSelectListImp.Create(ANode,ANodeName);
|
Result := TDOMNodeSelectListImp.Create(ANode,ANodeName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function SelectSingleNode(
|
||||||
|
const AXPathExpression : DOMString;
|
||||||
|
const AContextNode : TDOMNode;
|
||||||
|
const AErrorIfMore : Boolean
|
||||||
|
) : TDOMNode;
|
||||||
|
var
|
||||||
|
xp_res : TXPathVariable;
|
||||||
|
ns : TNodeSet;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
xp_res := EvaluateXPathExpression(AXPathExpression,AContextNode);
|
||||||
|
if ( xp_res <> nil ) then begin
|
||||||
|
if not xp_res.InheritsFrom(TXPathNodeSetVariable) then
|
||||||
|
raise Exception.CreateFmt(SERR_NoNodeXpathExpression,[AXPathExpression]);
|
||||||
|
ns := xp_res.AsNodeSet;
|
||||||
|
if ( ns <> nil ) and ( ns.Count > 0 ) then begin
|
||||||
|
if AErrorIfMore and ( ns.Count > 1 ) then
|
||||||
|
raise Exception.CreateFmt(SERR_XpathExpectingOneNode,[ns.Count,AXPathExpression]);
|
||||||
|
Result := TDOMNode(ns[0]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDOMNodeSelectListImp }
|
{ TDOMNodeSelectListImp }
|
||||||
|
|
||||||
type
|
type
|
||||||
|
Reference in New Issue
Block a user