Index: src/OFObject+Serialization.m ================================================================== --- src/OFObject+Serialization.m +++ src/OFObject+Serialization.m @@ -46,11 +46,11 @@ root = [OFXMLElement elementWithName: @"serialization" namespace: OF_SERIALIZATION_NS]; [root addChild: element]; ret = [@"\n" - stringByAppendingString: [root XMLString]]; + stringByAppendingString: [root XMLStringWithIndentation: 2]]; [ret retain]; @try { [pool release]; } @catch (id e) { Index: src/OFXMLElement.h ================================================================== --- src/OFXMLElement.h +++ src/OFXMLElement.h @@ -254,14 +254,21 @@ */ - (OFString*)stringValue; /** * \return A new autoreleased OFString representing the OFXMLElement as an - * XML string + * XML string */ - (OFString*)XMLString; +/** + * \param indentation The indentation for the XML string + * \return A new autoreleased OFString representing the OFXMLElement as an + * XML string with indentation. + */ +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation; + /** * Adds the specified attribute. * * If an attribute with the same name and namespace already exists, it is not * added. Index: src/OFXMLElement.m ================================================================== --- src/OFXMLElement.m +++ src/OFXMLElement.m @@ -435,19 +435,22 @@ ret->isa = [OFString class]; return ret; } - (OFString*)_XMLStringWithParent: (OFXMLElement*)parent + indentation: (unsigned int)indentation + level: (size_t)level { OFAutoreleasePool *pool, *pool2; char *cString; size_t length, i, j, attributesCount; OFString *prefix, *parentPrefix; OFXMLAttribute **attributesCArray; OFString *ret, *tmp; OFMutableDictionary *allNamespaces; OFString *defaultNS; + BOOL indentAfter = YES; if (characters != nil) return [characters stringByXMLEscaping]; if (CDATA != nil) @@ -483,12 +486,15 @@ defaultNS = parent->defaultNamespace; else defaultNS = defaultNamespace; i = 0; - length = [name cStringLength] + 3; + length = [name cStringLength] + 3 + (level * indentation); cString = [self allocMemoryWithSize: length]; + + for (j = 0; j < level * indentation; j++) + cString[i++] = ' '; /* Start of tag */ cString[i++] = '<'; if (prefix != nil && ![ns isEqual: defaultNS]) { @@ -585,27 +591,47 @@ SEL appendSel = @selector(appendCStringWithoutUTF8Checking:); tmp = [OFMutableString string]; append = [tmp methodForSelector: appendSel]; - for (j = 0; j < childrenCount; j++) + for (j = 0; j < childrenCount; j++) { + if (indentation > 0 && childrenCArray[j]->name != nil) + append(tmp, appendSel, "\n"); + append(tmp, appendSel, - [[childrenCArray[j] _XMLStringWithParent: self] + [[childrenCArray[j] + _XMLStringWithParent: self + indentation: indentation + level: level + 1] cString]); + } - length += [tmp cStringLength] + [name cStringLength] + 2; + if (indentation > 0 && childrenCount > 0 && + childrenCArray[j - 1]->name != nil) + append(tmp, appendSel, "\n"); + else + indentAfter = NO; + + length += [tmp cStringLength] + [name cStringLength] + 2 + + (indentAfter ? level * indentation : 0); @try { cString = [self resizeMemory: cString toSize: length]; } @catch (id e) { [self freeMemory: cString]; @throw e; } cString[i++] = '>'; + memcpy(cString + i, [tmp cString], [tmp cStringLength]); i += [tmp cStringLength]; + + if (indentAfter) + for (j = 0; j < level * indentation; j++) + cString[i++] = ' '; + cString[i++] = '<'; cString[i++] = '/'; if (prefix != nil) { length += [prefix cStringLength] + 1; @try { @@ -640,16 +666,25 @@ return ret; } - (OFString*)XMLString { - return [self _XMLStringWithParent: nil]; + return [self _XMLStringWithParent: nil + indentation: 0 + level: 0]; +} + +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation +{ + return [self _XMLStringWithParent: nil + indentation: indentation + level: 0]; } - (OFString*)description { - return [self XMLString]; + return [self XMLStringWithIndentation: 2]; } - (OFXMLElement*)XMLElementBySerializing { OFAutoreleasePool *pool; Index: tests/OFSerializationTests.m ================================================================== --- tests/OFSerializationTests.m +++ tests/OFSerializationTests.m @@ -28,40 +28,10 @@ #import "OFXMLElement.h" #import "TestsAppDelegate.h" static OFString *module = @"OFSerialization"; -static const OFString *expected = @"\n" - @"" - @"" - @"Qu"xbar\ntest" - @"1234" - @"asd" - @"1234" - @"5678" - @"Hello" - @"Blub" - @"B"la" - @"Hello" - @"Wo ld!\nHow are you?" - @"https://webkeks.org/" - @"x" - @"" - @"http://www.w3.org/2000/xmlns/" - @"xmlns" - @"http://www.w3.org/XML/1998/namespace" - @"xml" - @"" - @"y" - @"" - @"http://www.w3.org/2000/xmlns/" - @"xmlns" - @"http://www.w3.org/XML/1998/namespace" - @"xml" - @"" - @"list" - @""; @implementation TestsAppDelegate (SerializationTests) - (void)serializationTests { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; @@ -88,13 +58,14 @@ [d setObject: @"list" forKey: l]; TEST(@"-[stringBySerializing]", - (s = [d stringBySerializing]) && [s isEqual: expected]) + (s = [d stringBySerializing]) && [s isEqual: + [OFString stringWithContentsOfFile: @"serialization.xml"]]) TEST(@"-[objectByDeserializing]", [[s objectByDeserializing] isEqual: d]) [pool drain]; } @end Index: tests/OFXMLElementTests.m ================================================================== --- tests/OFXMLElementTests.m +++ tests/OFXMLElementTests.m @@ -133,8 +133,13 @@ [[OFXMLElement elementWithXMLString: @""] isEqual: [OFXMLElement elementWithXMLString: @""]] && [[OFXMLElement elementWithXMLString: @""] isEqual: [OFXMLElement elementWithXMLString: @""]]) + TEST(@"-[XMLStringWithIndentation:]", + [[[OFXMLElement elementWithXMLString: @"a\nb"] + XMLStringWithIndentation: 2] isEqual: + @"\n \n a\nb\n \n"]) + [pool drain]; } @end ADDED tests/serialization.xml Index: tests/serialization.xml ================================================================== --- tests/serialization.xml +++ tests/serialization.xml @@ -0,0 +1,93 @@ + + + + + + + Qu"xbar +test + 1234 + asd + + 1234 + 5678 + + + + + Hello + + + + + Blub + + + B"la + + + + + + Hello + Wo ld! +How are you? + https://webkeks.org/ + + x + + + + + http://www.w3.org/2000/xmlns/ + + + xmlns + + + + + http://www.w3.org/XML/1998/namespace + + + xml + + + + + + + + y + + + + + http://www.w3.org/2000/xmlns/ + + + xmlns + + + + + http://www.w3.org/XML/1998/namespace + + + xml + + + + + + + + + + + + list + + + +