In this example we will show how to use the objective-c version of s.im.pl serialization to translate between runtime objects and xml files. In the getting started objective-c tutorial, we generated a set of header and implementation files from java annotated classes. We will now use those and slightly modify our rss_translationScope.xml file to serialize and deserialize a modified xml file.
To view this tutorial you will need to download the entire ecologylabFundamental project.
Access to the ecologylab fundamental project source is available
through
anonymous SVN access (user: anonymous, password: anonymous).
The source for this tutorial is
located under
/trunk/ecologylabXMLObjC/library/Rss
Below is the header file of Rss we generated from our Java annotated class definitions in the "getting started" tutorial. This defines the attributes which were annotated in Java or were semantically defined to bind to the XML file, such as a float variable "version" and a nested "Channel" object.
@interface Rss : ElementState { float version; Channel *channel; } @property (nonatomic, readwrite) float version; + (TranslationScope *) getTranslationScope; + (id) rssTestObject; - (void) setVersionWithReference: (float *) t; - (id) initTestObject; @end |
Below is the header of the "Channel" class which defines a set of attributes and a list of "Items". In objective-c we do not have strongly typed fields so items is defined as type "NSMutableArray".
@interface Channel : ElementState { NSString *title; NSString *description; ParsedURL *link; NSMutableArray *items; } @property (nonatomic, readwrite, retain) NSString *title; @property (nonatomic, readwrite, retain) NSString *description; @property (nonatomic, readwrite, retain) ParsedURL *link; @property (nonatomic, readwrite, retain) NSMutableArray *items; + (id) channelTestObject; - (id) initTestObject; @end |
Below is the class definition of "Item" which again defines a set of attributes and a list of "categorySets".
@interface Item : ElementState { NSString *title; NSString *description; ParsedURL *link; ParsedURL *guid; NSString *author; NSMutableArray *categorySet; } @property (nonatomic, readwrite, retain) NSString *title; @property (nonatomic, readwrite, retain) NSString *description; @property (nonatomic, readwrite, retain) ParsedURL *link; @property (nonatomic, readwrite, retain) ParsedURL *guid; @property (nonatomic, readwrite, retain) NSString *author; @property (nonatomic, readwrite, retain) NSMutableArray *categorySet; + (id) itemTestObject; - (id) initTestObject; @end |
In objective-c we create the translation scope from the XML file we generated from our Java classes. This translation scope XML is the internal data structure which s.im.pl serialization will use to derive the serialization and deserialization of the XML file.
<translation_scope name="rss">
<class_descriptor described_class="s.im.pl serialization.library.rss.Item"
tag_name="item">
<field_descriptor field="title" tag_name="title"
type="2" scalar_type="StringType" needs_escaping="true"></field_descriptor>
<field_descriptor field="description" tag_name="description"
type="2" scalar_type="StringType" needs_escaping="true"></field_descriptor>
<field_descriptor field="link" tag_name="link" type="2"
scalar_type="ParsedURLType" needs_escaping="true"></field_descriptor>
<field_descriptor field="guid" tag_name="guid" type="2"
scalar_type="ParsedURLType" needs_escaping="true"></field_descriptor>
<field_descriptor field="author" tag_name="author"
type="2" scalar_type="StringType" needs_escaping="true"></field_descriptor>
<field_descriptor field="categorySet" tag_name="category_set"
type="5" scalar_type="StringType" needs_escaping="true"
collection_or_map_tag_name="category"></field_descriptor>
</class_descriptor>
<class_descriptor described_class="s.im.pl serialization.library.rss.Rss"
tag_name="rss">
<field_descriptor field="version" tag_name="version"
type="1" scalar_type="FloatType"></field_descriptor>
<field_descriptor field="channel" tag_name="channel"
type="3" element_class="s.im.pl serialization.library.rss.Channel"></field_descriptor>
</class_descriptor>
<class_descriptor described_class="s.im.pl serialization.library.rss.Channel"
tag_name="channel">
<field_descriptor field="title" tag_name="title"
type="2" scalar_type="StringType" needs_escaping="true"></field_descriptor>
<field_descriptor field="description" tag_name="description"
type="2" scalar_type="StringType" needs_escaping="true"></field_descriptor>
<field_descriptor field="link" tag_name="link" type="2"
scalar_type="ParsedURLType" needs_escaping="true"></field_descriptor>
<field_descriptor field="items" tag_name="items"
type="4" collection_or_map_tag_name="item" wrapped="true"
element_class="s.im.pl serialization.library.rss.Item"></field_descriptor>
</class_descriptor>
</translation_scope>
|
Below we call the static "initWithXMLFilePath" function on TranslationScope, which will parse the above XML and create and initialize the internal data structures which will perform and drive the translation processes.
/* * Creating translation scope from XML file */ + (TranslationScope *) getTranslationScope { if(translationScope == nil){ NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: @"RssTranslationScope.xml"]; translationScope = [[TranslationScope alloc] initWithXMLFilePath: path]; } return translationScope; } |
We have now successfully initialized s.im.pl serialization and can now start serializing and deserializing XML files.
Serialization and de-serialization is driven by two functions. The static "TranslationScope" function "deserialize" and te "ElementState" inherited function "translateToXML".
//Rss Monomorphic test case //test.xml contains dummy Rss data which will deserialize and then serialize. NSString *rssInput = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: @"test.xml"];
//Creating translation scope from RssTranslationScope.xml and deserializing test.xml Rss *test = (Rss *)[[Rss getTranslationScope] deserialize: rssInput]; NSMutableString *rssoutput = [NSMutableString string];
//Serializing the data back to XML into an output MutableString buffer. [test serialize:rssoutput]; |
In the above code we use both the functions to translate back to a sample XML file.
Below is the test Rss XML file which we used for translation. This is not a correct Rss feed and "item" is wrapped by "items" tag. We can see in the above translation scope XML file that "items" collection is marked as wrapped.
We have now successfully translated to and from XML files in objective-c.