Index: src/OFXMLElement.h
==================================================================
--- src/OFXMLElement.h
+++ src/OFXMLElement.h
@@ -215,10 +215,15 @@
/**
* \return An array with all children of the element
*/
- (OFArray*)children;
+/**
+ * \return A string with the string value of all children concatenated
+ */
+- (OFString*)stringValue;
+
/**
* \return A new autoreleased OFString representing the OFXMLElement as an
* XML string
*/
- (OFString*)XMLString;
Index: src/OFXMLElement.m
==================================================================
--- src/OFXMLElement.m
+++ src/OFXMLElement.m
@@ -262,10 +262,46 @@
- (OFArray*)children
{
return [[children copy] autorelease];
}
+
+- (OFString*)stringValue
+{
+ OFAutoreleasePool *pool;
+ OFMutableString *ret;
+ OFXMLElement **children_c;
+ size_t i, count = [children count];
+
+ if (count == 0)
+ return @"";
+
+ ret = [OFMutableString string];
+ children_c = [children cArray];
+ pool = [[OFAutoreleasePool alloc] init];
+
+ for (i = 0; i < count; i++) {
+ if (children_c[i]->characters != nil)
+ [ret appendString: children_c[i]->characters];
+ else if (children_c[i]->cdata != nil)
+ [ret appendString: children_c[i]->cdata];
+ else if (children_c[i]->comment == nil) {
+ [ret appendString: [children_c[i] stringValue]];
+ [pool releaseObjects];
+ }
+ }
+
+ [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;
+}
- (OFString*)_XMLStringWithParent: (OFXMLElement*)parent
{
OFAutoreleasePool *pool, *pool2;
char *str_c;
Index: tests/OFXMLElementTests.m
==================================================================
--- tests/OFXMLElementTests.m
+++ tests/OFXMLElementTests.m
@@ -114,10 +114,15 @@
@""] &&
R([elem[2] addChild: [OFXMLElement elementWithName: @"bar"
namespace: @"urn:objfw:test"]]) &&
[[elem[2] XMLString] isEqual:
@""])
+
+ TEST(@"+[elementWithXMLString:] and -[stringValue]",
+ [[[OFXMLElement elementWithXMLString:
+ @"foobazqux"] stringValue] isEqual:
+ @"foobarbazqux"])
TEST(@"-[elementsForName:namespace:]",
(a = [elem[2] elementsForName: @"bar"
namespace: @"urn:objfw:test"]) &&
[a count] == 1 && [[[a firstObject] XMLString] isEqual:
Index: tests/TestsAppDelegate.m
==================================================================
--- tests/TestsAppDelegate.m
+++ tests/TestsAppDelegate.m
@@ -136,12 +136,12 @@
#endif
[self URLTests];
#ifdef OF_THREADS
[self HTTPRequestTests];
#endif
- [self XMLElementTests];
[self XMLParserTests];
+ [self XMLElementTests];
[self XMLElementBuilderTests];
#ifdef OF_PLUGINS
[self pluginTests];
#endif
#ifdef OF_HAVE_PROPERTIES