Index: src/OFXMLElement.h
==================================================================
--- src/OFXMLElement.h
+++ src/OFXMLElement.h
@@ -10,10 +10,11 @@
*/
#import "OFObject.h"
@class OFString;
+@class OFMutableString;
@class OFMutableArray;
@class OFMutableDictionary;
@class OFXMLAttribute;
@interface OFXMLElement: OFObject
@@ -20,13 +21,14 @@
{
OFString *name;
OFString *namespace;
OFString *defaultNamespace;
OFMutableArray *attributes;
- OFString *stringValue;
OFMutableDictionary *namespaces;
OFMutableArray *children;
+ OFString *text;
+ OFMutableString *comment;
}
/**
* \param name The name for the element
* \return A new autoreleased OFXMLElement with the specified element name
@@ -60,10 +62,26 @@
*/
+ elementWithName: (OFString*)name
namespace: (OFString*)ns
stringValue: (OFString*)stringval;
+/**
+ * Creates a new element, only consisting of the specified text.
+ *
+ * \param text The text the element represents
+ * \return A new autoreleased OFXMLElement consisting of the specified text
+ */
++ elementWithText: (OFString*)text;
+
+/**
+ * Creates a new element, only consisting of the specified comment.
+ *
+ * \param comment The comment the element represents
+ * \return A new autoreleased OFXMLElement consisting of the specified comment
+ */
++ elementWithComment: (OFString*)text;
+
/**
* Initializes an already allocated OFXMLElement with the specified element
* name.
*
* \param name The name for the element
@@ -107,10 +125,28 @@
*/
- initWithName: (OFString*)name
namespace: (OFString*)ns
stringValue: (OFString*)stringval;
+/**
+ * Initializes an already allocated OFXMLElement so that it only consists of the
+ * specified text.
+ *
+ * \param text The text the element represents
+ * \return An initialized OFXMLElement consisting of the specified text
+ */
+- initWithText: (OFString*)text;
+
+/**
+ * Initializes an already allocated OFXMLElement so that it only consists of the
+ * specified comment.
+ *
+ * \param comment The comment the element represents
+ * \return An initialized OFXMLElement consisting of the specified comment
+ */
+- initWithComment: (OFString*)text;
+
/**
* \return A new autoreleased OFString representing the OFXMLElement as an
* XML string
*/
- (OFString*)string;
Index: src/OFXMLElement.m
==================================================================
--- src/OFXMLElement.m
+++ src/OFXMLElement.m
@@ -48,10 +48,20 @@
{
return [[[self alloc] initWithName: name
namespace: ns
stringValue: stringval] autorelease];
}
+
++ elementWithText: (OFString*)text
+{
+ return [[[self alloc] initWithText: text] autorelease];
+}
+
++ elementWithComment: (OFString*)comment
+{
+ return [[[self alloc] initWithComment: comment] autorelease];
+}
- init
{
@throw [OFNotImplementedException newWithClass: isa
selector: _cmd];
@@ -86,31 +96,75 @@
{
self = [super init];
name = [name_ copy];
namespace = [ns copy];
- stringValue = [stringval copy];
+
+ if (stringval != nil) {
+ OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];;
+ [self addChild: [OFXMLElement elementWithText: stringval]];
+ [pool release];
+ }
namespaces = [[OFMutableDictionary alloc] initWithKeysAndObjects:
@"http://www.w3.org/XML/1998/namespace", @"xml",
@"http://www.w3.org/2000/xmlns/", @"xmlns", nil];
return self;
}
+
+- initWithText: (OFString*)text_
+{
+ self = [super init];
+
+ @try {
+ OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
+ text = [[text_ stringByXMLEscaping] retain];
+ [pool release];
+ } @catch (OFException *e) {
+ [self dealloc];
+ @throw e;
+ }
+
+ return self;
+}
+
+- initWithComment: (OFString*)comment_
+{
+ self = [super init];
+
+ @try {
+ comment = [[OFMutableString alloc] initWithString: @""];
+ } @catch (OFException *e) {
+ [self dealloc];
+ @throw e;
+ }
+
+ return self;
+}
- (OFString*)_stringWithParentNamespaces: (OFDictionary*)parent_namespaces
parentDefaultNamespace: (OFString*)parent_default_ns
{
- OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init], *pool2;
+ OFAutoreleasePool *pool, *pool2;
char *str_c;
size_t len, i, j, attrs_count;
OFString *prefix = nil;
OFXMLAttribute **attrs_carray;
OFString *ret, *tmp;
OFMutableDictionary *all_namespaces;
OFString *def_ns;
+ if (text != nil)
+ return [[text retain] autorelease];
+
+ if (comment != nil)
+ return [[comment retain] autorelease];
+
+ pool = [[OFAutoreleasePool alloc] init];
def_ns = (defaultNamespace != nil
? defaultNamespace : parent_default_ns);
if (parent_namespaces != nil) {
OFEnumerator *key_enum = [namespaces keyEnumerator];
@@ -210,31 +264,25 @@
[pool2 releaseObjects];
}
/* Childen */
- if (stringValue != nil || children != nil) {
- if (stringValue != nil)
- tmp = [stringValue stringByXMLEscaping];
- else if (children != nil) {
- OFXMLElement **children_carray = [children cArray];
- size_t children_count = [children count];
- IMP append;
-
- tmp = [OFMutableString string];
- append = [tmp methodForSelector:
- @selector(appendCStringWithoutUTF8Checking:)];
-
- for (j = 0; j < children_count; j++)
- append(tmp, @selector(
- appendCStringWithoutUTF8Checking:),
- [[children_carray[j]
- _stringWithParentNamespaces:
- all_namespaces
- parentDefaultNamespace: defaultNamespace]
- cString]);
- }
+ if (children != nil) {
+ OFXMLElement **children_carray = [children cArray];
+ size_t children_count = [children count];
+ IMP append;
+
+ tmp = [OFMutableString string];
+ append = [tmp methodForSelector:
+ @selector(appendCStringWithoutUTF8Checking:)];
+
+ for (j = 0; j < children_count; j++)
+ append(tmp, @selector(
+ appendCStringWithoutUTF8Checking:),
+ [[children_carray[j]
+ _stringWithParentNamespaces: all_namespaces
+ parentDefaultNamespace: defaultNamespace] cString]);
len += [tmp cStringLength] + [name cStringLength] + 2;
@try {
str_c = [self resizeMemory: str_c
toSize: len];
@@ -288,10 +336,14 @@
parentDefaultNamespace: nil];
}
- (void)addAttribute: (OFXMLAttribute*)attr
{
+ if (name == nil)
+ @throw [OFInvalidArgumentException newWithClass: isa
+ selector: _cmd];
+
if (attributes == nil)
attributes = [[OFMutableArray alloc] init];
/* FIXME: Prevent having it twice! */
@@ -299,11 +351,17 @@
}
- (void)addAttributeWithName: (OFString*)name_
stringValue: (OFString*)value
{
- OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
+ OFAutoreleasePool *pool;
+
+ if (name == nil)
+ @throw [OFInvalidArgumentException newWithClass: isa
+ selector: _cmd];
+
+ pool = [[OFAutoreleasePool alloc] init];
[self addAttribute: [OFXMLAttribute attributeWithName: name_
namespace: nil
stringValue: value]];
[pool release];
}
@@ -310,11 +368,17 @@
- (void)addAttributeWithName: (OFString*)name_
namespace: (OFString*)ns
stringValue: (OFString*)value
{
- OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
+ OFAutoreleasePool *pool;
+
+ if (name == nil)
+ @throw [OFInvalidArgumentException newWithClass: isa
+ selector: _cmd];
+
+ pool = [[OFAutoreleasePool alloc] init];
[self addAttribute: [OFXMLAttribute attributeWithName: name_
namespace: ns
stringValue: value]];
[pool release];
}
@@ -323,11 +387,11 @@
/* TODO: Remove attribute */
- (void)setPrefix: (OFString*)prefix
forNamespace: (OFString*)ns
{
- if (prefix == nil || [prefix isEqual: @""])
+ if (name == nil || prefix == nil || [prefix isEqual: @""])
@throw [OFInvalidArgumentException newWithClass: isa
selector: _cmd];
if (ns == nil)
ns = @"";
@@ -335,23 +399,31 @@
forKey: ns];
}
- (OFString*)defaultNamespace
{
+ if (name == nil)
+ @throw [OFInvalidArgumentException newWithClass: isa
+ selector: _cmd];
+
return [[defaultNamespace retain] autorelease];
}
- (void)setDefaultNamespace: (OFString*)ns
{
+ if (name == nil)
+ @throw [OFInvalidArgumentException newWithClass: isa
+ selector: _cmd];
+
OFString *old = defaultNamespace;
defaultNamespace = [ns copy];
[old release];
}
- (void)addChild: (OFXMLElement*)child
{
- if (stringValue != nil)
+ if (name == nil)
@throw [OFInvalidArgumentException newWithClass: isa
selector: _cmd];
if (children == nil)
children = [[OFMutableArray alloc] init];
@@ -362,12 +434,13 @@
- (void)dealloc
{
[name release];
[namespace release];
[attributes release];
- [stringValue release];
[namespaces release];
[children release];
+ [text release];
+ [comment release];
[super dealloc];
}
@end
Index: tests/OFXMLElementTests.m
==================================================================
--- tests/OFXMLElementTests.m
+++ tests/OFXMLElementTests.m
@@ -53,10 +53,18 @@
stringValue: @"x"]) &&
R([elem[3] setPrefix: @"objfw-test"
forNamespace: @"urn:objfw:test"]) &&
[[elem[3] string] isEqual: @"x"])
+ TEST(@"+[elementWithText:]",
+ (elem[3] = [OFXMLElement elementWithText: @""]) &&
+ [[elem[3] string] isEqual: @"<foo>"])
+
+ TEST(@"+[elementWithComment:]",
+ (elem[3] = [OFXMLElement elementWithComment: @" comment "]) &&
+ [[elem[3] string] isEqual: @""])
+
TEST(@"-[addAttributeWithName:stringValue:]",
R([elem[0] addAttributeWithName: @"foo"
stringValue: @"b&ar"]) &&
[[elem[0] string] isEqual: @""] &&
R([elem[1] addAttributeWithName: @"foo"