Rewrite hierarchy handling to match OSX

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34441 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2012-01-06 12:22:30 +00:00
parent 078309e705
commit 42f0192c2c
6 changed files with 238 additions and 74 deletions

View file

@ -1,3 +1,13 @@
2012-01-05 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSXMLDocument.m:
* Source/NSXMLElement.m:
* Source/NSXMLNode.m:
* Source/NSXMLPrivate.h:
Rewrote node hierarchy handling to match OSX documentation and
behaviors. Also implemented -hash and -isEqual: to match OSX for
NSXMLNode.
2012-01-05 22:20-EST Doug Simons <doug.simons@testplant.com>
* Source/NSXMLDocument.m: Modify XMLStringWithOptions: to only include

View file

@ -99,10 +99,18 @@ extern "C" {
- (void) setAttributes: (NSArray*)attributes;
/**
* Sets attributes from the supplkied dictionary.
* Sets attributes from the supplied dictionary.<br />
* DEPRECATED ... use -setAttributesWithDictionary: instead.
*/
- (void) setAttributesAsDictionary: (NSDictionary*)attributes;
#if OS_API_VERSION(100700, GS_API_LATEST)
/**
* Sets attributes from the supplied dictionary.
*/
- (void) setAttributesWithDictionary: (NSDictionary*)attributes;
#endif
/**
* Returns the receiver's attributes.
*/

View file

@ -218,8 +218,14 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
- (void) setRootElement: (NSXMLNode*)root
{
NSArray *children;
NSAssert(internal->rootElement == nil, NSGenericException);
[self insertChild: root atIndex: [internal->children count]];
/* this method replaces *all* children with the specified element.
*/
children = [[NSArray alloc] initWithObjects: &root count: 1];
[self setChildren: children];
[children release];
internal->rootElement = (NSXMLElement*)root;
}
@ -248,48 +254,94 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
- (void) insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index
{
[child setParent: self];
[(NSMutableArray *)internal->children insertObject: child atIndex: index];
// internal->childrenHaveMutated = YES;
NSXMLNodeKind kind;
NSAssert(nil != child, NSInvalidArgumentException);
NSAssert(index <= internal->childCount, NSInvalidArgumentException);
NSAssert(nil == [child parent], NSInvalidArgumentException);
kind = [child kind];
NSAssert(NSXMLAttributeKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLDTDKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLDocumentKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLElementDeclarationKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLEntityDeclarationKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLInvalidKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLNamespaceKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLNotationDeclarationKind != kind, NSInvalidArgumentException);
if (nil == internal->children)
{
internal->children = [[NSMutableArray alloc] initWithCapacity: 10];
}
[internal->children insertObject: child
atIndex: index];
GSIVar(child, parent) = self;
internal->childCount++;
}
- (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index
{
NSEnumerator *enumerator = [children objectEnumerator];
NSXMLNode *node;
while ((node = [enumerator nextObject]) != nil)
NSXMLNode *child;
while ((child = [enumerator nextObject]) != nil)
{
[self insertChild: node atIndex: index++];
[self insertChild: child atIndex: index++];
}
}
- (void) removeChildAtIndex: (NSUInteger)index
{
[(NSMutableArray *)internal->children removeObjectAtIndex: index];
// internal->childrenHaveMutated = YES;
NSXMLNode *child = [internal->children objectAtIndex: index];
if (nil != child)
{
if (internal->rootElement == child)
{
internal->rootElement = nil;
}
GSIVar(child, parent) = nil;
[internal->children removeObjectAtIndex: index];
if (0 == --internal->childCount)
{
/* The -children method must return nil if there are no children,
* so we destroy the container.
*/
DESTROY(internal->children);
}
}
}
- (void) setChildren: (NSArray*)children
{
unsigned count;
while ((count = [internal->children count]) > 0)
if (children != internal->children)
{
[self removeChildAtIndex: count - 1];
}
[self insertChildren: children atIndex: 0];
}
NSEnumerator *en;
NSXMLNode *child;
[children retain];
while (internal->childCount > 0)
{
[self removeChildAtIndex:internal->childCount - 1];
}
en = [children objectEnumerator];
while ((child = [en nextObject]) != nil)
{
[self insertChild: child atIndex: internal->childCount];
}
[children release];
}
}
- (void) addChild: (NSXMLNode*)child
{
[self insertChild: child atIndex: [internal->children count]];
[self insertChild: child atIndex: internal->childCount];
}
- (void) replaceChildAtIndex: (NSUInteger)index withNode: (NSXMLNode*)node
{
[self removeChildAtIndex: index];
[self insertChild: node atIndex: index];
[self removeChildAtIndex: index + 1];
}
- (NSData*) XMLData
@ -374,9 +426,11 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
- (id) copyWithZone: (NSZone *)zone
{
id c = [super copyWithZone: zone];
NSXMLDocument *c = (NSXMLDocument*)[super copyWithZone: zone];
[c setStandalone: internal->standalone];
[c setRootElement: internal->rootElement];
[c setChildren: internal->children];
GSIVar(c, rootElement) = internal->rootElement;
[c setDTD: internal->docType];
[c setMIMEType: internal->MIMEType];
return c;
@ -399,7 +453,7 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
[lastElement addChild: currentElement];
[internal->elementStack addObject: currentElement];
[currentElement release];
if (internal->rootElement == nil)
if (nil == internal->rootElement)
{
[self setRootElement: currentElement];
}

View file

@ -71,10 +71,11 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
GS_CREATE_INTERNAL(NSXMLElement)
if ((self = [super initWithKind: NSXMLElementKind]) != nil)
{
ASSIGN(internal->name, name);
ASSIGNCOPY(internal->name, name);
ASSIGNCOPY(internal->URI, URI);
internal->attributes = [[NSMutableDictionary alloc] initWithCapacity: 10];
internal->namespaces = [[NSMutableArray alloc] initWithCapacity: 10];
internal->children = [[NSMutableArray alloc] initWithCapacity: 10];
internal->objectValue = @"";
}
return self;
}
@ -109,7 +110,7 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
- (void) addAttribute: (NSXMLNode*)attribute
{
[internal->attributes setObject: attribute
forKey: [attribute name]];
forKey: [attribute name]];
}
- (void) removeAttributeForName: (NSString*)name
@ -122,6 +123,7 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
NSEnumerator *enumerator = [attributes objectEnumerator];
NSXMLNode *attribute;
[internal->attributes removeAllObjects];
while ((attribute = [enumerator nextObject]) != nil)
{
[self addAttribute: attribute];
@ -129,10 +131,16 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
}
- (void) setAttributesAsDictionary: (NSDictionary*)attributes
{
[self setAttributesWithDictionary: attributes];
}
- (void) setAttributesWithDictionary: (NSDictionary*)attributes
{
NSEnumerator *en = [attributes keyEnumerator];
NSString *key;
[internal->attributes removeAllObjects];
while ((key = [en nextObject]) != nil)
{
NSString *val = [attributes objectForKey: key];
@ -153,7 +161,7 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
}
- (NSXMLNode*) attributeForLocalName: (NSString*)localName
URI: (NSString*)URI
URI: (NSString*)URI
{
[self notImplemented: _cmd];
return nil;
@ -174,6 +182,15 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
ASSIGNCOPY(internal->namespaces, namespaces);
}
- (void) setObjectValue: (id)value
{
if (nil == value)
{
value = @""; // May not be nil
}
ASSIGN(internal->objectValue, value);
}
- (NSArray*) namespaces
{
return internal->namespaces;
@ -199,9 +216,29 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
- (void) insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index
{
[child setParent: self];
NSXMLNodeKind kind;
NSAssert(nil != child, NSInvalidArgumentException);
NSAssert(index <= internal->childCount, NSInvalidArgumentException);
NSAssert(nil == [child parent], NSInvalidArgumentException);
kind = [child kind];
// FIXME ... should we check for valid kinds rather than invalid ones?
NSAssert(NSXMLAttributeKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLDTDKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLDocumentKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLElementDeclarationKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLEntityDeclarationKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLInvalidKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLNamespaceKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLNotationDeclarationKind != kind, NSInvalidArgumentException);
if (nil == internal->children)
{
internal->children = [[NSMutableArray alloc] initWithCapacity: 10];
}
[internal->children insertObject: child
atIndex: index];
GSIVar(child, parent) = self;
internal->childCount++;
}
@ -218,38 +255,52 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
- (void) removeChildAtIndex: (NSUInteger)index
{
[internal->children removeObjectAtIndex: index];
internal->childCount--;
NSXMLNode *child = [internal->children objectAtIndex: index];
if (nil != child)
{
GSIVar(child, parent) = nil;
[internal->children removeObjectAtIndex: index];
if (0 == --internal->childCount)
{
/* The -children method must return nil if there are no children,
* so we destroy the container.
*/
DESTROY(internal->children);
}
}
}
- (void) setChildren: (NSArray*)children
{
NSMutableArray *c = [children mutableCopy];
NSEnumerator *en = [c objectEnumerator];
NSXMLNode *n = nil;
ASSIGN(internal->children, c);
internal->childCount = [children count];
[c release];
while((n = [en nextObject]) != nil)
if (children != internal->children)
{
[n setParent: self];
NSEnumerator *en;
NSXMLNode *child;
[children retain];
while (internal->childCount > 0)
{
[self removeChildAtIndex:internal->childCount - 1];
}
en = [children objectEnumerator];
while ((child = [en nextObject]) != nil)
{
[self insertChild: child atIndex: internal->childCount];
}
[children release];
}
// internal->childrenHaveMutated = YES;
}
- (void) addChild: (NSXMLNode*)child
{
[child setParent: self];
[internal->children addObject: child];
// internal->childrenHaveMutated = YES;
internal->childCount++;
[self insertChild: child atIndex: internal->childCount];
}
- (void) replaceChildAtIndex: (NSUInteger)index withNode: (NSXMLNode*)node
{
[self removeChildAtIndex: index];
[self insertChild: node atIndex: index];
[self removeChildAtIndex: index + 1];
}
- (void) normalizeAdjacentTextNodesPreservingCDATA: (BOOL)preserve
@ -295,28 +346,24 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
- (id) copyWithZone: (NSZone *)zone
{
id c = [super copyWithZone: zone];
NSEnumerator *en = [internal->namespaces objectEnumerator];
NSXMLElement *c = (NSXMLElement*)[super copyWithZone: zone];
NSEnumerator *en = [internal->namespaces objectEnumerator];
id obj = nil;
while((obj = [en nextObject]) != nil)
while ((obj = [en nextObject]) != nil)
{
[c addNamespace: [obj copyWithZone: zone]];
}
en = [internal->attributes objectEnumerator];
while((obj = [en nextObject]) != nil)
while ((obj = [en nextObject]) != nil)
{
NSXMLNode *attr = [obj copyWithZone: zone];
[c addAttribute: attr];
}
en = [[self children] objectEnumerator];
while((obj = [en nextObject]) != nil)
{
NSXMLNode *n = [obj copyWithZone:zone];
[self addChild: n];
}
[c setChildren: [self children]];
return c;
}

View file

@ -30,13 +30,6 @@
GS_PRIVATE_INTERNAL(NSXMLNode)
@implementation NSXMLNode (Private)
- (void) setParent: (NSXMLNode *)node
{
ASSIGN(internal->parent,node);
}
@end
@implementation NSXMLNode
+ (id) attributeWithName: (NSString*)name
@ -199,7 +192,7 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
return internal->childCount;
}
- (NSArray*)children
- (NSArray*) children
{
return internal->children;
}
@ -217,7 +210,7 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
[c setStringValue: [self stringValue]];
/*
while((obj = [en nextObject]) != nil)
while ((obj = [en nextObject]) != nil)
{
NSXMLNode *n = [obj copyWithZone:zone];
[self addChild: n];
@ -251,6 +244,11 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
}
}
- (NSUInteger) hash
{
return [internal->name hash];
}
- (NSUInteger) index
{
return internal->index;
@ -324,10 +322,51 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
*/
internal->kind = kind;
internal->options = theOptions;
internal->children = [NSMutableArray new];
internal->stringValue = @"";
return self;
}
- (BOOL) isEqual: (id)other
{
NSString *s;
NSArray *c;
if (other == (id)self)
{
return YES;
}
if (NO == [other isKindOfClass: [self class]])
{
return NO;
}
if ([(NSXMLNode*)other kind] != internal->kind)
{
return NO;
}
s = [other name];
if (s != internal->name && NO == [s isEqual: internal->name])
{
return NO;
}
s = [other URI];
if (s != internal->URI && NO == [s isEqual: internal->URI])
{
return NO;
}
c = [other children];
if (c != internal->children && NO == [c isEqual: internal->children])
{
return NO;
}
return YES;
}
- (NSXMLNodeKind) kind
{
return internal->kind;
@ -509,7 +548,10 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (void) setName: (NSString *)name
{
ASSIGNCOPY(internal->name, name);
if (NSXMLInvalidKind != internal->kind)
{
ASSIGNCOPY(internal->name, name);
}
}
- (void) setStringValue: (NSString*)string
@ -519,19 +561,26 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (void) setURI: (NSString*)URI
{
ASSIGNCOPY(internal->URI, URI);
if (NSXMLInvalidKind != internal->kind)
{
ASSIGNCOPY(internal->URI, URI);
}
}
- (void) setStringValue: (NSString*)string resolvingEntities: (BOOL)resolve
{
if (resolve == NO)
{
ASSIGN(internal->stringValue, string);
ASSIGNCOPY(internal->stringValue, string);
}
else
{
// need to actually resolve entities...
ASSIGN(internal->stringValue, string);
ASSIGNCOPY(internal->stringValue, string);
}
if (nil == internal->stringValue)
{
internal->stringValue = @""; // string value may not be nil
}
}
@ -557,6 +606,5 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
return [self notImplemented: _cmd];
}
@end

View file

@ -180,6 +180,3 @@
#endif
@interface NSXMLNode (Private)
- (void) setParent: (NSXMLNode *)node;
@end