DELETED SERIALIZATION Index: SERIALIZATION ================================================================== --- SERIALIZATION +++ /dev/null @@ -1,182 +0,0 @@ -1.) Basic Concept - -This document describes the serialization used by ObjFW. It is designed to be -easy parsable and usable in other programming languages while still supporting -ObjFW-specific features, which are all optional. - -Every object can have a set of parameters which are optional and can be ignored -if they don't exist in the language for which parsing is done. These parameters -are written in the form (parameter1,parameter2) and precede the object. -Parameters not known by the implementation should be ignored - they are -completely optional except for the extension type. - -All spaces (except those in strings, of course) are optional and only to improve -readability - they are by no means required, but they are still recommended. - -ObjFW serialization supports 4 basic types: Strings, arrays and dictionaries. -It is limited to those 4 types because those are available in all languages. -Lists are a special case of arrays in ObjFW serialization. For all objects -that can not be serialized with those 4 basic types, there is the extension -type [], which can be used for any object but is not portable between languages. -This type is described in 6.). - - -2.) Strings - -Strings are very similar to how strings are done in C. They start with a " and -end with a ". The escape sequences \", \\, \n, \r and \t exist, like in C -strings. It is required to use \", \\, \n and \r. The reason for this is that -using an actual newline would modify the string when indention is done. However, -using \t is recommended. -Strings can be split just like in C. For example "Hello " "World" is equivalent -to "Hello World". Because this is possible, it is recommended to end the string -after \n and continue it in a new line to increase readability. - -Strings are required to be UTF-8 encoded. - -The only accepted parameter for strings is mutable. If the language for which -parsing is done does not know the concept of mutable and immutable objects, this -parameter should be ignored. - -Examples for strings: - - "This is a \"string!\"" - - "This is a string containing a\n" - "new line!" - - "This is\ta string\tcontaining tabs!" - - (mutable)"This string is mutable!" - - -3.) Arrays - -Arrays start with a [ and end with an ]. The elements are separated by a comma. -Whitespaces are allowed between objects and after the inital [ and before the -final ]. - -It allows the mutable parameter, which should be handled the same way like it -should be for strings. - -It also has the list parameter. Specifying this parameter creates a -double-linked list instead of an array. - -It also allows specifying a number as a parameter. This number is considered -the expected size of the array. It is by no means required and it should by no -means be assumed to be reliable. If the number is not equal to the actual size, -the parser should error out. The parser should also make sure to ignore the -number if it is too big to prevent a possible DoS. - -Examples for arrays: - - ["This", "is", "an", "array", "with", "7", "strings"] - - (mutable)["This array", "is mutable"] - - (3)["This array specifies", "the number of elements", "for performance"] - - (mutable,2)["Parameters can be", "combined"] - - -4.) Dictionaries - -Dictionary start with a { and end with a }. The elements are written in the form -key = value and each entry ends with an ;. - -It allows the mutable parameter, which should be handled the same way like it -should be for strings. - -It also allows specifying a number as a parameter, which should be handled -exactly like for arrays. - -Examples for dictionaries: - - {"This is a key" = "This is a value"} - - (mutable){"mutable" = (BOOL)1} - - (2){ - "key1" = "value1", - "key2" = "value2" - } - - { - ["Mapping", "an", "array"] = "To a string"; - { "mapping" = "a dictionary" } = ["To", "an", "array"]; - } - - -5.) Numbers - -Numbers are written by just writing a number. The type of a number may be -specified by a parameter. If it is not specified, the implementation should -choose are type which fits the number. If the specified type is not big enough -for the number, the implementation should use another type that fits. - -Known parameters are: - BOOL - char (signed!) - short (signed!) - int (signed!) - long (signed!) - int8_t - int16_t - int32_t - int64_t - unsigned char, - unsigned short, - unsigned int, - unsigned long - uint8_t - uint16_t - uint32_t - uint64_t - size_t - ssize_t - intmax_t - uintmax_t - intptr_t - uintptr_t - float - double - -Examples for numbers: - - 1 - 2.6 - (BOOL)0 - (intmax_t)1234567 - (double)2.5 - - -6.) Extension Type - -The extension type allows adding new objects to ObjFW serialization. The -extension type has a parameter class= which specifies the class which should -handle deserialization and a version= parameter which specifies the version of -the class serialization as a single integer. The extension type starts with a [ -and ends with a ]. Inside those brackets can be arbitray basic types, which -should be passed unmodified to the class for deserialization. -If an implementation can't deserialize an extension type, it is required to -error out. Other languages are allowed to parse extension types of classes which -are in ObjFW, like OFXMLElement, but are by no means required to do so. Other -languages may also add their own extension types, but are required to add the -foreign= parameter and set it to their name, so other implementations don't try -to deserialize it, but error out instead. Other implementations are allowed to -serialize to ObjFW objects if they know them. For example, it might be desirable -to also create OFXMLElements from other languages. - -Examples for using the extension type: - - (class=OFXMLElement)<""> - - (class=OFURL)< - "https://webkeks.org/objfw/" - > - - (class=Foo,foreign=Foolang)< - { - "property1" = "value1" - } - > Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -19,10 +19,11 @@ #include #import "OFArray.h" #import "OFDataArray.h" #import "OFString.h" +#import "OFXMLElement.h" #import "OFAutoreleasePool.h" #import "OFEnumerationMutationException.h" #import "OFOutOfRangeException.h" @@ -430,53 +431,32 @@ */ ret->isa = [OFString class]; return ret; } -- (OFString*)stringBySerializing +- (OFXMLElement*)XMLElementBySerializing { OFAutoreleasePool *pool; - OFMutableString *ret; - OFObject **cArray; - size_t i, count; - - if ([array count] == 0) { - if ([self isKindOfClass: [OFMutableArray class]]) - return @"(mutable,0)[]"; - else - return @"(0)[]"; - } - - cArray = [array cArray]; - count = [array count]; - if ([self isKindOfClass: [OFMutableArray class]]) - ret = [OFMutableString stringWithFormat: @"(mutable,%zd)[\n", - count]; - else - ret = [OFMutableString stringWithFormat: @"(%zd)[\n", count]; + OFXMLElement *element; + id *cArray = [array cArray]; + size_t i, count = [array count]; + + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS]; + pool = [[OFAutoreleasePool alloc] init]; + [element addAttributeWithName: @"class" + stringValue: [self className]]; - for (i = 0; i < count - 1; i++) { - [ret appendString: [cArray[i] stringBySerializing]]; - [ret appendString: @",\n"]; - + for (i = 0; i < count; i++) { + [element addChild: [cArray[i] XMLElementBySerializing]]; [pool releaseObjects]; } - [ret appendString: [cArray[i] stringBySerializing]]; - [ret replaceOccurrencesOfString: @"\n" - withString: @"\n\t"]; - [ret appendString: @"\n]"]; [pool release]; - /* - * Class swizzle the string to be immutable. We declared the return type - * to be OFString*, so it can't be modified anyway. But not swizzling it - * would create a real copy each time -[copy] is called. - */ - ret->isa = [OFString class]; - return ret; + return element; } - (void)makeObjectsPerformSelector: (SEL)selector { id *cArray = [array cArray]; Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -23,11 +23,11 @@ #include #import "OFDate.h" #import "OFString.h" #import "OFDictionary.h" -#import "OFNumber.h" +#import "OFXMLElement.h" #import "OFAutoreleasePool.h" #ifdef OF_THREADS # import "OFThread.h" #endif @@ -289,27 +289,36 @@ - (OFString*)description { return [self dateStringWithFormat: @"%Y-%m-%dT%H:%M:%SZ"]; } -- (OFString*)stringBySerializing -{ - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFDictionary *dictionary = [OFDictionary dictionaryWithKeysAndObjects: - @"seconds", [OFNumber numberWithInt64: seconds], - @"microseconds", [OFNumber numberWithUInt32: microseconds], nil]; - OFString *ret = [[OFString alloc] - initWithFormat: @"(class=OFDate,version=0)<%@>", - [dictionary stringBySerializing]]; - - @try { - [pool release]; - } @finally { - [ret autorelease]; - } - - return ret; +- (OFXMLElement*)XMLElementBySerializing +{ + OFAutoreleasePool *pool; + OFXMLElement *element; + + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS]; + + pool = [[OFAutoreleasePool alloc] init]; + [element addAttributeWithName: @"class" + stringValue: [self className]]; + + [element addChild: + [OFXMLElement elementWithName: @"seconds" + namespace: OF_SERIALIZATION_NS + stringValue: [OFString stringWithFormat: + @"%" PRId64, seconds]]]; + [element addChild: + [OFXMLElement elementWithName: @"microseconds" + namespace: OF_SERIALIZATION_NS + stringValue: [OFString stringWithFormat: + @"%" PRIu32, microseconds]]]; + + [pool release]; + + return element; } - (uint32_t)microsecond { return microseconds; Index: src/OFDictionary.m ================================================================== --- src/OFDictionary.m +++ src/OFDictionary.m @@ -20,10 +20,11 @@ #import "OFDictionary.h" #import "OFEnumerator.h" #import "OFArray.h" #import "OFString.h" +#import "OFXMLElement.h" #import "OFAutoreleasePool.h" #import "OFEnumerationMutationException.h" #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" @@ -755,61 +756,55 @@ */ ret->isa = [OFString class]; return ret; } -- (OFString*)stringBySerializing +- (OFXMLElement*)XMLElementBySerializing { - OFMutableString *ret; OFAutoreleasePool *pool, *pool2; + OFXMLElement *element; OFEnumerator *keyEnumerator, *objectEnumerator; - id key, object; - size_t i; - - if (count == 0) { - if ([self isKindOfClass: [OFMutableDictionary class]]) - return @"(mutable,0){}"; - else - return @"(0){}"; - } - - if ([self isKindOfClass: [OFMutableDictionary class]]) - ret = [OFMutableString stringWithFormat: @"(mutable,%zd){\n", - count]; - else - ret = [OFMutableString stringWithFormat: @"(%zd){\n", count]; + id key, object; + + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS]; + pool = [[OFAutoreleasePool alloc] init]; + [element addAttributeWithName: @"class" + stringValue: [self className]]; + keyEnumerator = [self keyEnumerator]; objectEnumerator = [self objectEnumerator]; - i = 0; pool2 = [[OFAutoreleasePool alloc] init]; - while ((key = [keyEnumerator nextObject]) != nil && - (object = [objectEnumerator nextObject]) != nil) { - [ret appendString: [key stringBySerializing]]; - [ret appendString: @" = "]; - [ret appendString: [object stringBySerializing]]; + (object = [objectEnumerator nextObject]) != nil) { + OFXMLElement *pair, *keyElement, *valueElement; + + pair = [OFXMLElement elementWithName: @"pair" + namespace: OF_SERIALIZATION_NS]; + + keyElement = [OFXMLElement + elementWithName: @"key" + namespace: OF_SERIALIZATION_NS]; + [keyElement addChild: [key XMLElementBySerializing]]; + [pair addChild: keyElement]; + + valueElement = [OFXMLElement + elementWithName: @"value" + namespace: OF_SERIALIZATION_NS]; + [valueElement addChild: [object XMLElementBySerializing]]; + [pair addChild: valueElement]; - if (++i < count) - [ret appendString: @",\n"]; + [element addChild: pair]; [pool2 releaseObjects]; } - [ret replaceOccurrencesOfString: @"\n" - withString: @"\n\t"]; - [ret appendString: @"\n}"]; [pool release]; - /* - * Class swizzle the string to be immutable. We declared the return type - * to be OFString*, so it can't be modified anyway. But not swizzling it - * would create a real copy each time -[copy] is called. - */ - ret->isa = [OFString class]; - return ret; + return element; } @end @implementation OFDictionaryEnumerator - initWithDictionary: (OFDictionary*)dictionary_ Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -18,10 +18,11 @@ #include "assert.h" #import "OFList.h" #import "OFString.h" +#import "OFXMLElement.h" #import "OFAutoreleasePool.h" #import "OFEnumerationMutationException.h" #import "macros.h" @@ -321,64 +322,52 @@ */ ret->isa = [OFString class]; return ret; } -- (OFString*)stringBySerializing +- (OFXMLElement*)XMLElementBySerializing { - OFMutableString *ret; OFAutoreleasePool *pool; + OFXMLElement *element; of_list_object_t *iter; - if (count == 0) - return @"(list,mutable)[]"; + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS]; - ret = [OFMutableString stringWithString: @"(list,mutable)[\n"]; pool = [[OFAutoreleasePool alloc] init]; + [element addAttributeWithName: @"class" + stringValue: [self className]]; for (iter = firstListObject; iter != NULL; iter = iter->next) { - [ret appendString: [iter->object stringBySerializing]]; - - if (iter->next != NULL) - [ret appendString: @",\n"]; - + [element addChild: [iter->object XMLElementBySerializing]]; [pool releaseObjects]; } - [ret replaceOccurrencesOfString: @"\n" - withString: @"\n\t"]; - [ret appendString: @"\n]"]; [pool release]; - /* - * Class swizzle the string to be immutable. We declared the return type - * to be OFString*, so it can't be modified anyway. But not swizzling it - * would create a real copy each time -[copy] is called. - */ - ret->isa = [OFString class]; - return ret; + return element; } - (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state objects: (id*)objects count: (int)count_ { - of_list_object_t **list_obj = (of_list_object_t**)state->extra; + of_list_object_t **listObject = (of_list_object_t**)state->extra; state->itemsPtr = objects; state->mutationsPtr = &mutations; if (state->state == 0) { - *list_obj = firstListObject; + *listObject = firstListObject; state->state = 1; } - if (*list_obj == NULL) + if (*listObject == NULL) return 0; - objects[0] = (*list_obj)->object; - *list_obj = (*list_obj)->next; + objects[0] = (*listObject)->object; + *listObject = (*listObject)->next; return 1; } - (OFEnumerator*)objectEnumerator { Index: src/OFNumber.m ================================================================== --- src/OFNumber.m +++ src/OFNumber.m @@ -18,10 +18,12 @@ #include #import "OFNumber.h" #import "OFString.h" +#import "OFXMLElement.h" +#import "OFAutoreleasePool.h" #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" #import "macros.h" @@ -1088,90 +1090,70 @@ default: @throw [OFInvalidFormatException newWithClass: isa]; } } -- (OFString*)stringBySerializing +- (OFXMLElement*)XMLElementBySerializing { + OFAutoreleasePool *pool; + OFXMLElement *element; + + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS]; + + pool = [[OFAutoreleasePool alloc] init]; + + [element addAttributeWithName: @"class" + stringValue: [self className]]; + [element setStringValue: [self description]]; + switch (type) { case OF_NUMBER_BOOL: - return (value.bool_ ? @"1" : @"0"); + [element addAttributeWithName: @"type" + stringValue: @"boolean"]; + break; case OF_NUMBER_UCHAR: - return [OFString stringWithFormat: @"%hhu", - value.uchar]; case OF_NUMBER_USHORT: - return [OFString stringWithFormat: @"%hu", - value.ushort]; case OF_NUMBER_UINT: - return [OFString stringWithFormat: @"%u", - value.uint]; case OF_NUMBER_ULONG: - return [OFString stringWithFormat: @"%lu", - value.ulong]; case OF_NUMBER_UINT8: - return [OFString stringWithFormat: @"%" @PRIu8, - value.uint8]; case OF_NUMBER_UINT16: - return [OFString stringWithFormat: @"%" @PRIu16, - value.uint16]; case OF_NUMBER_UINT32: - return [OFString stringWithFormat: @"%" @PRIu32, - value.uint32]; case OF_NUMBER_UINT64: - return [OFString stringWithFormat: @"%" @PRIu64, - value.uint64]; case OF_NUMBER_SIZE: - return [OFString stringWithFormat: @"%ju", - (uintmax_t)value.size]; case OF_NUMBER_UINTMAX: - return [OFString stringWithFormat: @"%ju", - value.uintmax]; case OF_NUMBER_UINTPTR: - return [OFString stringWithFormat: @"%" @PRIuPTR, - value.uintptr]; + [element addAttributeWithName: @"type" + stringValue: @"unsigned"]; + break; case OF_NUMBER_CHAR: - return [OFString stringWithFormat: @"%hhd", - value.char_]; case OF_NUMBER_SHORT: - return [OFString stringWithFormat: @"%hd", - value.short_]; case OF_NUMBER_INT: - return [OFString stringWithFormat: @"%d", - value.int_]; case OF_NUMBER_LONG: - return [OFString stringWithFormat: @"%ld", - value.long_]; case OF_NUMBER_INT8: - return [OFString stringWithFormat: @"%" @PRId8, - value.int8]; case OF_NUMBER_INT16: - return [OFString stringWithFormat: @"%" @PRId16, - value.int16]; case OF_NUMBER_INT32: - return [OFString stringWithFormat: @"%" @PRId32, - value.int32]; case OF_NUMBER_INT64: - return [OFString stringWithFormat: @"%" @PRId64, - value.int64]; case OF_NUMBER_SSIZE: - return [OFString stringWithFormat: @"%jd", - (intmax_t)value.ssize]; case OF_NUMBER_INTMAX: - return [OFString stringWithFormat: @"%jd", - value.intmax]; case OF_NUMBER_PTRDIFF: - return [OFString stringWithFormat: @"%td" @PRIdPTR, - value.ptrdiff]; case OF_NUMBER_INTPTR: - return [OFString stringWithFormat: @"%" @PRIdPTR, - value.intptr]; + [element addAttributeWithName: @"type" + stringValue: @"signed"]; + break; case OF_NUMBER_FLOAT: - return [OFString stringWithFormat: @"%f", - value.float_]; + [element addAttributeWithName: @"type" + stringValue: @"float"]; + break; case OF_NUMBER_DOUBLE: - return [OFString stringWithFormat: @"%lf", - value.double_]; + [element addAttributeWithName: @"type" + stringValue: @"double"]; + break; default: @throw [OFInvalidFormatException newWithClass: isa]; } + + [pool release]; + + return element; } @end Index: src/OFSerialization.h ================================================================== --- src/OFSerialization.h +++ src/OFSerialization.h @@ -13,15 +13,20 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ @class OFString; +@class OFXMLElement; + +#define OF_SERIALIZATION_NS @"https://webkeks.org/objfw/serialization" /** * \brief A protocol for serializing objects. */ @protocol OFSerialization /** - * \brief Serializes the object into a string. + * \brief Serializes the object into an XML element. + * + * \return The object serialized into an XML element */ -- (OFString*)stringBySerializing; +- (OFXMLElement*)XMLElementBySerializing; @end Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -34,10 +34,11 @@ #import "OFArray.h" #import "OFDictionary.h" #import "OFFile.h" #import "OFURL.h" #import "OFHTTPRequest.h" +#import "OFXMLElement.h" #import "OFAutoreleasePool.h" #import "OFHTTPRequestFailedException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" @@ -1053,37 +1054,31 @@ - (OFString*)description { return [[self copy] autorelease]; } -- (OFString*)stringBySerializing -{ - OFMutableString *serialization = [[self mutableCopy] autorelease]; - [serialization replaceOccurrencesOfString: @"\\" - withString: @"\\\\"]; - [serialization replaceOccurrencesOfString: @"\"" - withString: @"\\\""]; - [serialization replaceOccurrencesOfString: @"\n" - withString: @"\\n\"\n \""]; - [serialization replaceOccurrencesOfString: @"\r" - withString: @"\\r"]; - [serialization replaceOccurrencesOfString: @"\t" - withString: @"\\t"]; - - if ([self isKindOfClass: [OFMutableString class]]) - [serialization prependString: @"(mutable)\""]; +- (OFXMLElement*)XMLElementBySerializing +{ + OFAutoreleasePool *pool; + OFXMLElement *element; + + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS + stringValue: self]; + + pool = [[OFAutoreleasePool alloc] init]; + + if ([self isKindOfClass: [OFConstantString class]]) + [element addAttributeWithName: @"class" + stringValue: @"OFString"]; else - [serialization prependString: @"\""]; - [serialization appendString: @"\""]; - - /* - * Class swizzle the string to be immutable. We declared the return type - * to be OFString*, so it can't be modified anyway. But not swizzling it - * would create a real copy each time -[copy] is called. - */ - serialization->isa = [OFString class]; - return serialization; + [element addAttributeWithName: @"class" + stringValue: [self className]]; + + [pool release]; + + return element; } - (of_unichar_t)characterAtIndex: (size_t)index { of_unichar_t c; Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -21,10 +21,11 @@ #include #import "OFURL.h" #import "OFString.h" #import "OFArray.h" +#import "OFXMLElement.h" #import "OFAutoreleasePool.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfMemoryException.h" @@ -528,21 +529,24 @@ - (OFString*)description { return [self string]; } -- (OFString*)stringBySerializing -{ - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFString *ret = [[OFString alloc] - initWithFormat: @"(class=OFURL,version=0)<%@>", - [[self string] stringBySerializing]]; - - @try { - [pool release]; - } @finally { - [ret autorelease]; - } - - return ret; +- (OFXMLElement*)XMLElementBySerializing +{ + OFAutoreleasePool *pool; + OFXMLElement *element; + + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS]; + + pool = [[OFAutoreleasePool alloc] init]; + + [element addAttributeWithName: @"class" + stringValue: [self className]]; + [element setStringValue: [self string]]; + + [pool release]; + + return element; } @end Index: src/OFXMLAttribute.m ================================================================== --- src/OFXMLAttribute.m +++ src/OFXMLAttribute.m @@ -17,10 +17,11 @@ #include "config.h" #import "OFXMLAttribute.h" #import "OFString.h" #import "OFDictionary.h" +#import "OFXMLElement.h" #import "OFAutoreleasePool.h" @implementation OFXMLAttribute + attributeWithName: (OFString*)name namespace: (OFString*)ns @@ -71,36 +72,37 @@ - (OFString*)stringValue { return [[stringValue copy] autorelease]; } -- (OFString*)stringBySerializing -{ - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFMutableDictionary *dictionary = [OFMutableDictionary dictionary]; - OFString *ret; - - if (name != nil) - [dictionary setObject: name - forKey: @"name"]; - if (ns != nil) - [dictionary setObject: ns - forKey: @"namespace"]; - if (stringValue != nil) - [dictionary setObject: stringValue - forKey: @"stringValue"]; - - dictionary->isa = [OFDictionary class]; - - ret = [[OFString alloc] - initWithFormat: @"(class=OFXMLElement,version=0)<%@>", - [dictionary stringBySerializing]]; - - @try { - [pool release]; - } @finally { - [ret autorelease]; - } - - return ret; +- (OFXMLElement*)XMLElementBySerializing +{ + OFAutoreleasePool *pool; + OFXMLElement *element; + + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS]; + + pool = [[OFAutoreleasePool alloc] init]; + + [element addAttributeWithName: @"class" + stringValue: [self className]]; + + [element addChild: + [OFXMLElement elementWithName: @"name" + namespace: OF_SERIALIZATION_NS + stringValue: name]]; + if (ns != nil) + [element addChild: + [OFXMLElement elementWithName: @"namespace" + namespace: OF_SERIALIZATION_NS + stringValue: ns]]; + [element addChild: + [OFXMLElement elementWithName: @"stringValue" + namespace: OF_SERIALIZATION_NS + stringValue: stringValue]]; + + [pool release]; + + return element; } @end Index: src/OFXMLElement.m ================================================================== --- src/OFXMLElement.m +++ src/OFXMLElement.m @@ -566,57 +566,94 @@ - (OFString*)description { return [self XMLString]; } -- (OFString*)stringBySerializing +- (OFXMLElement*)XMLElementBySerializing { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFMutableDictionary *dictionary = [OFMutableDictionary dictionary]; - OFString *ret; + OFAutoreleasePool *pool; + OFXMLElement *element; + + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS]; + + pool = [[OFAutoreleasePool alloc] init]; + + [element addAttributeWithName: @"class" + stringValue: [self className]]; if (name != nil) - [dictionary setObject: name - forKey: @"name"]; - if (ns != nil) - [dictionary setObject: ns - forKey: @"namespace"]; - if (defaultNamespace != nil) - [dictionary setObject: defaultNamespace - forKey: @"defaultNamespace"]; - if (attributes != nil) - [dictionary setObject: attributes - forKey: @"attributes"]; - if (namespaces != nil) - [dictionary setObject: namespaces - forKey: @"namespaces"]; - if (children != nil) - [dictionary setObject: children - forKey: @"children"]; - if (characters != nil) - [dictionary setObject: characters - forKey: @"characters"]; - if (CDATA != nil) - [dictionary setObject: CDATA - forKey: @"CDATA"]; - if (comment != nil) - [dictionary setObject: comment - forKey: @"comment"]; - - dictionary->isa = [OFDictionary class]; - - ret = [[OFString alloc] - initWithFormat: @"(class=OFXMLElement,version=0)<%@>", - [dictionary stringBySerializing]]; - - @try { - [pool release]; - } @finally { - [ret autorelease]; - } - - return ret; + [element addChild: + [OFXMLElement elementWithName: @"name" + namespace: OF_SERIALIZATION_NS + stringValue: name]]; + + if (ns != nil) + [element addChild: + [OFXMLElement elementWithName: @"namespace" + namespace: OF_SERIALIZATION_NS + stringValue: ns]]; + + if (defaultNamespace != nil) + [element addChild: + [OFXMLElement elementWithName: @"defaultNamespace" + namespace: OF_SERIALIZATION_NS + stringValue: defaultNamespace]]; + + if (attributes != nil) { + OFXMLElement *attributesElement; + + attributesElement = + [OFXMLElement elementWithName: @"attributes" + namespace: OF_SERIALIZATION_NS]; + [attributesElement addChild: + [attributes XMLElementBySerializing]]; + [element addChild: attributesElement]; + } + + if (namespaces != nil) { + OFXMLElement *namespacesElement; + + namespacesElement = + [OFXMLElement elementWithName: @"namespaces" + namespace: OF_SERIALIZATION_NS]; + [namespacesElement addChild: + [namespaces XMLElementBySerializing]]; + [element addChild: namespacesElement]; + } + + if (children != nil) { + OFXMLElement *childrenElement; + + childrenElement = + [OFXMLElement elementWithName: @"children" + namespace: OF_SERIALIZATION_NS]; + [childrenElement addChild: [children XMLElementBySerializing]]; + [element addChild: childrenElement]; + } + + if (characters != nil) + [element addChild: + [OFXMLElement elementWithName: @"characters" + namespace: OF_SERIALIZATION_NS + stringValue: characters]]; + + if (CDATA != nil) + [element addChild: + [OFXMLElement elementWithName: @"CDATA" + namespace: OF_SERIALIZATION_NS + stringValue: CDATA]]; + + if (comment != nil) + [element addChild: + [OFXMLElement elementWithName: @"comment" + namespace: OF_SERIALIZATION_NS + stringValue: comment]]; + + [pool release]; + + return element; } - (void)addAttribute: (OFXMLAttribute*)attribute { if (name == nil)