Re: How to remove & (ampersand) sign from XML posting

Giganews Newsgroups
Subject: Re: How to remove & (ampersand) sign from XML posting
Posted by:  Remy Lebeau (Indy Team) (no.spam@no.spam.com)
Date: Thu, 17 May 2007

"Thien Tang" <t…@tctdigital.com> wrote in message
news:69FF8D197426E340t…@tctdigital.com...

> When I submitted an XML section (below) the server at the
> vendor site saw the & in place of the carriage return/line feed
> characters and returned an 'Cannot parse XML' error.

The original documentation did say as much:

    "Note: The ampersand symbol ("&") is not a valid character and
will cause an error if inputted within any element of the XML
request."

The overloaded version of Post() that accepts a TStrings parameter
expects the items to be 'name=value' pairs.  The rules for
'application/x-www-form-urlencoded' dictate that 'name=value' pairs
must be separated by the '&' character.  When retreiving the Text of a
TStrings, the items are separated by line breaks, so TIdHTTP changes
the line breaks into '&' instead.

'application/x-www-form-urlencoded' was designed for HTML form
submissions, thus it relies on 'name=value' pairs to be submitted.
The XMLMessenger protocol should not be relying on
'application/x-www-form-urlencoded' to begin with, as it is not
well-suited for XML, especially since the XML is not coming from an
HTML form to begin with.  In fact, I see nothing in the XMLMessenger
spec about how HTTP is to be used at all, though all of the examples
use 'application/x-www-form-urlencoded', which leads me to think that
the examples themselves are wrong and not the spec.  The spec only
describes the XML itself and nothing else.

The best way would have been to just accept the raw XML data as a
binary stream with a ContentType of 'text/xml'.  Then the data does
not have to be encoded at all, and can be processed as-is.

If you must continue using 'application/x-www-form-urlencoded' (which
you need to confirm with your vendor, based on how it is actually
reading the data from you), then you have no choice but to encode the
XML data yourself manually so that you can encode them as '%0D%0A', as
per the 'application/x-www-form-urlencoded'' rules.  Encode the data
into a TStream, such as a TMemoryStream or TStringStream, and then use
Post(Stream) instead of Post(TStrings) so that the TStream content is
transmitted as-is without any extra alterations by TIdHTTP.  For
example:

    function EncodeXML(AStrings: TStrings): String;
    const
        AlphaNumeric = ['a'..'z', 'A'..'Z', '0'..'9'] ;
    var
        I, J: Integer;
        S: String;
    begin
        Result := '';
        for I := 0 to AStrings.Count-1 do
        begin
            if I <> 0 then Result := Result + '%0D%0A';
            S := AStrings[I];
            for J := 1 to Length(S) do
            begin
                if S[J] in AlphaNumeric then
                    Result := Result + S[J]
                else if S[J]  = ' ' then
                    Result := Result + '+'
                else
                    Result := Result + '%' + IntToHex(Ord(S[J]), 2);
            end;
        end;
    end;

    procedure TmainForm.Button1Click(Sender: TObject);
    var
        XML: TStringList;
        Strm: TStringStream;
        Response: String;
    begin
        XML := TStringList.Create;
        try
            XML.LoadFromFile('test2.xml');
            Strm := TStringStream.Create(EncodeXML(XML));
        finally
            XML.Free;
        end;
        try
            IdHTTP1.Request.ContentType :=
'application/x-www-form-urlencoded';
            Response :=
IdHTTP1.Post('https://somewebsitesome:7777/Messenger/XMLMessenger',
Strm);
        finally
            Strm.Free;
        end;
    end;

Gambit

Replies

In response to

How to remove & (ampersand) sign from XML posting posted by Thien Tang on Thu, 17 May 2007