如何阻止Indy将XML中的字符转换为代码

时间:2015-02-13 00:46:57

标签: xml delphi indy

我试图使用第三方网络API,它希望请求正文是一个XML文档,但服务器正在接收的XML因为格式不正确而被拒绝,因为Indy已经取代了ANSI代码的一堆字符。

我正在使用XE2和Indy 10.5.8.0。

我已经注意到Indy正在将CRLF转换为&,因此将所有这些转换为源XML。现在,当我传递给.Post的TStringList包含:

<?xml version="1.0" encoding="utf-8"?><AdCourierAPI>

服务器正在看:

%3C%3Fxml+version=%221.0%22+encoding%3D%22utf-8%22%3F%3E%3CAdCourierAPI%3E

如何阻止Indy这样做?我需要更改编码吗?

以下是其中一种API方法的代码:

function TBroadBeanAPI.ListChannels(const AUserName, APassword: String): String;
var
  HTTP: TIdHTTP;
  SSL: TIdSSLIOHandlerSocketOpenSSL;
  ASource: TStringList;
  XMLRequest: String;
begin
  HTTP := TIdHTTP.Create(nil);
  SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
  ASource := TStringList.Create;

  Result := '';

  try
    HTTP.IOHandler := SSL;
    HTTP.Request.ContentType := 'text/xml';
    HTTP.Request.Charset := 'utf-8';

    XMLRequest := '<?xml version="1.0" encoding="utf-8"?>'+
                  '<AdCourierAPI>'+
                  '    <Method>ListChannels</Method>'+
                  '    <APIKey>'+APIKEY+'</APIKey>'+
                  '    <Account>'+
                  '        <UserName>'+AUserName+'</UserName>'+
                  '        <Password>'+APassword+'</Password>'+
                  '    </Account>'+
                  '</AdCourierAPI>';

    ASource.Text := XMLRequest;
    Result := HTTP.Post(APIURL, ASource);
  finally
    SSL.Free;
    HTTP.Free;
    ASource.Free;
  end;
end;

2 个答案:

答案 0 :(得分:3)

您使用的是Post()的错误版本。

您正在使用Post()的重载版本接受TStrings作为输入。该版本旨在以application/x-www-form-urlencoded格式发布HTML网络表单,其中TStrings应包含根据W3C提交网络表单规则进行编码的name=value字符串。这就是为什么你看到你的XML被编码的原因。

您需要使用接受Post()作为输入的TStream的其他重载版本。 TStream数据将按原样传输。

试试这个:

function TBroadBeanAPI.ListChannels(const AUserName, APassword: String): String;
var
  HTTP: TIdHTTP;
  SSL: TIdSSLIOHandlerSocketOpenSSL;
  ASource: TStringStream;
  XMLRequest: String;
begin
  Result := '';
  HTTP := TIdHTTP.Create(nil);
  try
    SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
    HTTP.IOHandler := SSL;
    HTTP.Request.ContentType := 'text/xml';
    HTTP.Request.Charset := 'utf-8';

    XMLRequest := '<?xml version="1.0" encoding="utf-8"?>'+
                  '<AdCourierAPI>'+
                  '    <Method>ListChannels</Method>'+
                  '    <APIKey>'+APIKEY+'</APIKey>'+
                  '    <Account>'+
                  '        <UserName>'+AUserName+'</UserName>'+
                  '        <Password>'+APassword+'</Password>'+
                  '    </Account>'+
                  '</AdCourierAPI>';

    ASource := TStringStream.Create(XMLRequest, TEncoding.UTF8);
    try
      Result := HTTP.Post(APIURL, ASource);
    finally
      ASource.Free;
    end;
  finally
    HTTP.Free;
  end;
end;

另外,在构建XML时,您没有对APIKEYAUserNameAPassword进行编码。如果它们包含保留字符,则必须按照XML格式规则对它们进行转义/编码。所以要小心。您应该使用真正的XML引擎来构建XML,而不是使用字符串连接。否则,至少要添加符合XML的编码函数,以便连接格式正确的字符串。

答案 1 :(得分:0)

答案是关闭TIdHTTP对象的HTTPOptions中的[hoForceEncodeParams]。这可以这样做:

HTTP.HTTPOptions := [];