Question

I am trying to create an iOS app which (besides a few other things) needs to load in the content of a Wordpress-Page

When I use the getPosts feature from Wordpress's XML-RPC feature, I get the following returned:

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <params>
    <param>
      <value>
      <array><data>
  <value><struct>
  <member><name>post_id</name><value><string>23</string></value></member>
  <member><name>post_title</name><value><string>&lt;!--:de--&gt;Post1&lt;!--:--&gt;&lt;!--:en--&gt;Post1&lt;!--:--&gt;</string></value></member>
  <member><name>post_date</name><value><dateTime.iso8601>20140211T14:26:39</dateTime.iso8601></value></member>
  <member><name>post_date_gmt</name><value><dateTime.iso8601>20140211T12:26:39</dateTime.iso8601></value></member>
  <member><name>post_modified</name><value><dateTime.iso8601>20140217T22:32:45</dateTime.iso8601></value></member>
  <member><name>post_modified_gmt</name><value><dateTime.iso8601>20140217T20:32:45</dateTime.iso8601></value></member>
  <member><name>post_status</name><value><string>publish</string></value></member>
  <member><name>post_type</name><value><string>post</string></value></member>
  <member><name>post_name</name><value><string>im-notfall</string></value></member>
  <member><name>post_author</name><value><string>1</string></value></member>
  <member><name>post_password</name><value><string></string></value></member>
  <member><name>post_excerpt</name><value><string></string></value></member>
  <member><name>post_content</name><value><string>&lt;!--:de--&gt;&lt;b&gt;Post1&lt;/b&gt;&lt;!--:--&gt;&lt;!--:en--&gt;&lt;b&gt;Post1&lt;/b&gt;&lt;!--:--&gt;</string></value></member>
  <member><name>post_parent</name><value><string>0</string></value></member>
  <member><name>post_mime_type</name><value><string></string></value></member>
  <member><name>link</name><value><string>http://example.com/ExampleProjekt/?p=23</string></value></member>
  <member><name>guid</name><value><string>http://example.com/ExampleProjekt/?p=23</string></value></member>
  <member><name>menu_order</name><value><int>5</int></value></member>
  <member><name>comment_status</name><value><string>closed</string></value></member>
  <member><name>ping_status</name><value><string>open</string></value></member>
  <member><name>sticky</name><value><boolean>0</boolean></value></member>
  <member><name>post_thumbnail</name><value><array><data>
</data></array></value></member>
  <member><name>post_format</name><value><string>standard</string></value></member>
  <member><name>terms</name><value><array><data>
  <value><struct>
  <member><name>term_id</name><value><string>1</string></value></member>
  <member><name>name</name><value><string>Allgemein</string></value></member>
  <member><name>slug</name><value><string>allgemein</string></value></member>
  <member><name>term_group</name><value><string>0</string></value></member>
  <member><name>term_taxonomy_id</name><value><string>1</string></value></member>
  <member><name>taxonomy</name><value><string>category</string></value></member>
  <member><name>description</name><value><string></string></value></member>
  <member><name>parent</name><value><string>0</string></value></member>
  <member><name>count</name><value><int>3</int></value></member>
</struct></value>
</data></array></value></member>
  <member><name>custom_fields</name><value><array><data>
</data></array></value></member>
</struct></value>
  <value><struct>
  <member><name>post_id</name><value><string>9</string></value></member>
  <member><name>post_title</name><value><string>&lt;!--:de--&gt;Post2&lt;!--:--&gt;&lt;!--:en--&gt;Post2&lt;!--:--&gt;</string></value></member>
  <member><name>post_date</name><value><dateTime.iso8601>20140206T13:16:56</dateTime.iso8601></value></member>
  <member><name>post_date_gmt</name><value><dateTime.iso8601>20140206T11:16:56</dateTime.iso8601></value></member>
  <member><name>post_modified</name><value><dateTime.iso8601>20140217T22:33:01</dateTime.iso8601></value></member>
  <member><name>post_modified_gmt</name><value><dateTime.iso8601>20140217T20:33:01</dateTime.iso8601></value></member>
  <member><name>post_status</name><value><string>publish</string></value></member>
  <member><name>post_type</name><value><string>post</string></value></member>
  <member><name>post_name</name><value><string>neuer-erster-beitrag</string></value></member>
  <member><name>post_author</name><value><string>1</string></value></member>
  <member><name>post_password</name><value><string></string></value></member>
  <member><name>post_excerpt</name><value><string></string></value></member>
  <member><name>post_content</name><value><string>&lt;!--:de--&gt;&lt;b&gt;Post2&lt;/b&gt;&lt;!--:--&gt;&lt;!--:en--&gt;&lt;b&gt;Post2&lt;/b&gt;&lt;!--:--&gt;</string></value></member>
  <member><name>post_parent</name><value><string>0</string></value></member>
  <member><name>post_mime_type</name><value><string></string></value></member>
  <member><name>link</name><value><string>http://example.com/ExampleProjekt/?p=9</string></value></member>
  <member><name>guid</name><value><string>http://example.com/ExampleProjekt/?p=9</string></value></member>
  <member><name>menu_order</name><value><int>3</int></value></member>
  <member><name>comment_status</name><value><string>closed</string></value></member>
  <member><name>ping_status</name><value><string>open</string></value></member>
  <member><name>sticky</name><value><boolean>0</boolean></value></member>
  <member><name>post_thumbnail</name><value><array><data>
</data></array></value></member>
  <member><name>post_format</name><value><string>standard</string></value></member>
  <member><name>terms</name><value><array><data>
  <value><struct>
  <member><name>term_id</name><value><string>1</string></value></member>
  <member><name>name</name><value><string>Allgemein</string></value></member>
  <member><name>slug</name><value><string>allgemein</string></value></member>
  <member><name>term_group</name><value><string>0</string></value></member>
  <member><name>term_taxonomy_id</name><value><string>1</string></value></member>
  <member><name>taxonomy</name><value><string>category</string></value></member>
  <member><name>description</name><value><string></string></value></member>
  <member><name>parent</name><value><string>0</string></value></member>
  <member><name>count</name><value><int>3</int></value></member>
</struct></value>
</data></array></value></member>
  <member><name>custom_fields</name><value><array><data>
</data></array></value></member>
</struct></value>
  <value><struct>
  <member><name>post_id</name><value><string>5</string></value></member>
  <member><name>post_title</name><value><string>&lt;!--:de--&gt;Post3&lt;!--:--&gt;&lt;!--:en--&gt;Post3&lt;!--:--&gt;</string></value></member>
  <member><name>post_date</name><value><dateTime.iso8601>20131217T17:32:09</dateTime.iso8601></value></member>
  <member><name>post_date_gmt</name><value><dateTime.iso8601>20131217T15:32:09</dateTime.iso8601></value></member>
  <member><name>post_modified</name><value><dateTime.iso8601>20140217T22:33:18</dateTime.iso8601></value></member>
  <member><name>post_modified_gmt</name><value><dateTime.iso8601>20140217T20:33:18</dateTime.iso8601></value></member>
  <member><name>post_status</name><value><string>publish</string></value></member>
  <member><name>post_type</name><value><string>post</string></value></member>
  <member><name>post_name</name><value><string>test-beitrag-2</string></value></member>
  <member><name>post_author</name><value><string>1</string></value></member>
  <member><name>post_password</name><value><string></string></value></member>
  <member><name>post_excerpt</name><value><string></string></value></member>
  <member><name>post_content</name><value><string>&lt;!--:de--&gt;&lt;b&gt;Post3&lt;/b&gt;&lt;!--:--&gt;&lt;!--:en--&gt;&lt;b&gt;Post3&lt;/b&gt;&lt;!--:--&gt;</string></value></member>
  <member><name>post_parent</name><value><string>0</string></value></member>
  <member><name>post_mime_type</name><value><string></string></value></member>
  <member><name>link</name><value><string>http://example.com/ExampleProjekt/?p=5</string></value></member>
  <member><name>guid</name><value><string>http://example.com/ExampleProjekt/?p=5</string></value></member>
  <member><name>menu_order</name><value><int>4</int></value></member>
  <member><name>comment_status</name><value><string>closed</string></value></member>
  <member><name>ping_status</name><value><string>open</string></value></member>
  <member><name>sticky</name><value><boolean>0</boolean></value></member>
  <member><name>post_thumbnail</name><value><array><data>
</data></array></value></member>
  <member><name>post_format</name><value><string>standard</string></value></member>
  <member><name>terms</name><value><array><data>
  <value><struct>
  <member><name>term_id</name><value><string>1</string></value></member>
  <member><name>name</name><value><string>Allgemein</string></value></member>
  <member><name>slug</name><value><string>allgemein</string></value></member>
  <member><name>term_group</name><value><string>0</string></value></member>
  <member><name>term_taxonomy_id</name><value><string>1</string></value></member>
  <member><name>taxonomy</name><value><string>category</string></value></member>
  <member><name>description</name><value><string></string></value></member>
  <member><name>parent</name><value><string>0</string></value></member>
  <member><name>count</name><value><int>3</int></value></member>
</struct></value>
</data></array></value></member>
  <member><name>custom_fields</name><value><array><data>
</data></array></value></member>
</struct></value>
</data></array>
      </value>
    </param>
  </params>
</methodResponse>

Specifically I would need the following fields:

  • post_id
  • post_title
  • post_motified
  • post_content
  • menu_order

I've tried a few options to achieve this. One was using Gdata, which has been recommended in another post, but the example is for a simpler xml, and I can't seem to get it to work for me.

    NSArray *tempPosts = [XMLdoc nodesForXPath:@"//methodResponse/params/param/value/array/data/value/struct/member" error:nil];

I also tried using the WPXMLRPC framework -> https://github.com/wordpress-mobile/wpxmlrpc

Using this code:

WPXMLRPCDecoder *decodedWPXML = [[WPXMLRPCDecoder alloc] initWithData:XMLcontent];
if ([decodedWPXML isFault]) {
    NSLog(@"XML-RPC error %ld: %@", (long)[decodedWPXML faultCode], [decodedWPXML faultString]);
} else {
    NSLog(@"XML-RPC response: %@", [decodedWPXML object]);
}

I manage to receive an object, which I can output via NSLog(@"%@", object); But I fail to further process any data I receive that way. I am (maybe obvious for some) very new to objective-c. I have also looked at the official wordpress for iOS app, but I wasn't able to make use of any code.

Any help would be appreciated, I don't mind using any different frameworks/technologies, etc. if they help getting to my solution.

Was it helpful?

Solution 2

GDataXMLDocument *XMLdoc = [[GDataXMLDocument alloc] initWithData:XMLcontent options:0 error:nil];
NSArray *XMLofPosts = [XMLdoc  nodesForXPath:@"//methodResponse/params/param/value/array/data/value/struct/member" error:nil];

gives me an array of all post members that i can iterate via
for(GDataXMLElement *postMember in XMLofPosts){ ... }

Thansk for the help. I've opened a new post for a more detailed question on the subject, since I found it's pretty much a different question, since it's on GDataXML more than getting the Wordpress XML GDataXML nodesForXPath on Node contains items of entire GDataXMLDocument

OTHER TIPS

I am happy with Wordpress JSON plugin, it's free. You can easily fine tune your requests to specific pages and post types, it's well documented. What you get back from your site is always a structure of dictionaries and arrays in JSON (better then XML ;). Good way to examine the JSON structure is a JSON viewer.

Some sample code to get started.

- (void)loadNewsForPage:(NSUInteger)page
{

    NSURLSession *session = [NSURLSession sharedSession];
    [[session dataTaskWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.mywordpresssite.com/api/get_posts/?page=%lu", (unsigned long)page]]
            completionHandler:^(NSData *data,
                                NSURLResponse *response,
                                NSError *error) {

                // handle response
                NSError *jsonError = nil;
                id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];

                if (!jsonError) {
                    if ([jsonObject isKindOfClass:[NSDictionary class]]) {

                        // fill datastore
                        [self newsIntoDataStore:(NSDictionary *)jsonObject forPage:page];
                    }
                    else {
                        NSLog(@"returned jsonObject is not a dictionary!");
                    }
                } else {
                    NSLog(@"jsonError, news: %@", jsonError);
                }

            }] resume];
}

- (void)newsIntoDataStore:(NSDictionary *)news forPage:(NSUInteger)page
{
    if ([[news objectForKey:@"status"] isEqualToString:@"ok"]) {

        self.newsPages = [[news objectForKey:@"pages"] integerValue];
        NSArray *posts = [news objectForKey:@"posts"];

        if (posts.count > 0) {
            // store individual posts

            for (NSDictionary *post in posts) {

                // determine post slug
                NSArray *categoriesArray = [post objectForKey:@"categories"];
                NSString *postSlug = nil;
                NSString *desiredSlug = @"news";

                if (categoriesArray.count > 0) {
                    for (NSDictionary *category in categoriesArray) {
                        if ([[category objectForKey:@"slug"] isEqualToString:desiredSlug]) {
                            postSlug = desiredSlug;
                        }
                    }
                }

                    NSString *title = [post objectForKey:@"title"];

                    NSDate *dateFromAPI = [self.dateFormatterFromAPI dateFromString:[post objectForKey:@"date"]];
                    NSString *date = [self.dateFormatterForCell stringFromDate:dateFromAPI];

                    NSString *imageURLStringOrg = [[[post objectForKey:@"thumbnail_images"] objectForKey:@"full"] objectForKey:@"url"];
                    NSString *imageURLStringConverted = [imageURLStringOrg stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

                    NSAttributedString *attributedContentString = [[NSAttributedString alloc] initWithData:[[post objectForKey:@"excerpt"] dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];
                    NSString *content = [attributedContentString string];

                    NSString *url = [post objectForKey:@"url"];

                    if (title && date && imageURLStringConverted && content && url) {

                        NSDictionary *postDictionary = @{@"title" : title, @"date" : date, @"imageURL" : imageURLStringConverted, @"content" : content, @"url" : url};

                        [self.newsArray addObject:postDictionary];

                    } else {
                        NSLog(@"some post item empty, skipping this post: %lu", (unsigned long)[posts indexOfObject:post]);
                    }
                }

            }

            dispatch_async(dispatch_get_main_queue(), ^{

                if (self.pageLoaded < self.newsPages) {
                    [self loadNewsForPage:self.pageLoaded + 1];
                } else {

                    [self.delegate newsFetchingCompleted];
                }
            });

        } else {
            NSLog(@"no objects in the array");
        }
    } else {
        NSLog(@"returned status NOT OK");
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top