mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
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:
parent
078309e705
commit
42f0192c2c
6 changed files with 238 additions and 74 deletions
10
ChangeLog
10
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -180,6 +180,3 @@
|
|||
|
||||
#endif
|
||||
|
||||
@interface NSXMLNode (Private)
|
||||
- (void) setParent: (NSXMLNode *)node;
|
||||
@end
|
||||
|
|
Loading…
Reference in a new issue