Reputation: 3644
I want to convert a xml file to a plist file, but I dont know how to save the information of the xml attributes <tag attribute="value"></tag>
example xml:
<root>
<tag attribute="value">Stackoverflow</tag>
</root>
as far as I know, .plist file doesnt provide attributes, so what can I do to prevent a .plist like this:
<root>
<array>
<item>StackOverflow</item>
<item>value</item>
</array>
</root>
I dont want an array for each tag with an attribute, so does anyone knows a simplier approach? I searched the web on this but couldnt find a solution. Thank you.
Upvotes: 2
Views: 1534
Reputation: 438092
Rather than dwelling on the plist format, I think the more interesting question is what is the appropriate combination of nested NSArray
and NSDictionary
collection objects that best represent this structure in Objective-C. Then, once you have it in nested collection objects, you can employ the writeToFile
method to generate the plist file automatically.
Now you say that you don't want an "array for each tag with an attribute". First, I wouldn't have suggested an array, but I'd actually suggest a dictionary. Second, that's precisely what I think you want, a consistent, intelligible representation for each tag. Third, I'd suggest you do this not only for the tags with attributes, but I might even do it for all tags.
I'm not sure why you said you don't want to use an array for each tag, but while it might seem inefficient, it turns out that it's much easier to do that, because then your structure will be in a consistent, easy to use format.
The simplest solution is to have a dictionary for each element in the XML source, one key would be @"value"
and another would be @"attributes"
(and you could omit the attributes
if there were none).
Imagine the following XML:
<produce>
<product>
<name language="English">Apple</name>
<price currency="USD">1.23</price>
<color>red</color>
</product>
<product>
<name language="English">Banana</name>
<price currency="USD">2.63</price>
<color>yellow</color>
</product>
</produce>
I'm suggesting you have an array of products, for which each product is a NSDictionary
with three keys, name
, price
, and color
. The values for these three are, themselves, NSDictionary
objects, but with two keys, value
and, if appropriate, attributes
. Thus, if you were going to represent that resulting series of nested objects manually in code, it might look like (where, @[a, b, c]
is a NSArray
, and @{key1:value1, key2:value2}
is a NSDictionary
):
NSArray *array = @[
@{
@"name":
@{
@"value" : @"Apple",
@"attributes" : @{@"language":@"English"}
},
@"price":
@{
@"value" : @1.23,
@"attributes" : @{@"currency":@"USD"}
},
@"color":
@{
@"value" : @"red"
}
},
@{
@"name":
@{
@"value" : @"Banana",
@"attributes" : @{@"language":@"English"}
},
@"price":
@{
@"value":@1.46,
@"attributes":@{@"currency":@"USD"}
},
@"color":@{@"value":@"yellow"}
}
];
While that looks complicated, it's actually incredibly easy to use. If you want the second object, that would be array[1]
. If you want the color of that second object, it would be array[1][@"color"][@"value"]
. If you wanted the name of the language of the first object, it would be array[0][@"name"][@"attributes"][@"language"]
. Once you start using this nested collection object structure, you can see (a) why I prefer dictionaries to arrays; but also why (b) I use the same dictionary structure whether there is an attribute or not, that way the process of retrieving the value is consistent at all times.
Anyway, if I now employ the writeToFile
method, that happens to yields a plist like so:
<?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">
<array>
<dict>
<key>color</key>
<dict>
<key>value</key>
<string>red</string>
</dict>
<key>name</key>
<dict>
<key>attributes</key>
<dict>
<key>language</key>
<string>English</string>
</dict>
<key>value</key>
<string>Apple</string>
</dict>
<key>price</key>
<dict>
<key>attributes</key>
<dict>
<key>currency</key>
<string>USD</string>
</dict>
<key>value</key>
<real>1.23</real>
</dict>
</dict>
<dict>
<key>color</key>
<dict>
<key>value</key>
<string>yellow</string>
</dict>
<key>name</key>
<dict>
<key>attributes</key>
<dict>
<key>language</key>
<string>English</string>
</dict>
<key>value</key>
<string>Banana</string>
</dict>
<key>price</key>
<dict>
<key>attributes</key>
<dict>
<key>currency</key>
<string>USD</string>
</dict>
<key>value</key>
<real>1.46</real>
</dict>
</dict>
</array>
</plist>
But the nice thing is, I don't have to write a plist myself. I just load the XML into my structure of nested arrays and dictionaries, and then use writeToFile
to generate the plist file. And when I want to use that plist, I can now read it with a single call to arrayWithContentsOfFile
.
Upvotes: 2