简体   繁体   中英

Send and receive XML via POST on Delphi

I've seen some examples here and there on how to POST data to a server using Indy, but my question is how can I view the answer the server provides?

Here is what I have, from the user Bruce McGee , and modified myself a bit:

function ExecuteAPI: string;
var
  lHTTP: TIdHTTP;
  lParamList: TStringList;
begin
  lParamList := TStringList.Create;
  lParamList.Add('<input type=text name=StoreName value="Hálitopuro Produtos">');
  lParamList.Add('<input type=text name=StoreID value="123456"> ');
  lParamList.Add('<input type=text name=Username value="Admin"> ');
  lParamList.Add('<input type=password name=Password value="Password123">');
  lParamList.Add('<input type=text name=method value="ReportView">');
  lParamList.Add('<input type=text name=ObjectID value="425">');
  lParamList.Add('<input type=text name=Par1 value="Category name">');
  lParamList.Add('<input type=text name=Par2 value="Ref/Name/Descr"> ');
  lParamList.Add('<input type=text name=Par3 value="false"> ');
  lParamList.Add('<input type=text name=Par4 value="false"> ');

  lHTTP := TIdHTTP.Create(nil);

  try
    Result := lHTTP.Post('https://www.rumo.com.br/sistema/adm/APILogon.asp', lParamList);
  finally
    lHTTP.Free;
    lParamList.Free;
  end;
end;

The API states that the server also returns a XML, regardless on what the request or result is, but how can I view it? For example, by filling a TMemo?

I've seen some examples here and there on how to POST data to a server using Indy

You are not populating the TStringList correctly. DO NOT store the actual HTML tags in it, just their name=value pairs by themselves, eg:

lParamList.Add('StoreName=Hálitopuro Produtos');
lParamList.Add('StoreID=123456');
lParamList.Add('Username=Admin');
lParamList.Add('Password=Password123');
lParamList.Add('method=ReportView');
lParamList.Add('ObjectID=425');
lParamList.Add('Par1=Category name');
lParamList.Add('Par2=Ref/Name/Descr');
lParamList.Add('Par3=false');
lParamList.Add('Par4=false');

how can I view the answer the server provides?

TIdHTTP.Post() returns the server's response to you. There are two overloaded versions of Post() for this purpose - one that returns the response as a String , and one that fills a TStream with the raw response bytes. You are calling the first one, so just use the String however you want, eg:

var
  XML: string;
begin
  XML := ExecuteAPI;
  // use XML as needed, for example:
  // Memo1.Text := XML;
end;

However, that being said...

The API states that the server also returns a XML, regardless on what the request or result is

XML is not textual data, it is binary data with textual elements in it. Treating the XML as binary is important for proper charset handling for non-ASCII characters. You should use the TStream version of Post() and then load the raw data to an actual XML parser for further processing (as I'm sure you will eventually want to actually do something based on the content of the response, not just look at it), eg:

procedure ExecuteAPI(Response: TStream);
var
  lHTTP: TIdHTTP;
  lParamList: TStringList;
begin
  lParamList := TStringList.Create;
  try
    lParamList.Add('StoreName=Hálitopuro Produtos');
    lParamList.Add('StoreID=123456');
    lParamList.Add('Username=...');
    lParamList.Add('Password=...');
    lParamList.Add('method=ReportView');
    lParamList.Add('ObjectID=425');
    lParamList.Add('Par1=Category name');
    lParamList.Add('Par2=Ref/Name/Descr');
    lParamList.Add('Par3=false');
    lParamList.Add('Par4=false');

    lHTTP := TIdHTTP.Create(nil);
    try
      lHTTP.Post('https://www.rumo.com.br/sistema/adm/APILogon.asp', lParamList, Response);
    finally
      lHTTP.Free;
    end;
  finally
    lParamList.Free;
  end;
end;

var
  XML: TMemoryStream;
  Doc: IXMLDocument;
begin
  XML := TMemoryStream.Create;
  try
    ExecuteAPI(XML);
    XML.Position := 0;
    {Memo1.Lines.LoadFromStream(XML);
    XML.Position := 0;}
    Doc := TXMLDocument.Create(nil);
    Doc.LoadFromStream(XML);
  finally
    XML.Free;
  end;
  // use Doc as needed...
end;

If you let TIdHTTP.Post() return the XML as a String , TIdHTTP will try to figure out the XML's charset by analyzing the HTTP Content-Type header, and potentially also the XML's own prolog declaration, and then decode the raw data to Unicode based on that charset, and then re-encode the Unicode data to a String (which will be either Ansi or Unicode depending on your version of Delphi). That first step is error-prone and could cause data loss, for instance if the HTTP server is misconfigured. It is better to have TIdHTTP.Post() return the raw XML data and let an XML parser handle the charset decoding. That is part of its job, afterall.

How can I view it, for example, by filling a TMemo?

To view text in a memo control, assign to the Text property:

Memo1.Text := ExecuteAPI;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM