Wednesday, February 2, 2011

Simplest Example: Hierarchical Plist in iOS and Rails

These examples are based directly on this article, Reading a Plist into an NSArray.

The Plist


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Region 1</key>
<array>
<string>John Bob</string>
<string>Billy Ray</string>
</array>
<key>Region 2</key>
<array>
<string>John Bob's Bro</string>
<string>Frankie Sanders</string>
</array>
</dict>
</plist>


and the code


NSString *path = [[NSBundle mainBundle] pathForResource:@"regions" ofType:@"plist"];
NSDictionary *regions = [[[NSDictionary alloc] initWithContentsOfFile:path] autorelease];
for (NSString *region in regions) {
NSArray *array = [regions objectForKey:region];
for (NSString *representative in array) {
NSLog(@"rep=%@, region=%@", representative, region);
}
}


If you're dealing with a plist, the file is read in one giant gulp, so if you have memory problems, you'll have to use CoreData, and I don't think XML can be the backing store.

So what's the simplest code to read this same plist in Rails?


require 'test_helper'
class ReadPlistTest < ActiveSupport::TestCase
  test "recover names of regions and names of reps" do
    require "rexml/document"
    file = File.new("../data/regions.plist") # we're run from test, otherwise it'd be /data/regions.plist
    doc  = REXML::Document.new file
    region_names = []

    doc.elements.each("plist/dict/key") { |element| region_names << element.text }

    regions = {}
    i = 0    # can't use each_with_index
    doc.elements.each("plist/dict/array") do |element|
      region = []
      regions[region_names[i]] = region
      element.each_element("string") { |thing| region << thing.text }
      i+=1
    end

    puts regions.count.to_s
    puts y(regions)

  end
end

No comments: