Parse an iOS plist on Android

I was implementing a feature in the CalorieCount Android App the other day that was previously implemented in the iOS version of that same app. Just needed to show a list of timezones based on what country was selected. Not rocket science at all, but the iOS implementation was storing the data in a plist file, with a <dict> element inside. So rather than take that data and try to translate it to something more ‘android specific’ … I decided to just use the file as is. The biggest benefit was that in the future if we ever had to update the file, I could update it in place, and simply copy it over to the other platform.

So I copied the file into my xml folder, and wrote this simple parser that reads the file in, and parses it into a HashMap

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
package cyborg;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
 
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
 
import android.content.Context;
 
/**
* This class parses an iOS plist with a dict element into a hashmap.
*/
public class XmlMapParser {
private XmlPullParser parser;
 
public XmlMapVisitor(Context context, int xmlid) {
parser = context.getResources().getXml(xmlid);
}
 
public HashMap<String, ArrayList<String>> convert() {
HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
 
final String KEY = "key", STRING = "string";
try {
parser.next();
int eventType = parser.getEventType();
String lastTag = null;
String lastKey = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
lastTag = parser.getName();
}
else if (eventType == XmlPullParser.TEXT) {
// some text
if (KEY.equalsIgnoreCase(lastTag)) {
// start tracking a new key
lastKey = parser.getText();
}
else if (STRING.equalsIgnoreCase(lastTag)) {
// a new string for the last encountered key
if (!map.containsKey(lastKey)) {
map.put(lastKey, new ArrayList<String>());
}
map.get(lastKey).add(parser.getText());
}
}
eventType = parser.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
 
return map;
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>key1</key>
<array>
<string>one</string>
<string>two</string>
</array>
<key>key2</key>
<array>
<string>one</string>
<string>two</string>
</array>
</dict>
</plist>
view raw sample.plist This Gist brought to you by GitHub.

The way I look at it, may as well reuse what we’ve got, and spend less time yak shaving (ie. translating between platforms) … git ‘er done!

Leave a Comment