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"
- @""
- @"";
@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
+
+
+
+