Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -204,10 +204,17 @@ 4B3D23EB1337FCB000DD29B8 /* unicode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B67998C1099E7C50041064A /* unicode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B3D23EE1337FFD000DD29B8 /* of_asprintf.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB50DD012F863C700C9393F /* of_asprintf.m */; }; 4B3D5694139A617D0010A78F /* OFSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B3D5693139A617D0010A78F /* OFSerializationTests.m */; }; 4B45355313DCFE1E0037AB4D /* OFCountedSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B45355113DCFE1E0037AB4D /* OFCountedSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B45355413DCFE1E0037AB4D /* OFCountedSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B45355213DCFE1E0037AB4D /* OFCountedSet.m */; }; + 4B49EA66143B39CE0005BBC6 /* OFXMLNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49EA65143B39CE0005BBC6 /* OFXMLNodeTests.m */; }; + 4B49EA6D143B3A090005BBC6 /* OFXMLCDATA.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49EA67143B3A090005BBC6 /* OFXMLCDATA.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B49EA6E143B3A090005BBC6 /* OFXMLCDATA.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49EA68143B3A090005BBC6 /* OFXMLCDATA.m */; }; + 4B49EA6F143B3A090005BBC6 /* OFXMLCharacters.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49EA69143B3A090005BBC6 /* OFXMLCharacters.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B49EA70143B3A090005BBC6 /* OFXMLCharacters.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49EA6A143B3A090005BBC6 /* OFXMLCharacters.m */; }; + 4B49EA71143B3A090005BBC6 /* OFXMLComment.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49EA6B143B3A090005BBC6 /* OFXMLComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B49EA72143B3A090005BBC6 /* OFXMLComment.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49EA6C143B3A090005BBC6 /* OFXMLComment.m */; }; 4B511B7C139C0A34003764A5 /* OFNull.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B511B7A139C0A34003764A5 /* OFNull.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B511B7D139C0A34003764A5 /* OFNull.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B511B7B139C0A34003764A5 /* OFNull.m */; }; 4B55A0FF133ABEA900B58A93 /* OFThreadJoinFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0F9133ABEA900B58A93 /* OFThreadJoinFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A100133ABEA900B58A93 /* OFThreadJoinFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FA133ABEA900B58A93 /* OFThreadJoinFailedException.m */; }; 4B55A101133ABEA900B58A93 /* OFThreadStartFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0FB133ABEA900B58A93 /* OFThreadStartFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -305,11 +312,10 @@ 4BF33B0A133807A20059CEF7 /* OFStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF6791235358D0076B512 /* OFStringTests.m */; }; 4BF33B0B133807A20059CEF7 /* OFTCPSocketTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67A1235358D0076B512 /* OFTCPSocketTests.m */; }; 4BF33B0C133807A20059CEF7 /* OFThreadTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67B1235358D0076B512 /* OFThreadTests.m */; }; 4BF33B0D133807A20059CEF7 /* OFURLTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF0749512DFAFCA00A4ADD1 /* OFURLTests.m */; }; 4BF33B0E133807A20059CEF7 /* OFXMLElementBuilderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67C1235358D0076B512 /* OFXMLElementBuilderTests.m */; }; - 4BF33B0F133807A20059CEF7 /* OFXMLElementTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67D1235358D0076B512 /* OFXMLElementTests.m */; }; 4BF33B10133807A20059CEF7 /* OFXMLParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67E1235358D0076B512 /* OFXMLParserTests.m */; }; 4BF33B11133807A20059CEF7 /* PropertiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67F1235358D0076B512 /* PropertiesTests.m */; }; 4BF33B12133807A20059CEF7 /* TestsAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF6811235358D0076B512 /* TestsAppDelegate.m */; }; 4BF33B4713380CE20059CEF7 /* testfile.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BF33B4313380CD40059CEF7 /* testfile.txt */; }; 4BF33B4813380D2D0059CEF7 /* testfile.bin in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BF33B4213380CD40059CEF7 /* testfile.bin */; }; @@ -470,10 +476,17 @@ 4B3D23EF1338008000DD29B8 /* mach_alias_list */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mach_alias_list; path = src/mach_alias_list; sourceTree = SOURCE_ROOT; }; 4B3D5693139A617D0010A78F /* OFSerializationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSerializationTests.m; path = tests/OFSerializationTests.m; sourceTree = ""; }; 4B45355113DCFE1E0037AB4D /* OFCountedSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCountedSet.h; path = src/OFCountedSet.h; sourceTree = ""; }; 4B45355213DCFE1E0037AB4D /* OFCountedSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCountedSet.m; path = src/OFCountedSet.m; sourceTree = ""; }; 4B4986DF1101F64500A2CFDA /* objc_properties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = objc_properties.m; path = src/objc_properties.m; sourceTree = ""; }; + 4B49EA65143B39CE0005BBC6 /* OFXMLNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLNodeTests.m; path = tests/OFXMLNodeTests.m; sourceTree = ""; }; + 4B49EA67143B3A090005BBC6 /* OFXMLCDATA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLCDATA.h; path = src/OFXMLCDATA.h; sourceTree = ""; }; + 4B49EA68143B3A090005BBC6 /* OFXMLCDATA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLCDATA.m; path = src/OFXMLCDATA.m; sourceTree = ""; }; + 4B49EA69143B3A090005BBC6 /* OFXMLCharacters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLCharacters.h; path = src/OFXMLCharacters.h; sourceTree = ""; }; + 4B49EA6A143B3A090005BBC6 /* OFXMLCharacters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLCharacters.m; path = src/OFXMLCharacters.m; sourceTree = ""; }; + 4B49EA6B143B3A090005BBC6 /* OFXMLComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLComment.h; path = src/OFXMLComment.h; sourceTree = ""; }; + 4B49EA6C143B3A090005BBC6 /* OFXMLComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLComment.m; path = src/OFXMLComment.m; sourceTree = ""; }; 4B4A61F212DF5EA20048F3F2 /* OFURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFURL.h; path = src/OFURL.h; sourceTree = SOURCE_ROOT; }; 4B4A61F312DF5EA20048F3F2 /* OFURL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFURL.m; path = src/OFURL.m; sourceTree = SOURCE_ROOT; }; 4B511B7A139C0A34003764A5 /* OFNull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFNull.h; path = src/OFNull.h; sourceTree = ""; }; 4B511B7B139C0A34003764A5 /* OFNull.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFNull.m; path = src/OFNull.m; sourceTree = ""; }; 4B55A0F9133ABEA900B58A93 /* OFThreadJoinFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFThreadJoinFailedException.h; path = src/exceptions/OFThreadJoinFailedException.h; sourceTree = ""; }; @@ -553,11 +566,10 @@ 4B6EF6781235358D0076B512 /* OFStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStreamTests.m; path = tests/OFStreamTests.m; sourceTree = SOURCE_ROOT; }; 4B6EF6791235358D0076B512 /* OFStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStringTests.m; path = tests/OFStringTests.m; sourceTree = SOURCE_ROOT; }; 4B6EF67A1235358D0076B512 /* OFTCPSocketTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFTCPSocketTests.m; path = tests/OFTCPSocketTests.m; sourceTree = SOURCE_ROOT; }; 4B6EF67B1235358D0076B512 /* OFThreadTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFThreadTests.m; path = tests/OFThreadTests.m; sourceTree = SOURCE_ROOT; }; 4B6EF67C1235358D0076B512 /* OFXMLElementBuilderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLElementBuilderTests.m; path = tests/OFXMLElementBuilderTests.m; sourceTree = SOURCE_ROOT; }; - 4B6EF67D1235358D0076B512 /* OFXMLElementTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLElementTests.m; path = tests/OFXMLElementTests.m; sourceTree = SOURCE_ROOT; }; 4B6EF67E1235358D0076B512 /* OFXMLParserTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLParserTests.m; path = tests/OFXMLParserTests.m; sourceTree = SOURCE_ROOT; }; 4B6EF67F1235358D0076B512 /* PropertiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PropertiesTests.m; path = tests/PropertiesTests.m; sourceTree = SOURCE_ROOT; }; 4B6EF6801235358D0076B512 /* TestsAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestsAppDelegate.h; path = tests/TestsAppDelegate.h; sourceTree = SOURCE_ROOT; }; 4B6EF6811235358D0076B512 /* TestsAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestsAppDelegate.m; path = tests/TestsAppDelegate.m; sourceTree = SOURCE_ROOT; }; 4B6EF684123535B60076B512 /* TestPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestPlugin.m; path = tests/plugin/TestPlugin.m; sourceTree = SOURCE_ROOT; }; @@ -974,10 +986,16 @@ 4B6799841099E7C50041064A /* OFThread.m */, 4B4A61F212DF5EA20048F3F2 /* OFURL.h */, 4B4A61F312DF5EA20048F3F2 /* OFURL.m */, 4BF1BCCE11C9663F0025511F /* OFXMLAttribute.h */, 4BF1BCCF11C9663F0025511F /* OFXMLAttribute.m */, + 4B49EA67143B3A090005BBC6 /* OFXMLCDATA.h */, + 4B49EA68143B3A090005BBC6 /* OFXMLCDATA.m */, + 4B49EA69143B3A090005BBC6 /* OFXMLCharacters.h */, + 4B49EA6A143B3A090005BBC6 /* OFXMLCharacters.m */, + 4B49EA6B143B3A090005BBC6 /* OFXMLComment.h */, + 4B49EA6C143B3A090005BBC6 /* OFXMLComment.m */, 4B6799871099E7C50041064A /* OFXMLElement.h */, 4B6799881099E7C50041064A /* OFXMLElement.m */, 4BB25E86139C388A00F574EA /* OFXMLElement+Serialization.h */, 4BB25E87139C388A00F574EA /* OFXMLElement+Serialization.m */, 4B0D249411DFAA3D00ED6FFC /* OFXMLElementBuilder.h */, @@ -1032,11 +1050,11 @@ 4B6EF6791235358D0076B512 /* OFStringTests.m */, 4B6EF67A1235358D0076B512 /* OFTCPSocketTests.m */, 4B6EF67B1235358D0076B512 /* OFThreadTests.m */, 4BF0749512DFAFCA00A4ADD1 /* OFURLTests.m */, 4B6EF67C1235358D0076B512 /* OFXMLElementBuilderTests.m */, - 4B6EF67D1235358D0076B512 /* OFXMLElementTests.m */, + 4B49EA65143B39CE0005BBC6 /* OFXMLNodeTests.m */, 4B6EF67E1235358D0076B512 /* OFXMLParserTests.m */, 4B6EF67F1235358D0076B512 /* PropertiesTests.m */, 4B6EF6801235358D0076B512 /* TestsAppDelegate.h */, 4B6EF6811235358D0076B512 /* TestsAppDelegate.m */, ); @@ -1140,10 +1158,13 @@ 4B3D23DC1337FCB000DD29B8 /* OFString+XMLUnescaping.h in Headers */, 4B3D23DD1337FCB000DD29B8 /* OFTCPSocket.h in Headers */, 4B3D23DE1337FCB000DD29B8 /* OFThread.h in Headers */, 4B3D23DF1337FCB000DD29B8 /* OFURL.h in Headers */, 4B3D23E01337FCB000DD29B8 /* OFXMLAttribute.h in Headers */, + 4B49EA6D143B3A090005BBC6 /* OFXMLCDATA.h in Headers */, + 4B49EA6F143B3A090005BBC6 /* OFXMLCharacters.h in Headers */, + 4B49EA71143B3A090005BBC6 /* OFXMLComment.h in Headers */, 4B3D23E11337FCB000DD29B8 /* OFXMLElement.h in Headers */, 4BB25E8C139C388A00F574EA /* OFXMLElement+Serialization.h in Headers */, 4B3D23E21337FCB000DD29B8 /* OFXMLElementBuilder.h in Headers */, 4B11005C14329B9A003A45D8 /* OFXMLNode.h in Headers */, 4B3D23E31337FCB000DD29B8 /* OFXMLParser.h in Headers */, @@ -1427,10 +1448,13 @@ 4B3D23AA1337FC0D00DD29B8 /* OFString+XMLUnescaping.m in Sources */, 4B3D23AB1337FC0D00DD29B8 /* OFTCPSocket.m in Sources */, 4B3D23AC1337FC0D00DD29B8 /* OFThread.m in Sources */, 4B3D23AD1337FC0D00DD29B8 /* OFURL.m in Sources */, 4B3D23AE1337FC0D00DD29B8 /* OFXMLAttribute.m in Sources */, + 4B49EA6E143B3A090005BBC6 /* OFXMLCDATA.m in Sources */, + 4B49EA70143B3A090005BBC6 /* OFXMLCharacters.m in Sources */, + 4B49EA72143B3A090005BBC6 /* OFXMLComment.m in Sources */, 4B3D23AF1337FC0D00DD29B8 /* OFXMLElement.m in Sources */, 4BB25E8D139C388A00F574EA /* OFXMLElement+Serialization.m in Sources */, 4B3D23B01337FC0D00DD29B8 /* OFXMLElementBuilder.m in Sources */, 4B11005D14329B9A003A45D8 /* OFXMLNode.m in Sources */, 4B3D23B11337FC0D00DD29B8 /* OFXMLParser.m in Sources */, @@ -1516,11 +1540,11 @@ 4BF33B0A133807A20059CEF7 /* OFStringTests.m in Sources */, 4BF33B0B133807A20059CEF7 /* OFTCPSocketTests.m in Sources */, 4BF33B0C133807A20059CEF7 /* OFThreadTests.m in Sources */, 4BF33B0D133807A20059CEF7 /* OFURLTests.m in Sources */, 4BF33B0E133807A20059CEF7 /* OFXMLElementBuilderTests.m in Sources */, - 4BF33B0F133807A20059CEF7 /* OFXMLElementTests.m in Sources */, + 4B49EA66143B39CE0005BBC6 /* OFXMLNodeTests.m in Sources */, 4BF33B10133807A20059CEF7 /* OFXMLParserTests.m in Sources */, 4BF33B11133807A20059CEF7 /* PropertiesTests.m in Sources */, 4BF33B12133807A20059CEF7 /* TestsAppDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -52,10 +52,13 @@ OFString+XMLUnescaping.m \ OFTCPSocket.m \ ${OFTHREAD_M} \ OFURL.m \ OFXMLAttribute.m \ + OFXMLCDATA.m \ + OFXMLCharacters.m \ + OFXMLComment.m \ OFXMLElement.m \ OFXMLElement+Serialization.m \ OFXMLElementBuilder.m \ OFXMLNode.m \ OFXMLParser.m \ Index: src/OFArray_adjacent.m ================================================================== --- src/OFArray_adjacent.m +++ src/OFArray_adjacent.m @@ -191,20 +191,16 @@ ![[element namespace] isEqual: OF_SERIALIZATION_NS]) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; - enumerator = [[element children] objectEnumerator]; + enumerator = [[element elementsForNamespace: + OF_SERIALIZATION_NS] objectEnumerator]; pool2 = [[OFAutoreleasePool alloc] init]; while ((child = [enumerator nextObject]) != nil) { - id object; - - if (![[child namespace] isEqual: OF_SERIALIZATION_NS]) - continue; - - object = [child objectByDeserializing]; + id object = [child objectByDeserializing]; [array addItem: &object]; [object retain]; [pool2 releaseObjects]; } Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -49,17 +49,15 @@ ![[element namespace] isEqual: OF_SERIALIZATION_NS]) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; - enumerator = [[element children] objectEnumerator]; + enumerator = [[element elementsForNamespace: + OF_SERIALIZATION_NS] objectEnumerator]; pool2 = [[OFAutoreleasePool alloc] init]; while ((child = [enumerator nextObject]) != nil) { - if (![[child namespace] isEqual: OF_SERIALIZATION_NS]) - continue; - [self appendObject: [child objectByDeserializing]]; [pool2 releaseObjects]; } Index: src/OFSet_hashtable.m ================================================================== --- src/OFSet_hashtable.m +++ src/OFSet_hashtable.m @@ -144,17 +144,15 @@ exceptionWithClass: isa selector: _cmd]; one = [OFNumber numberWithSize: 1]; - enumerator = [[element children] objectEnumerator]; + enumerator = [[element elementsForNamespace: + OF_SERIALIZATION_NS] objectEnumerator]; pool2 = [[OFAutoreleasePool alloc] init]; while ((child = [enumerator nextObject]) != nil) { - if (![[child namespace] isEqual: OF_SERIALIZATION_NS]) - continue; - [dictionary _setObject: one forKey: [child objectByDeserializing] copyKey: NO]; [pool2 releaseObjects]; Index: src/OFXMLAttribute.m ================================================================== --- src/OFXMLAttribute.m +++ src/OFXMLAttribute.m @@ -163,6 +163,13 @@ [pool release]; [element autorelease]; return element; } + +- (OFString*)description +{ + return [OFString stringWithFormat: @"", + name, ns, stringValue]; +} @end ADDED src/OFXMLCDATA.h Index: src/OFXMLCDATA.h ================================================================== --- src/OFXMLCDATA.h +++ src/OFXMLCDATA.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFXMLNode.h" + +/** + * \brief A class representing XML CDATA. + */ +@interface OFXMLCDATA: OFXMLNode +{ + OFString *CDATA; +} + +/** + * \brief Creates a new OFXMLCDATA with the specified string. + * + * \param string The string value for the CDATA + * \return A new OFXMLCDATA + */ ++ CDATAWithString: (OFString*)string; + +/** + * \brief Initializes an alredy allocated OFXMLCDATA with the specified string. + * + * \param string The string value for the CDATA + * \return An initialized OFXMLCDATA + */ +- initWithString: (OFString*)string; +@end ADDED src/OFXMLCDATA.m Index: src/OFXMLCDATA.m ================================================================== --- src/OFXMLCDATA.m +++ src/OFXMLCDATA.m @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFXMLCDATA.h" +#import "OFString.h" +#import "OFXMLElement.h" +#import "OFAutoreleasePool.h" + +#import "OFInvalidArgumentException.h" + +@implementation OFXMLCDATA ++ CDATAWithString: (OFString*)string +{ + return [[[self alloc] initWithString: string] autorelease]; +} + +- initWithString: (OFString*)string +{ + self = [super init]; + + @try { + CDATA = [string copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- initWithSerialization: (OFXMLElement*)element +{ + self = [super init]; + + @try { + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + + if (![[element name] isEqual: [self className]] || + ![[element namespace] isEqual: OF_SERIALIZATION_NS]) + @throw [OFInvalidArgumentException + exceptionWithClass: isa + selector: _cmd]; + + CDATA = [[element stringValue] copy]; + + [pool release]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (BOOL)isEqual: (id)object +{ + OFXMLCDATA *otherCDATA; + + if (![object isKindOfClass: [OFXMLCDATA class]]) + return NO; + + otherCDATA = object; + + return ([otherCDATA->CDATA isEqual: CDATA]); +} + +- (uint32_t)hash +{ + return [CDATA hash]; +} + +- (OFString*)stringValue +{ + return [[CDATA copy] autorelease]; +} + +- (OFString*)XMLString +{ + return [OFString stringWithFormat: @"", CDATA]; +} + +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation +{ + return [OFString stringWithFormat: @"", CDATA]; +} + +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation + level: (unsigned int)level +{ + return [OFString stringWithFormat: @"", CDATA]; +} + +- (OFString*)description +{ + return [OFString stringWithFormat: @"", CDATA]; +} + +- (OFXMLElement*)XMLElementBySerializing +{ + OFXMLElement *element = + [OFXMLElement elementWithName: [self className] + namespace: OF_SERIALIZATION_NS]; + [element addChild: self]; + + return element; +} +@end ADDED src/OFXMLCharacters.h Index: src/OFXMLCharacters.h ================================================================== --- src/OFXMLCharacters.h +++ src/OFXMLCharacters.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFXMLNode.h" + +/** + * \brief A class representing XML characters. + */ +@interface OFXMLCharacters: OFXMLNode +{ + OFString *characters; +} + +/** + * \brief Creates a new OFXMLCharacters with the specified string. + * + * \param string The string value for the characters + * \return A new OFXMLCharacters + */ ++ charactersWithString: (OFString*)string; + +/** + * \brief Initializes an already allocated OFXMLCharacters with the specified + * string. + * + * \param string The string value for the characters + * \return An initialized OFXMLCharacters + */ +- initWithString: (OFString*)string; +@end ADDED src/OFXMLCharacters.m Index: src/OFXMLCharacters.m ================================================================== --- src/OFXMLCharacters.m +++ src/OFXMLCharacters.m @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFXMLCharacters.h" +#import "OFString.h" +#import "OFXMLElement.h" +#import "OFAutoreleasePool.h" + +#import "OFInvalidArgumentException.h" + +@implementation OFXMLCharacters ++ charactersWithString: (OFString*)string +{ + return [[[self alloc] initWithString: string] autorelease]; +} + +- initWithString: (OFString*)string +{ + self = [super init]; + + @try { + characters = [string copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- initWithSerialization: (OFXMLElement*)element +{ + self = [super init]; + + @try { + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + + if (![[element name] isEqual: [self className]] || + ![[element namespace] isEqual: OF_SERIALIZATION_NS]) + @throw [OFInvalidArgumentException + exceptionWithClass: isa + selector: _cmd]; + + characters = [[element stringValue] copy]; + + [pool release]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (BOOL)isEqual: (id)object +{ + OFXMLCharacters *otherCharacters; + + if (![object isKindOfClass: [OFXMLCharacters class]]) + return NO; + + otherCharacters = object; + + return ([otherCharacters->characters isEqual: characters]); +} + +- (uint32_t)hash +{ + return [characters hash]; +} + +- (OFString*)stringValue +{ + return [[characters copy] autorelease]; +} + +- (OFString*)XMLString +{ + return [characters stringByXMLEscaping]; +} + +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation +{ + return [characters stringByXMLEscaping]; +} + +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation + level: (unsigned int)level +{ + return [characters stringByXMLEscaping]; +} + +- (OFString*)description +{ + return [characters stringByXMLEscaping]; +} + +- (OFXMLElement*)XMLElementBySerializing +{ + return [OFXMLElement elementWithName: [self className] + namespace: OF_SERIALIZATION_NS + stringValue: characters]; +} +@end ADDED src/OFXMLComment.h Index: src/OFXMLComment.h ================================================================== --- src/OFXMLComment.h +++ src/OFXMLComment.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFXMLNode.h" + +/** + * \brief A class for representing XML comments. + */ +@interface OFXMLComment: OFXMLNode +{ + OFString *comment; +} + +/** + * \brief Creates a new OFXMLComment with the specified string. + * + * \param string The string for the comment + * \return A new OFXMLComment + */ ++ commentWithString: (OFString*)string; + +/** + * \brief Initializes an already allocated OFXMLComment with the specified + * string. + * + * \param string The string for the comment + * \return An initialized OFXMLComment + */ +- initWithString: (OFString*)string; +@end ADDED src/OFXMLComment.m Index: src/OFXMLComment.m ================================================================== --- src/OFXMLComment.m +++ src/OFXMLComment.m @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFXMLComment.h" +#import "OFString.h" +#import "OFXMLElement.h" +#import "OFAutoreleasePool.h" + +#import "OFInvalidArgumentException.h" + +@implementation OFXMLComment ++ commentWithString: (OFString*)string +{ + return [[[self alloc] initWithString: string] autorelease]; +} + +- initWithString: (OFString*)string +{ + self = [super init]; + + @try { + comment = [string copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- initWithSerialization: (OFXMLElement*)element +{ + self = [super init]; + + @try { + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + + if (![[element name] isEqual: [self className]] || + ![[element namespace] isEqual: OF_SERIALIZATION_NS]) + @throw [OFInvalidArgumentException + exceptionWithClass: isa + selector: _cmd]; + + comment = [[element stringValue] copy]; + + [pool release]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (BOOL)isEqual: (id)object +{ + OFXMLComment *otherComment; + + if (![object isKindOfClass: [OFXMLComment class]]) + return NO; + + otherComment = object; + + return ([otherComment->comment isEqual: comment]); +} + +- (uint32_t)hash +{ + return [comment hash]; +} + +- (OFString*)stringValue +{ + return @""; +} + +- (OFString*)XMLString +{ + return [OFString stringWithFormat: @"", comment]; +} + +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation +{ + return [OFString stringWithFormat: @"", comment]; +} + +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation + level: (unsigned int)level +{ + OFString *ret; + + if (indentation > 0 && level > 0) { + char *whitespaces = [self allocMemoryWithSize: + (level * indentation) + 1]; + memset(whitespaces, ' ', level * indentation); + whitespaces[level * indentation] = 0; + + @try { + ret = [OFString stringWithFormat: @"%s", + whitespaces, + comment]; + } @finally { + [self freeMemory: whitespaces]; + } + } else + ret = [OFString stringWithFormat: @"", comment]; + + return ret; +} + +- (OFString*)description +{ + return [OFString stringWithFormat: @"", comment]; +} + +- (OFXMLElement*)XMLElementBySerializing +{ + return [OFXMLElement elementWithName: [self className] + namespace: OF_SERIALIZATION_NS + stringValue: comment]; +} +@end Index: src/OFXMLElement.h ================================================================== --- src/OFXMLElement.h +++ src/OFXMLElement.h @@ -32,13 +32,10 @@ OFString *ns; OFString *defaultNamespace; OFMutableArray *attributes; OFMutableDictionary *namespaces; OFMutableArray *children; - OFString *characters; - OFString *CDATA; - OFString *comment; } #ifdef OF_HAVE_PROPERTIES @property (copy) OFString *name; @property (copy, getter=namespace, setter=setNamespace:) OFString *ns; @@ -89,35 +86,10 @@ */ + elementWithName: (OFString*)name namespace: (OFString*)ns stringValue: (OFString*)stringValue; -/** - * \brief Creates a new element with the specified characters. - * - * \param characters The characters the element represents - * \return A new autoreleased OFXMLElement consisting of the specified - * characters - */ -+ elementWithCharacters: (OFString*)characters; - -/** - * \brief Creates a new element with the specified CDATA. - * - * \param CDATA The CDATA the element represents - * \return A new autoreleased OFXMLElement consisting of the specified CDATA - */ -+ elementWithCDATA: (OFString*)CDATA; - -/** - * \brief Creates a new element with the specified comment. - * - * \param comment The comment the element represents - * \return A new autoreleased OFXMLElement consisting of the specified comment - */ -+ elementWithComment: (OFString*)comment; - /** * \brief Creates a new element with the specified element. * * \param element An OFXMLElement to initialize the OFXMLElement with * \return A new autoreleased OFXMLElement with the contents of the specified @@ -186,37 +158,10 @@ */ - initWithName: (OFString*)name namespace: (OFString*)ns stringValue: (OFString*)stringValue; -/** - * \brief Initializes an already allocated OFXMLElement with the specified - * characters. - * - * \param characters The characters the element represents - * \return An initialized OFXMLElement consisting of the specified characters - */ -- initWithCharacters: (OFString*)characters; - -/** - * \brief Initializes an already allocated OFXMLElement with the specified - * CDATA. - * - * \param CDATA The CDATA the element represents - * \return An initialized OFXMLElement consisting of the specified CDATA - */ -- initWithCDATA: (OFString*)CDATA; - -/** - * \brief Initializes an already allocated OFXMLElement with the specified - * comment. - * - * \param comment The comment the element represents - * \return An initialized OFXMLElement consisting of the specified comment - */ -- initWithComment: (OFString*)comment; - /** * \brief Initializes an already allocated OFXMLElement with the specified * element. * * \param element An OFXMLElement to initialize the OFXMLElement with @@ -398,20 +343,20 @@ - (void)setDefaultNamespace: (OFString*)ns; /** * \brief Adds a child to the OFXMLElement. * - * \param child Another OFXMLElement which is added as a child + * \param child An OFXMLNode which is added as a child */ -- (void)addChild: (OFXMLElement*)child; +- (void)addChild: (OFXMLNode*)child; /** * \brief Removes the first child that is equal to the specified OFXMLElement. * * \param child The child to remove from the OFXMLElement */ -- (void)removeChild: (OFXMLElement*)child; +- (void)removeChild: (OFXMLNode*)child; /** * \brief Returns all children that are elements. * * \return All children that are elements Index: src/OFXMLElement.m ================================================================== --- src/OFXMLElement.m +++ src/OFXMLElement.m @@ -23,10 +23,12 @@ #import "OFString.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFDataArray.h" #import "OFXMLAttribute.h" +#import "OFXMLCharacters.h" +#import "OFXMLCDATA.h" #import "OFXMLParser.h" #import "OFXMLElementBuilder.h" #import "OFAutoreleasePool.h" #import "OFInvalidArgumentException.h" @@ -40,10 +42,13 @@ /* References for static linking */ void _references_to_categories_of_OFXMLElement(void) { _OFXMLElement_Serialization_reference = 1; } + +static Class charactersClass = Nil; +static Class CDATAClass = Nil; @interface OFXMLElement_OFXMLElementBuilderDelegate: OFObject { @public OFXMLElement *element; @@ -52,18 +57,12 @@ @implementation OFXMLElement_OFXMLElementBuilderDelegate - (void)elementBuilder: (OFXMLElementBuilder*)builder didBuildElement: (OFXMLElement*)element_ { - /* - * Make sure we don't take whitespaces before or after the root element - * into account. - */ - if ([element_ name] != nil) { - assert(element == nil); + if (element == nil) element = [element_ retain]; - } } - (void)dealloc { [element release]; @@ -71,10 +70,18 @@ [super dealloc]; } @end @implementation OFXMLElement ++ (void)initialize +{ + if (self == [OFXMLElement class]) { + charactersClass = [OFXMLCharacters class]; + CDATAClass = [OFXMLCDATA class]; + } +} + + elementWithName: (OFString*)name { return [[[self alloc] initWithName: name] autorelease]; } @@ -99,25 +106,10 @@ return [[[self alloc] initWithName: name namespace: ns stringValue: stringValue] autorelease]; } -+ elementWithCharacters: (OFString*)characters -{ - return [[[self alloc] initWithCharacters: characters] autorelease]; -} - -+ elementWithCDATA: (OFString*)CDATA -{ - return [[[self alloc] initWithCDATA: CDATA] autorelease]; -} - -+ elementWithComment: (OFString*)comment -{ - return [[[self alloc] initWithComment: comment] autorelease]; -} - + elementWithElement: (OFXMLElement*)element { return [[[self alloc] initWithElement: element] autorelease]; } @@ -190,67 +182,10 @@ } return self; } -- initWithCharacters: (OFString*)characters_ -{ - self = [super init]; - - @try { - if (characters_ == nil) - @throw [OFInvalidArgumentException - exceptionWithClass: isa - selector: _cmd]; - - characters = [characters_ copy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- initWithCDATA: (OFString*)CDATA_ -{ - self = [super init]; - - @try { - if (CDATA_ == nil) - @throw [OFInvalidArgumentException - exceptionWithClass: isa - selector: _cmd]; - - CDATA = [CDATA_ copy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- initWithComment: (OFString*)comment_ -{ - self = [super init]; - - @try { - if (comment_ == nil) - @throw [OFInvalidArgumentException - exceptionWithClass: isa - selector: _cmd]; - - comment = [comment_ copy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - - initWithElement: (OFXMLElement*)element { self = [super init]; @try { @@ -263,13 +198,10 @@ ns = [element->ns copy]; defaultNamespace = [element->defaultNamespace copy]; attributes = [element->attributes mutableCopy]; namespaces = [element->namespaces mutableCopy]; children = [element->children mutableCopy]; - characters = [element->characters copy]; - CDATA = [element->CDATA copy]; - comment = [element->comment copy]; } @catch (id e) { [self release]; @throw e; } @@ -366,19 +298,10 @@ name = [[[element attributeForName: @"name"] stringValue] copy]; ns = [[[element attributeForName: @"namespace"] stringValue] copy]; defaultNamespace = [[[element attributeForName: @"defaultNamespace"] stringValue] copy]; - characters = [[[element - elementForName: @"characters" - namespace: OF_SERIALIZATION_NS] stringValue] copy]; - CDATA = [[[element - elementForName: @"CDATA" - namespace: OF_SERIALIZATION_NS] stringValue] copy]; - comment = [[[element - elementForName: @"comment" - namespace: OF_SERIALIZATION_NS] stringValue] copy]; attributesElement = [[[element elementForName: @"attributes" namespace: OF_SERIALIZATION_NS] elementsForNamespace: OF_SERIALIZATION_NS] firstObject]; @@ -393,14 +316,11 @@ attributes = [[attributesElement objectByDeserializing] copy]; namespaces = [[namespacesElement objectByDeserializing] copy]; children = [[childrenElement objectByDeserializing] copy]; - if (!((name != nil || ns != nil || defaultNamespace != nil || - [attributes count] > 0 || [namespaces count] > 0 || - [children count] > 0) ^ (characters != nil) ^ - (CDATA != nil) ^ (comment != nil))) + if (name == nil) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; [pool release]; @@ -412,11 +332,11 @@ return self; } - (void)setName: (OFString*)name_ { - if (name == nil) + if (name_ == nil) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; OF_SETTER(name, name_, YES, YES) } @@ -426,14 +346,10 @@ return [[name copy] autorelease]; } - (void)setNamespace: (OFString*)ns_ { - if (name == nil) - @throw [OFInvalidArgumentException exceptionWithClass: isa - selector: _cmd]; - OF_SETTER(ns, ns_, YES, YES) } - (OFString*)namespace { @@ -460,11 +376,11 @@ - (void)setStringValue: (OFString*)stringValue { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; [self setChildren: [OFArray arrayWithObject: - [OFXMLElement elementWithCharacters: stringValue]]]; + [OFXMLCharacters charactersWithString: stringValue]]]; [pool release]; } - (OFString*)stringValue @@ -480,18 +396,12 @@ ret = [OFMutableString string]; cArray = [children cArray]; pool = [[OFAutoreleasePool alloc] init]; for (i = 0; i < count; i++) { - if (cArray[i]->characters != nil) - [ret appendString: cArray[i]->characters]; - else if (cArray[i]->CDATA != nil) - [ret appendString: cArray[i]->CDATA]; - else if (cArray[i]->comment == nil) { - [ret appendString: [cArray[i] stringValue]]; - [pool releaseObjects]; - } + [ret appendString: [cArray[i] stringValue]]; + [pool releaseObjects]; } [ret makeImmutable]; [pool release]; @@ -500,47 +410,20 @@ } - (OFString*)_XMLStringWithParent: (OFXMLElement*)parent namespaces: (OFDictionary*)allNamespaces indentation: (unsigned int)indentation - level: (size_t)level + level: (unsigned int)level { OFAutoreleasePool *pool, *pool2; char *cString; size_t length, i, j, attributesCount; OFString *prefix, *parentPrefix; OFXMLAttribute **attributesCArray; OFString *ret; OFString *defaultNS; - if (characters != nil) - return [characters stringByXMLEscaping]; - - if (CDATA != nil) - return [OFString stringWithFormat: @"", CDATA]; - - if (comment != nil) { - if (indentation > 0 && level > 0) { - char *whitespaces = [self - allocMemoryWithSize: (level * indentation) + 1]; - memset(whitespaces, ' ', level * indentation); - whitespaces[level * indentation] = 0; - - @try { - ret = [OFString - stringWithFormat: @"%s", - whitespaces, comment]; - } @finally { - [self freeMemory: whitespaces]; - } - } else - ret = [OFString stringWithFormat: @"", - comment]; - - return ret; - } - pool = [[OFAutoreleasePool alloc] init]; parentPrefix = [allNamespaces objectForKey: (parent != nil && parent->ns != nil ? parent->ns : (OFString*)@"")]; @@ -680,30 +563,37 @@ if (indentation > 0) { indent = YES; for (j = 0; j < childrenCount; j++) { - if (childrenCArray[j]->characters != nil || - childrenCArray[j]->CDATA != nil) { + if (childrenCArray[j]->isa == charactersClass || + childrenCArray[j]->isa == CDATAClass) { indent = NO; break; } } } else indent = NO; for (j = 0; j < childrenCount; j++) { OFString *child; + unsigned int ind = (indent ? indentation : 0); - if (indent) + if (ind) [tmp addItem: "\n"]; - child = [childrenCArray[j] - _XMLStringWithParent: self - namespaces: allNamespaces - indentation: (indent ? indentation : 0) - level: level + 1]; + if ([childrenCArray[j] isKindOfClass: + [OFXMLElement class]]) + child = [childrenCArray[j] + _XMLStringWithParent: self + namespaces: allNamespaces + indentation: ind + level: level + 1]; + else + child = [childrenCArray[j] + XMLStringWithIndentation: ind + level: level + 1]; [tmp addNItems: [child UTF8StringLength] fromCArray: [child UTF8String]]; } @@ -779,10 +669,19 @@ return [self _XMLStringWithParent: nil namespaces: nil indentation: indentation level: 0]; } + +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation + level: (unsigned int)level +{ + return [self _XMLStringWithParent: nil + namespaces: nil + indentation: indentation + level: level]; +} - (OFXMLElement*)XMLElementBySerializing { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFXMLElement *element; @@ -832,43 +731,19 @@ 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) { - OFXMLElement *CDATAElement = - [OFXMLElement elementWithName: @"CDATA" - namespace: OF_SERIALIZATION_NS]; - [CDATAElement addChild: [OFXMLElement elementWithCDATA: CDATA]]; - [element addChild: CDATAElement]; - } - - if (comment != nil) - [element addChild: - [OFXMLElement elementWithName: @"comment" - namespace: OF_SERIALIZATION_NS - stringValue: comment]]; - [element retain]; [pool release]; [element autorelease]; return element; } - (void)addAttribute: (OFXMLAttribute*)attribute { - if (name == nil) - @throw [OFInvalidArgumentException exceptionWithClass: isa - selector: _cmd]; - if (attributes == nil) attributes = [[OFMutableArray alloc] init]; if ([self attributeForName: attribute->name namespace: attribute->ns] == nil) @@ -885,20 +760,16 @@ - (void)addAttributeWithName: (OFString*)name_ namespace: (OFString*)ns_ stringValue: (OFString*)stringValue { - OFAutoreleasePool *pool; + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - if (name == nil) - @throw [OFInvalidArgumentException exceptionWithClass: isa - selector: _cmd]; - - pool = [[OFAutoreleasePool alloc] init]; [self addAttribute: [OFXMLAttribute attributeWithName: name_ namespace: ns_ stringValue: stringValue]]; + [pool release]; } - (OFXMLAttribute*)attributeForName: (OFString*)attributeName { @@ -970,11 +841,11 @@ } - (void)setPrefix: (OFString*)prefix forNamespace: (OFString*)ns_ { - if (name == nil || prefix == nil || [prefix isEqual: @""]) + if (prefix == nil || [prefix isEqual: @""]) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; if (ns_ == nil) ns_ = @""; @@ -992,43 +863,33 @@ stringValue: ns_]; } - (OFString*)defaultNamespace { - if (name == nil) - @throw [OFInvalidArgumentException exceptionWithClass: isa - selector: _cmd]; - - return [[defaultNamespace retain] autorelease]; + OF_GETTER(defaultNamespace, YES) } - (void)setDefaultNamespace: (OFString*)ns_ { - if (name == nil) - @throw [OFInvalidArgumentException exceptionWithClass: isa - selector: _cmd]; - - OFString *old = defaultNamespace; - defaultNamespace = [ns_ copy]; - [old release]; + OF_SETTER(defaultNamespace, ns_, YES, YES) } -- (void)addChild: (OFXMLElement*)child +- (void)addChild: (OFXMLNode*)child { - if (name == nil) + if ([child isKindOfClass: [OFXMLAttribute class]]) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; if (children == nil) children = [[OFMutableArray alloc] init]; [children addObject: child]; } -- (void)removeChild: (OFXMLElement*)child +- (void)removeChild: (OFXMLNode*)child { - if (name == nil) + if ([child isKindOfClass: [OFXMLAttribute class]]) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; [children removeObject: child]; } @@ -1050,11 +911,11 @@ OFMutableArray *ret = [OFMutableArray array]; OFXMLElement **cArray = [children cArray]; size_t i, count = [children count]; for (i = 0; i < count; i++) - if (cArray[i]->name != nil) + if ([cArray[i] isKindOfClass: [OFXMLElement class]]) [ret addObject: cArray[i]]; [ret makeImmutable]; return ret; @@ -1065,11 +926,12 @@ OFMutableArray *ret = [OFMutableArray array]; OFXMLElement **cArray = [children cArray]; size_t i, count = [children count]; for (i = 0; i < count; i++) - if (cArray[i]->ns == nil && + if ([cArray[i] isKindOfClass: [OFXMLElement class]] && + cArray[i]->ns == nil && [cArray[i]->name isEqual: elementName]) [ret addObject: cArray[i]]; [ret makeImmutable]; @@ -1081,11 +943,12 @@ OFMutableArray *ret = [OFMutableArray array]; OFXMLElement **cArray = [children cArray]; size_t i, count = [children count]; for (i = 0; i < count; i++) - if (cArray[i]->name != nil && + if ([cArray[i] isKindOfClass: [OFXMLElement class]] && + cArray[i]->name != nil && [cArray[i]->ns isEqual: elementNS]) [ret addObject: cArray[i]]; [ret makeImmutable]; @@ -1105,11 +968,12 @@ ret = [OFMutableArray array]; cArray = [children cArray]; count = [children count]; for (i = 0; i < count; i++) - if ([cArray[i]->ns isEqual: elementNS] && + if ([cArray[i] isKindOfClass: [OFXMLElement class]] && + [cArray[i]->ns isEqual: elementNS] && [cArray[i]->name isEqual: elementName]) [ret addObject: cArray[i]]; [ret makeImmutable]; @@ -1139,19 +1003,10 @@ ![otherElement->namespaces isEqual: namespaces]) return NO; if (otherElement->children != children && ![otherElement->children isEqual: children]) return NO; - if (otherElement->characters != characters && - ![otherElement->characters isEqual: characters]) - return NO; - if (otherElement->CDATA != CDATA && - ![otherElement->CDATA isEqual: CDATA]) - return NO; - if (otherElement->comment != comment && - ![otherElement->comment isEqual: comment]) - return NO; return YES; } - (uint32_t)hash @@ -1164,13 +1019,10 @@ OF_HASH_ADD_HASH(hash, [ns hash]); OF_HASH_ADD_HASH(hash, [defaultNamespace hash]); OF_HASH_ADD_HASH(hash, [attributes hash]); OF_HASH_ADD_HASH(hash, [namespaces hash]); OF_HASH_ADD_HASH(hash, [children hash]); - OF_HASH_ADD_HASH(hash, [characters hash]); - OF_HASH_ADD_HASH(hash, [CDATA hash]); - OF_HASH_ADD_HASH(hash, [comment hash]); OF_HASH_FINALIZE(hash); return hash; } @@ -1186,12 +1038,9 @@ [ns release]; [defaultNamespace release]; [attributes release]; [namespaces release]; [children release]; - [characters release]; - [CDATA release]; - [comment release]; [super dealloc]; } @end Index: src/OFXMLElementBuilder.h ================================================================== --- src/OFXMLElementBuilder.h +++ src/OFXMLElementBuilder.h @@ -44,10 +44,24 @@ didBuildElement: (OFXMLElement*)element; #ifdef OF_HAVE_OPTIONAL_PROTOCOLS @optional #endif + +/** + * \brief This callback is called when the OFXMLElementBuilder built an + * OFXMLNode which is not inside an element. + * + * This is usually called for comments or whitespace character data before the + * root element. + * + * \param builder The builder which built the OFXMLNode without parent + * \param node The OFXMLNode the OFXMLElementBuilder built + */ +- (void)elementBuilder: (OFXMLElementBuilder*)builder + didBuildParentlessNode: (OFXMLNode*)node; + /** * \brief This callback is called when the OFXMLElementBuilder gets a close tag * which does not belong there. * * Most likely, the OFXMLElementBuilder was used to build XML only of a child Index: src/OFXMLElementBuilder.m ================================================================== --- src/OFXMLElementBuilder.m +++ src/OFXMLElementBuilder.m @@ -18,13 +18,16 @@ #define OF_XML_ELEMENT_BUILDER_M #import "OFXMLElementBuilder.h" #import "OFXMLElement.h" +#import "OFXMLAttribute.h" +#import "OFXMLCharacters.h" +#import "OFXMLCDATA.h" +#import "OFXMLComment.h" #import "OFXMLParser.h" #import "OFMutableArray.h" -#import "OFAutoreleasePool.h" #import "OFMalformedXMLException.h" #import "macros.h" @@ -75,22 +78,19 @@ didStartElement: (OFString*)name withPrefix: (OFString*)prefix namespace: (OFString*)ns attributes: (OFArray*)attributes { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFXMLElement *element; OFXMLAttribute **cArray; size_t i, count; - IMP addAttribute; element = [OFXMLElement elementWithName: name namespace: ns]; cArray = [attributes cArray]; count = [attributes count]; - addAttribute = [element methodForSelector: @selector(addAttribute:)]; for (i = 0; i < count; i++) { if ([cArray[i] namespace] == nil && [[cArray[i] name] isEqual: @"xmlns"]) continue; @@ -98,83 +98,78 @@ if ([[cArray[i] namespace] isEqual: @"http://www.w3.org/2000/xmlns/"]) [element setPrefix: [cArray[i] name] forNamespace: [cArray[i] stringValue]]; - addAttribute(element, @selector(addAttribute:), cArray[i]); + [element addAttribute: cArray[i]]; } [[stack lastObject] addChild: element]; [stack addObject: element]; - - [pool release]; } - (void)parser: (OFXMLParser*)parser didEndElement: (OFString*)name withPrefix: (OFString*)prefix namespace: (OFString*)ns { - if ([stack count] == 0) { + switch ([stack count]) { + case 0: [delegate elementBuilder: self didNotExpectCloseTag: name withPrefix: prefix namespace: ns]; return; - } - - if ([stack count] == 1) + case 1: [delegate elementBuilder: self didBuildElement: [stack firstObject]]; + break; + } [stack removeLastObject]; } - (void)parser: (OFXMLParser*)parser foundCharacters: (OFString*)characters { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFXMLElement *element = - [OFXMLElement elementWithCharacters: characters]; + OFXMLCharacters *node; + OFXMLElement *parent; + + node = [OFXMLCharacters charactersWithString: characters]; + parent = [stack lastObject]; - if ([stack count] == 0) - [delegate elementBuilder: self - didBuildElement: element]; + if (parent != nil) + [parent addChild: node]; else - [[stack lastObject] addChild: element]; - - [pool release]; + [delegate elementBuilder: self + didBuildParentlessNode: node]; } - (void)parser: (OFXMLParser*)parser foundCDATA: (OFString*)CDATA { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFXMLElement *element = [OFXMLElement elementWithCDATA: CDATA]; + OFXMLCDATA *node = [OFXMLCDATA CDATAWithString: CDATA]; + OFXMLElement *parent = [stack lastObject]; - if ([stack count] == 0) - [delegate elementBuilder: self - didBuildElement: element]; + if (parent != nil) + [parent addChild: node]; else - [[stack lastObject] addChild: element]; - - [pool release]; + [delegate elementBuilder: self + didBuildParentlessNode: node]; } - (void)parser: (OFXMLParser*)parser foundComment: (OFString*)comment { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFXMLElement *element = [OFXMLElement elementWithComment: comment]; + OFXMLComment *node = [OFXMLComment commentWithString: comment]; + OFXMLElement *parent = [stack lastObject]; - if ([stack count] == 0) - [delegate elementBuilder: self - didBuildElement: element]; + if (parent != nil) + [parent addChild: node]; else - [[stack lastObject] addChild: element]; - - [pool release]; + [delegate elementBuilder: self + didBuildParentlessNode: node]; } - (OFString*)parser: (OFXMLParser*)parser foundUnknownEntityNamed: (OFString*)entity { @@ -186,10 +181,15 @@ @implementation OFObject (OFXMLElementBuilderDelegate) - (void)elementBuilder: (OFXMLElementBuilder*)builder didBuildElement: (OFXMLElement*)elem { } + +- (void)elementBuilder: (OFXMLElementBuilder*)builder + didBuildParentlessNode: (OFXMLNode*)node +{ +} - (void)elementBuilder: (OFXMLElementBuilder*)builder didNotExpectCloseTag: (OFString*)name withPrefix: (OFString*)prefix namespace: (OFString*)ns Index: src/OFXMLNode.h ================================================================== --- src/OFXMLNode.h +++ src/OFXMLNode.h @@ -70,6 +70,18 @@ * \param indentation The indentation for the XML string * \return An OFString representing the OFXMLNode as an XML string with * indentation */ - (OFString*)XMLStringWithIndentation: (unsigned int)indentation; + +/** + * \brief Returns an OFString representing the OFXMLNode as an XML string with + * indentation for the specified level. + * + * \param indentation The indentation for the XML string + * \param level The level of indentation + * \return An OFString representing the OFXMLNode as an XML string with + * indentation + */ +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation + level: (unsigned int)level; @end Index: src/OFXMLNode.m ================================================================== --- src/OFXMLNode.m +++ src/OFXMLNode.m @@ -56,14 +56,22 @@ return [[self stringValue] doubleValue]; } - (OFString*)XMLString { - return [self XMLStringWithIndentation: 0]; + return [self XMLStringWithIndentation: 0 + level: 0]; +} + +- (OFString*)XMLStringWithIndentation: (unsigned int)indentation +{ + return [self XMLStringWithIndentation: 0 + level: 0]; } - (OFString*)XMLStringWithIndentation: (unsigned int)indentation + level: (unsigned int)level { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } @@ -78,9 +86,8 @@ selector: _cmd]; } - copy { - @throw [OFNotImplementedException exceptionWithClass: isa - selector: _cmd]; + return [self retain]; } @end Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -55,10 +55,14 @@ #import "OFMD5Hash.h" #import "OFSHA1Hash.h" #import "OFXMLAttribute.h" #import "OFXMLElement.h" +#import "OFXMLAttribute.h" +#import "OFXMLCharacters.h" +#import "OFXMLCDATA.h" +#import "OFXMLComment.h" #import "OFXMLParser.h" #import "OFXMLElementBuilder.h" #import "OFFloatVector.h" #import "OFFloatMatrix.h" Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -20,12 +20,12 @@ OFStreamTests.m \ OFStringTests.m \ OFTCPSocketTests.m \ ${OFTHREADTESTS_M} \ OFURLTests.m \ - OFXMLElementTests.m \ OFXMLElementBuilderTests.m \ + OFXMLNodeTests.m \ OFXMLParserTests.m \ ${PROPERTIESTESTS_M} \ TestsAppDelegate.m IOS_USER ?= mobile Index: tests/OFXMLElementBuilderTests.m ================================================================== --- tests/OFXMLElementBuilderTests.m +++ tests/OFXMLElementBuilderTests.m @@ -24,19 +24,26 @@ #import "OFAutoreleasePool.h" #import "TestsAppDelegate.h" static OFString *module = @"OFXMLElementBuilder"; -static OFXMLElement *elem[2]; +static OFXMLNode *nodes[2]; static size_t i = 0; @implementation TestsAppDelegate (OFXMLElementBuilderTests) - (void)elementBuilder: (OFXMLElementBuilder*)builder - didBuildElement: (OFXMLElement*)elem_ + didBuildElement: (OFXMLElement*)element +{ + assert(i == 0); + nodes[i++] = [element retain]; +} + +- (void)elementBuilder: (OFXMLElementBuilder*)builder + didBuildParentlessNode: (OFXMLNode*)node { - assert(i < 2); - elem[i++] = [elem_ retain]; + assert(i == 1); + nodes[i++] = [node retain]; } - (void)XMLElementBuilderTests { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; @@ -49,14 +56,15 @@ [p setDelegate: builder]; [builder setDelegate: self]; TEST(@"Building elements from parsed XML", R([p parseString: str]) && - elem[0] != nil && [[elem[0] XMLString] isEqual: str] && + nodes[0] != nil && [[nodes[0] XMLString] isEqual: str] && R([p parseString: @""]) && - elem[1] != nil && [[elem[1] XMLString] isEqual: @""]) + nodes[1] != nil && [[nodes[1] XMLString] isEqual: @""] && + i == 2) - [elem[0] release]; - [elem[1] release]; + [nodes[0] release]; + [nodes[1] release]; [pool drain]; } @end DELETED tests/OFXMLElementTests.m Index: tests/OFXMLElementTests.m ================================================================== --- tests/OFXMLElementTests.m +++ tests/OFXMLElementTests.m @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFXMLElement.h" -#import "OFString.h" -#import "OFArray.h" -#import "OFAutoreleasePool.h" - -#import "TestsAppDelegate.h" - -static OFString *module = @"OFXMLElement"; - -@implementation TestsAppDelegate (OFXMLElementTests) -- (void)XMLElementTests -{ - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFXMLElement *elem[4]; - OFArray *a; - - TEST(@"+[elementWithName:]", - (elem[0] = [OFXMLElement elementWithName: @"foo"]) && - [[elem[0] XMLString] isEqual: @""]) - - TEST(@"+[elementWithName:stringValue:]", - (elem[1] = [OFXMLElement elementWithName: @"foo" - stringValue: @"b&ar"]) && - [[elem[1] XMLString] isEqual: @"b&ar"]) - - TEST(@"+[elementWithName:namespace:]", - (elem[2] = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test"]) && - R([elem[2] addAttributeWithName: @"test" - stringValue: @"test"]) && - R([elem[2] setPrefix: @"objfw-test" - forNamespace: @"urn:objfw:test"]) && - [[elem[2] XMLString] isEqual: @""] && - (elem[3] = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test"]) && - R([elem[3] addAttributeWithName: @"test" - stringValue: @"test"]) && - [[elem[3] XMLString] isEqual: - @""]) - - TEST(@"+[elementWithName:namespace:stringValue:]", - (elem[3] = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test" - stringValue: @"x"]) && - R([elem[3] setPrefix: @"objfw-test" - forNamespace: @"urn:objfw:test"]) && - [[elem[3] XMLString] isEqual: - @"x"]) - - TEST(@"+[elementWithCharacters:]", - (elem[3] = [OFXMLElement elementWithCharacters: @""]) && - [[elem[3] XMLString] isEqual: @"<foo>"]) - - TEST(@"+[elementWithCDATA:]", - (elem[3] = [OFXMLElement elementWithCDATA: @""]) && - [[elem[3] XMLString] isEqual: @"]]>"]); - - TEST(@"+[elementWithComment:]", - (elem[3] = [OFXMLElement elementWithComment: @" comment "]) && - [[elem[3] XMLString] isEqual: @""]) - - TEST(@"-[addAttributeWithName:stringValue:]", - R([elem[0] addAttributeWithName: @"foo" - stringValue: @"b&ar"]) && - [[elem[0] XMLString] isEqual: @""] && - R([elem[1] addAttributeWithName: @"foo" - stringValue: @"b&ar"]) && - [[elem[1] XMLString] isEqual: - @"b&ar"]) - - TEST(@"-[setPrefix:forNamespace:]", - R([elem[1] setPrefix: @"objfw-test" - forNamespace: @"urn:objfw:test"])) - - TEST(@"-[addAttributeWithName:namespace:stringValue:]", - R([elem[1] addAttributeWithName: @"foo" - namespace: @"urn:objfw:test" - stringValue: @"bar"]) && - R([elem[1] addAttributeWithName: @"foo" - namespace: @"urn:objfw:test" - stringValue: @"ignored"]) && - [[elem[1] XMLString] isEqual: - @"b&ar"]) - - TEST(@"-[removeAttributeForName:namespace:]", - R([elem[1] removeAttributeForName: @"foo"]) && - [[elem[1] XMLString] isEqual: - @"b&ar"] && - R([elem[1] removeAttributeForName: @"foo" - namespace: @"urn:objfw:test"]) && - [[elem[1] XMLString] isEqual: @"b&ar"]) - - TEST(@"-[addChild:]", - R([elem[0] addChild: [OFXMLElement elementWithName: @"bar"]]) && - [[elem[0] XMLString] isEqual: - @""] && - R([elem[2] addChild: [OFXMLElement elementWithName: @"bar" - namespace: @"urn:objfw:test"]]) && - [[elem[2] XMLString] isEqual: - @""]) - - TEST(@"+[elementWithXMLString:] and -[stringValue]", - [[[OFXMLElement elementWithXMLString: - @"\r\nfoo" - @"bazqux"] stringValue] - isEqual: @"foobarbazqux"]) - - TEST(@"-[elementsForName:namespace:]", - (a = [elem[2] elementsForName: @"bar" - namespace: @"urn:objfw:test"]) && - [a count] == 1 && [[[a firstObject] XMLString] isEqual: - @""]) - - TEST(@"-[isEqual:]", - [[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 \n"]) - - [pool drain]; -} -@end ADDED tests/OFXMLNodeTests.m Index: tests/OFXMLNodeTests.m ================================================================== --- tests/OFXMLNodeTests.m +++ tests/OFXMLNodeTests.m @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFXMLElement.h" +#import "OFXMLCharacters.h" +#import "OFXMLCDATA.h" +#import "OFXMLComment.h" +#import "OFString.h" +#import "OFArray.h" +#import "OFAutoreleasePool.h" + +#import "TestsAppDelegate.h" + +static OFString *module = @"OFXMLNode"; + +@implementation TestsAppDelegate (OFXMLNodeTests) +- (void)XMLNodeTests +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + id nodes[4]; + OFArray *a; + + TEST(@"+[elementWithName:]", + (nodes[0] = [OFXMLElement elementWithName: @"foo"]) && + [[nodes[0] XMLString] isEqual: @""]) + + TEST(@"+[elementWithName:stringValue:]", + (nodes[1] = [OFXMLElement elementWithName: @"foo" + stringValue: @"b&ar"]) && + [[nodes[1] XMLString] isEqual: @"b&ar"]) + + TEST(@"+[elementWithName:namespace:]", + (nodes[2] = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test"]) && + R([nodes[2] addAttributeWithName: @"test" + stringValue: @"test"]) && + R([nodes[2] setPrefix: @"objfw-test" + forNamespace: @"urn:objfw:test"]) && + [[nodes[2] XMLString] isEqual: @""] && + (nodes[3] = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test"]) && + R([nodes[3] addAttributeWithName: @"test" + stringValue: @"test"]) && + [[nodes[3] XMLString] isEqual: + @""]) + + TEST(@"+[elementWithName:namespace:stringValue:]", + (nodes[3] = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test" + stringValue: @"x"]) && + R([nodes[3] setPrefix: @"objfw-test" + forNamespace: @"urn:objfw:test"]) && + [[nodes[3] XMLString] isEqual: + @"x"]) + + TEST(@"+[charactersWithString:]", + (nodes[3] = [OFXMLCharacters charactersWithString: @""]) && + [[nodes[3] XMLString] isEqual: @"<foo>"]) + + TEST(@"+[CDATAWithString:]", + (nodes[3] = [OFXMLCDATA CDATAWithString: @""]) && + [[nodes[3] XMLString] isEqual: @"]]>"]); + + TEST(@"+[commentWithString:]", + (nodes[3] = [OFXMLComment commentWithString: @" comment "]) && + [[nodes[3] XMLString] isEqual: @""]) + + module = @"OFXMLElement"; + + TEST(@"-[addAttributeWithName:stringValue:]", + R([nodes[0] addAttributeWithName: @"foo" + stringValue: @"b&ar"]) && + [[nodes[0] XMLString] isEqual: @""] && + R([nodes[1] addAttributeWithName: @"foo" + stringValue: @"b&ar"]) && + [[nodes[1] XMLString] isEqual: + @"b&ar"]) + + TEST(@"-[setPrefix:forNamespace:]", + R([nodes[1] setPrefix: @"objfw-test" + forNamespace: @"urn:objfw:test"])) + + TEST(@"-[addAttributeWithName:namespace:stringValue:]", + R([nodes[1] addAttributeWithName: @"foo" + namespace: @"urn:objfw:test" + stringValue: @"bar"]) && + R([nodes[1] addAttributeWithName: @"foo" + namespace: @"urn:objfw:test" + stringValue: @"ignored"]) && + [[nodes[1] XMLString] isEqual: + @"b&ar"]) + + TEST(@"-[removeAttributeForName:namespace:]", + R([nodes[1] removeAttributeForName: @"foo"]) && + [[nodes[1] XMLString] isEqual: + @"b&ar"] && + R([nodes[1] removeAttributeForName: @"foo" + namespace: @"urn:objfw:test"]) && + [[nodes[1] XMLString] isEqual: @"b&ar"]) + + TEST(@"-[addChild:]", + R([nodes[0] addChild: [OFXMLElement elementWithName: @"bar"]]) && + [[nodes[0] XMLString] isEqual: + @""] && + R([nodes[2] addChild: [OFXMLElement elementWithName: @"bar" + namespace: @"urn:objfw:test"]]) && + [[nodes[2] XMLString] isEqual: + @""]) + + TEST(@"+[elementWithXMLString:] and -[stringValue]", + [[[OFXMLElement elementWithXMLString: + @"\r\nfoo" + @"bazqux"] stringValue] + isEqual: @"foobarbazqux"]) + + TEST(@"-[elementsForName:namespace:]", + (a = [nodes[2] elementsForName: @"bar" + namespace: @"urn:objfw:test"]) && + [a count] == 1 && [[[a firstObject] XMLString] isEqual: + @""]) + + TEST(@"-[isEqual:]", + [[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 \n"]) + + [pool drain]; +} +@end Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -150,16 +150,16 @@ @interface TestsAppDelegate (OFURLTests) - (void)URLTests; @end -@interface TestsAppDelegate (OFXMLElementTests) -- (void)XMLElementTests; +@interface TestsAppDelegate (OFXMLElementBuilderTests) +- (void)XMLElementBuilderTests; @end -@interface TestsAppDelegate (OFXMLElementBuilderTests) -- (void)XMLElementBuilderTests; +@interface TestsAppDelegate (OFXMLNodeTests) +- (void)XMLNodeTests; @end @interface TestsAppDelegate (OFXMLParserTests) - (void)XMLParserTests; @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -135,11 +135,11 @@ [self URLTests]; #ifdef OF_THREADS [self HTTPRequestTests]; #endif [self XMLParserTests]; - [self XMLElementTests]; + [self XMLNodeTests]; [self XMLElementBuilderTests]; [self serializationTests]; #ifdef OF_PLUGINS [self pluginTests]; #endif Index: tests/serialization.xml ================================================================== --- tests/serialization.xml +++ tests/serialization.xml @@ -1,15 +1,9 @@ - MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla - - - data - - Qu"xbar test 1234 0x1.34a456d5cfaadp+10 @@ -19,16 +13,10 @@ Hello - Blub - - - B"la - - Hello Wo ld! How are you? https://webkeks.org/ @@ -67,13 +55,11 @@ xml - - - + foo @@ -90,7 +76,19 @@ list + + Blub + + + B"la + + + MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla + + + data +