Charlie
private void button1_Click(object sender, System.EventArgs e)
{
a2zService.a2zAuthenticationHeader a2zHeader = new
a2zService.a2zAuthenticationHeader();
a2zService.a2zExhibitorList a2zServ = new a2zService.a2zExhibitorList();
a2zHeader.Key = "[omitted]";
a2zServ.a2zAuthenticationHeaderValue = a2zHeader;
XmlDocument xmlRequest = new XmlDocument();
xmlRequest.LoadXml("<as></as>");
XmlNode root = xmlRequest.FirstChild;
XmlNodeReader response = new
XmlNodeReader(a2zServ.getExhibitorList(root));
}
"Charles Vinal" <cvi...@euclidtechnology.com> wrote in message
news:46084161$1...@newsgroups.borland.com...
I'm not sure whether that's the case, but if in .NET (C# or other) you
create a webservice that exposes a System.Xml.XmlNode (or
System.Xml.XmlDocument), the service will typically expose the complex type
as "mixed=true" which Delphi's importer maps to 'WideString'. Unfortunately,
this will cause the data to be encoded in the XML packet. The service at the
other end will probably not handle this.
For example, if you send the following:
<client xmlns="urn:cust">
<nom>Racine</nom>
<titre genre="tragedie">Andromaque</titre>
</client>
Instead of the above, the XML packet will really contain:
<client xmlns="urn:cust"><nom>Racine</nom><titre
genre="tragedie">Andromaque</titre></client>
It's something that I've been working on remedying recently (it just fell of
the list for D2007). The new importer maps mixed complex types to a new
type, TXMLData:
{ For cases where one needs access to the raw XMLNode data in a SOAP
envelope }
TXMLData = class(TRemotable)
private
FXMLDocument: IXMLDocument;
FXMLNode: IXMLNode;
public
constructor Create; override;
destructor Destroy; override;
function ObjectToSOAP(RootNode, ParentNode: IXMLNode;
const ObjConverter: IObjConverter;
const Name, URI: InvString; ObjConvOpts:
TObjectConvertOptions;
out RefID: InvString): IXMLNode; override;
procedure SOAPToObject(const RootNode, Node: IXMLNode; const
ObjConverter: IObjConverter); override;
procedure LoadFomXML(const XML: string); overload;
procedure LoadFromXML(const XML: WideString); overload;
property XMLNode: IXMLNode read FXMLNode;
end;
We have not fully tested the above but it's checked in and I have had
unit-tests that illustrate the usage running for a few days. If you're
interested, I'd be happy to make TXMLData and the new importer available.
There are two other solutions to this:
#1. Keep the WideString and decode the data in the AfterExecute event.
#2 Have a TRemotable-derived class (like TXMLData) that you can created with
the string to send and that sends that string in ObjectToSOAP. TXMLData is
bulky because it has to clone any data into its own XML document. That's
because its lifetime can't be tied to that of a request/response. However,
since you're just sending data, you need a class with just a string member
that copies the string to the node.
Let me know if the above is accurate and if I can help with any approach
you'd like to try.
Cheers,
Bruneau.
Thanks for your reply. I have tried to implement using a tRemotable with a
property of ixmlnode and also a tremotable with wide string property. When I
use remotable.widestring method and preview the soap packet, it looks
perfect (I replace the > etc with the appropriate string before sending).
However, I still get an error from the server stating that there is no
object instance (hence why I think it has to be passed an actual instance of
a system.xml.xmlnode object). It seems that it is expecting to directly
write to a system.xml.xmlnode structure that is being passed (which I can't
seem to mimic). I would really appreciate any help you can provide. The wsdl
is located at:
http://dev3.a2zinc.net/ww5root/ezscte/dataservices/public/ExhibitorProvider.asmx?wsdl. I
can send you the code that I have as well.
I would also be interested in getting the code for the txmldata - it seems
almost all of the .net services we have to access us the xmldocument or
xmlnode (we don't have any control over the types - I would prefer a simple
widestring - but the vendor does it this way).
Thanks,
Charlie
"Jean-Marie Babet" <bba...@borland.com> wrote in message
news:46084abb$1...@newsgroups.borland.com...
Below is a unit, XSXMLData.pas that contains TXMLData extracted. It's a
TRemotable-based type that holds on to an XMLDocument. It writes and reads
the content of the document to and from the SOAP Envelope. It's not an ideal
solution as it duplicates data and has to clone nodes into and out of the
document of the envelope. However, that was required for it to outlive the
document that contained the XML data sent.
To send XML data, you'll use something along the lines of:
DataIn := TXMLData.Create;
try
DataIn.LoadFromXML(XMLStr);
AWebService.methodThatTakesXML(DataIn);
When receiving data, you can access the XML data via the XMLNode property:
DataOut := AWebService.methodThatReturnsXML(....);
try
ShowMessage(DataIn.XMLNode.XML);
Replace the 'WideString' that represent XML data with TXMLData in the file
generated by the importer. For example:
Request = TXMLData;
Response = TXMLData;
Please let me know if you need more information or run into difficulties
with the changes.
Cheers,
Bruneau.
====== [XSXMLData.pas ] ======
unit XSXMLData;
interface
uses SysUtils, InvokeRegistry, Classes, XmlIntf;
type
{ For cases where one needs access to the raw
XMLNode data in a SOAP envelope }
TXMLData = class(TRemotable)
private
FXMLDocument: IXMLDocument;
FXMLNode: IXMLNode;
public
constructor Create; override;
destructor Destroy; override;
function ObjectToSOAP(RootNode, ParentNode: IXMLNode;
const ObjConverter: IObjConverter;
const Name, URI: InvString;
ObjConvOpts: TObjectConvertOptions;
out RefID: InvString): IXMLNode; override;
procedure SOAPToObject(const RootNode, Node: IXMLNode;
const ObjConverter: IObjConverter); override;
procedure LoadFomXML(const XML: string); overload;
procedure LoadFromXML(const XML: WideString); overload;
property XMLNode: IXMLNode read FXMLNode;
end;
implementation
uses SOAPConst,
{$IFDEF MSWINDOWS}Windows{$ENDIF}
{$IFDEF LINUX}Libc{$ENDIF},
DateUtils, XMLDoc;
{ TXMLData }
constructor TXMLData.Create;
begin
inherited;
FXMLDocument := NewXMLDocument;
end;
destructor TXMLData.Destroy;
begin
FXMLNode := nil;
FXMLDocument := nil;
inherited;
end;
procedure TXMLData.LoadFomXML(const XML: string);
begin
FXMLDocument.LoadFromXML(XML);
if FXMLDocument.Node.ChildNodes.Count > 0 then
FXMLNode := FXMLDocument.Node.ChildNodes[0];
end;
procedure TXMLData.LoadFromXML(const XML: WideString);
begin
FXMLDocument.LoadFromXML(XML);
if FXMLDocument.Node.ChildNodes.Count > 0 then
FXMLNode := FXMLDocument.Node.ChildNodes[0];
end;
{ Utility routine lifted from XMLDoc.pas }
function CloneNodeToDoc(const SourceNode: IXMLNode;
const TargetDoc: IXMLDocument;
Deep: Boolean = True): IXMLNode;
var
I: Integer;
begin
with SourceNode do
case nodeType of
ntElement:
begin
Result := TargetDoc.CreateElement(NodeName, NamespaceURI);
for I := 0 to AttributeNodes.Count - 1 do
Result.AttributeNodes.Add(CloneNodeToDoc(AttributeNodes[I],
TargetDoc, False));
if Deep then
for I := 0 to ChildNodes.Count - 1 do
Result.ChildNodes.Add(CloneNodeToDoc(ChildNodes[I],
TargetDoc, Deep));
end;
ntAttribute:
begin
Result := TargetDoc.CreateNode(NodeName,
ntAttribute,
NamespaceURI);
Result.NodeValue := NodeValue;
end;
ntText, ntCData, ntComment:
Result := TargetDoc.CreateNode(NodeValue, NodeType);
ntEntityRef:
Result := TargetDoc.createNode(nodeName, NodeType);
ntProcessingInstr:
Result := TargetDoc.CreateNode(NodeName,
ntProcessingInstr,
NodeValue);
ntDocFragment:
begin
Result := TargetDoc.CreateNode('', ntDocFragment);
if Deep then
for I := 0 to ChildNodes.Count - 1 do
Result.ChildNodes.Add(CloneNodeToDoc(ChildNodes[I],
TargetDoc,
Deep));
end;
else
{ntReserved, ntEntity, ntDocument, ntDocType:}
{ XMLDocError(SInvalidNodeType); }
end;
end;
function TXMLData.ObjectToSOAP(RootNode, ParentNode: IXMLNode;
const ObjConverter: IObjConverter; const Name, URI: InvString;
ObjConvOpts: TObjectConvertOptions; out RefID: InvString): IXMLNode;
var
RawNode: IXMLNode;
begin
Result := inherited ObjectToSOAP(RootNode,
ParentNode,
ObjConverter,
Name, URI,
ObjConvOpts+[ocoDontSerializeProps],
RefId);
if (Result <> nil) and (FXMLNode <> nil) then
begin
RawNode := CloneNodeToDoc(FXMLNode,
ParentNode.OwnerDocument,
True);
if RawNode <> nil then
Result.ChildNodes.Add(RawNode);
end;
end;
procedure TXMLData.SOAPToObject(const RootNode, Node: IXMLNode;
const ObjConverter: IObjConverter);
begin
if Node.ChildNodes.Count = 1 then
FXMLNode := CloneNodeToDoc(Node.ChildNodes[0],
FXMLDocument, True)
end;
initialization
RemClassRegistry.RegisterXSClass(TXMLData,
XMLSchemaNameSpace,
'schema', '',
False,
ocNoMultiRef);
end.
"Charles Vinal" <cvi...@euclidtechnology.com> wrote in message
news:460922ce$1...@newsgroups.borland.com...
Thank you 1 million times over.
Charlie
"Jean-Marie Babet" <bba...@borland.com> wrote in message
news:46095885$1...@newsgroups.borland.com...
Cheers,
Bruneau.
I am surprised that this was not a top priority to get included into D2007 -
it seems a lot of the web services out there expect an actual XML document
as opposed to a widestring that contains XML data. This is probably due to
the ability to directly bind an xmldocument or xmlnode to .net and /or ajax
controls. If you have updates to the xmldata.pas file, please let me know!
Regards,
Charlie
"Jean-Marie Babet" <bba...@borland.com> wrote in message
news:46097539$1...@newsgroups.borland.com...
I'm running into an increasing number of WebServices that do pass raw XML
data but for D2007 (well, back when we were actually aiming at Highlander)
we made a list of the most requested Services Delphi users reported
[MapPoint/Amazon/eBay/etc]... then I built some C#/Axis services that
focused/illustrated the key problems we had.
TXMLData was on the list for two things: (a) complex types with mixed="true"
[that the raw XML data case] and (b) xsd:any support. ebay does use xsd:any
but my limited tests never found a case where 'any' content was sent. So at
that point TXMLData fell off the list. I would probably say that full
support for xsi:nil="true" node is the one item that would have come first
if I had the time.
Fortunately, these things are being addressed [although I think I'm not
supposed to say that:( - so I'll stop before I get myself in trouble].
Cheers,
Bruneau.
"Charles Vinal" <cvi...@euclidtechnology.com> wrote in message
news:460a799f$1...@newsgroups.borland.com...