API - Sending and Receiving XML

I am new to rails and looking someone to point me in the right
direction in how to accomplish the following:-

I need to communicate with an external api by either passing an XML
document directly
into the cgi (https://api.domain.com/v1/method.cgi) and set the
content-type to "text/xml", or pass it as a parameter and set the
content-type to "text/plain"

I supposedly get an XML response back instead of the HTML response, so
no need to download the HTML response, store it, then render a local
copy for the user; nor will i need to stick the XML document within a
parameter of a locally generated HTML form to submit it via the
browser to avoid downloading the HTML.

Each API method has example xml code for (Sending, The Response, DTD,
Schema)

What is the best tools/techniques to accomplish this !??

One of their simpler methods is as follows :-

**SEND**

<?xml version="1.0" encoding="utf-8" ?>
<SoftwareAPI>
<Method>ListUsers</Method>
<APIKey>123</APIKey>
<Account>
    <UserName>admin</UserName>
    <Password>Password</Password>
</Account>
</SoftwareAPI>

**RESPONSE**

<?xml version="1.0" encoding="utf-8" ?>
<SoftwareAPIResponse>
    <TimeNow>2012-01-23T16:44:00Z</TimeNow>
    <ResponseId>01-23-1232729040-23456</ResponseId>
    <ListUsersResponse>
        <User>
            <Team>team</Team>
            <Office>office</Office>
            <UserName>Joe.Bloggs</UserName>
            <Password>Password123</Password>
            <FullName>Joe Bloggs</FullName>
            <Language>Auto-Detect</Language>
            <Telephone>+44 207 123 456 789</Telephone>
            <ResponseEmail>joebloggs@domain.co.uk</ResponseEmail>
        </User>
    </ListUsersResponse>
</SoftwareAPIResponse>

This API method needs no interaction from the user or view, should the
coding be done from the controller or should I create a model for all
the api methods ?

How do I perform a post to the cgi url with the specified XML above
and process the response XML and display in a view ?

What are the best practices for accomplishing this ?

Many Thanks in Advance

Jonny

A few hints …

  1. Add a XML file to override the JSON default template wit scaffolds.

Something like this:

https://gist.github.com/1583881

(this is just the default JSON format, with all json find/replace with xml).

  1. Try out

$ rails generate resource User first_name:string last_name:string

to see an example in a scaffold.

Once that is there, you can start playing with localhost:3000/users.xml

to see the effect. By targeting either:

  • the .xml extension in a GUI browser
  • the Accept and Content-Type ‘application/xml’ in curl (see below)

Check the /log/development.log to verify that XML format is used (and not HTML)

  1. You may override to_xml to e.g. have whitelists on what you expose over the API
    (don’t forget to call super in your overridden method). to_xml will be default be
    used and will render a default XML template.

You can override that with a custom xml builder, like:

app/views/users/index.html.haml
app/views/users/index.xml.builder
app/views/users/show.xml.builder # here you would create your special builder for

                                             # <SoftwareAPIResponse> if needed

But with clever includes and whitelists of associated resources, you may be
able to use the default XML template.

  1. When you have associated models (e.g. User has_one :address), you will face
    2 difficulties:
  • address.singularize is wrong and this causes a bug in the to_xml serializer
    (… with 1 ‘s’). I will try to commit a patch
    for that (in the meanwhile, use custom inflections where needed).

  • for create/update accepts_nested_attributes_for will not work straightforwardly
    (since it only adds e.g. user.address_attributes= ; but for XML you would need
    user.address= to accept a hash and not a <Address …> object. I will try to

publish a gem for that.

  • for the XML format (instead of HTML), the client needs to set BOTH the
    Accepts and the Content-Type headers. You could use curl to test. Like this:

    request << “–header ‘Accept:application/xml’”

    request << “–header ‘Content-Type:application/xml; charset=utf-8’”

HTH.

Call me if you have more questions on this.

Peter