views:

1746

answers:

3

Hello, I have an API which sends an XML Request to a server:

<?xml version="1.0" encoding="UTF-8"?>
<request type="handle" action="update">
<userdata>
<username>YourUsername</username>
<password>YourPassword</password>
</userdata>
<handledata type="PERSON" id="HandleId">
<name>Mustermann</name>
<firstname>Max</firstname>
<organization>Firma KG</organization>
<street>Musterstrasse 1</street>
<postalcode>11111</postalcode>
<city>Musterstadt</city>
<state>Niedersachsen</state>
<country>DE</country>
<email>[email protected]</email>
<phone>+43-111-111111</phone>
<fax>+43-111-111111</fax>
<remarks>remarks</remarks>
</handledata>
</request>

How do I do this on the iPhone?

+6  A: 

You can use libxml2. I suspect it is the fastest approach. Add its framework to your project (see the "setting up your project" section of this document).

In the header of your XML writer, add the following imports:

#import <libxml/encoding.h>
#import <libxml/xmlwriter.h>

In the implementation, write a method to generate your XML. Presumably you'll be sending your request's bytes via an NSData* object, so you might write something like this:

- (NSData *) xmlDataFromRequest 
{
    xmlTextWriterPtr _writer;
    xmlBufferPtr _buf;
    xmlChar *_tmp;
    const char *_UTF8Encoding = "UTF-8";

    _buf = xmlBufferCreate();
    _writer = xmlNewTextWriterMemory(_buf, 0);

    // <?xml version="1.0" encoding="UTF-8"?>
    xmlTextWriterStartDocument(_writer, "1.0", _UTF8Encoding, NULL);

    // <request type="handle" action="update">
    xmlTextWriterStartElement(_writer, BAD_CAST "request");
    xmlTextWriterWriteAttribute(_writer, BAD_CAST "type", BAD_CAST "handle");
    xmlTextWriterWriteAttribute(_writer, BAD_CAST "action", BAD_CAST "update");
    xmlTextWriterEndElement(_writer);

    // <userdata>...</userdata>
    xmlTextWriterStartElement(_writer, BAD_CAST "userdata");
    xmlTextWriterStartElement(_writer, BAD_CAST "username");
    _tmp = [self xmlCharPtrForInput:[[NSString stringWithFormat:@"YourUsername"] cStringUsingEncoding:NSUTF8StringEncoding] withEncoding:_UTF8Encoding];
    xmlTextWriterWriteString(_writer, _tmp);
    xmlTextWriterEndElement(_writer); // closing <username>
    xmlTextWriterStartElement(_writer, BAD_CAST "password");
    _tmp = [self xmlCharPtrForInput:[[NSString stringWithFormat:@"YourPassword"] cStringUsingEncoding:NSUTF8StringEncoding] withEncoding:_UTF8Encoding];
    xmlTextWriterWriteString(_writer, _tmp);
    xmlTextWriterEndElement(_writer); // closing <password> 
    xmlTextWriterEndElement(_writer); // closing <userdata>

    // etc.

    xmlTextWriterEndDocument(_writer);
    xmlFreeTextWriter(_writer);

    // turn libxml2 buffer into NSData* object

    NSData *_xmlData = [NSData dataWithBytes:(_buf->content) length:(_buf->use)];
    xmlBufferFree(_buf);

    return _xmlData;
}

I have a helper method here that I use to convert const char * into xmlChar *:

- (xmlChar *) xmlCharPtrForInput:(const char *)_input withEncoding:(const char *)_encoding 
{
    xmlChar *_output;
    int _ret;
    int _size;
    int _outputSize;
    int _temp;
    xmlCharEncodingHandlerPtr _handler;

    if (_input == 0)
        return 0;

    _handler = xmlFindCharEncodingHandler(_encoding);

    if (!_handler) {
        NSLog(@"convertInput: no encoding handler found for '%s'\n", (_encoding ? _encoding : ""));
        return 0;
    }

    _size = (int) strlen(_input) + 1;
    _outputSize = _size * 2 - 1;
    _output = (unsigned char *) xmlMalloc((size_t) _outputSize);

    if (_output != 0) {
        _temp = _size - 1;
        _ret = _handler->input(_output, &_outputSize, (const xmlChar *) _input, &_temp);
        if ((_ret < 0) || (_temp - _size + 1)) {
            if (_ret < 0) {
                NSLog(@"convertInput: conversion wasn't successful.\n");
            } else {
                NSLog(@"convertInput: conversion wasn't successful. Converted: %i octets.\n", _temp);
            }   
            xmlFree(_output);
            _output = 0;
        } else {
            _output = (unsigned char *) xmlRealloc(_output, _outputSize + 1);
            _output[_outputSize] = 0;  /*null terminating out */
        }
    } else {
        NSLog(@"convertInput: no memory\n");
    }

    return _output;
}
Alex Reynolds
Very very helpful answer Alex.
Luther Baker
A: 

Wow, cool :) And to send the NSData, i urse a normal NSURLCONNECTION and NSHTTPREQUEST?

Ploetzeneder
A: 

I would use string formatting for such a simple structure.

Ovidiu S.