added _insertChild:atIndex: private method to replicate Cocoa behavior of allowing adjacent text nodes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/branches/nsxml_using_libxml2@34684 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Doug Simons 2012-02-01 01:12:12 +00:00
parent 67effbde5f
commit a7a674de22
4 changed files with 98 additions and 50 deletions

View file

@ -1,3 +1,13 @@
2012-01-31 Doug Simons <doug.simons@testplant.com>
* Source/NSXMLDocument.m
* Source/NSXMLElement.m
* Source/NSXMLNode.m (-insertChild:atIndex:): Implement our own
_insertChild:atIndex: method to link a child in by hand. This
avoids the built-in libxml functions' behavior of always merging
adjacent text nodes as they are added, which Cocoa doesn't do.
Next we need to implement -normalizeAdjacentTextNodesPreservingCDATA:.
2012-01-31 17:57-EST Gregory John Casamento <greg.casamento@gmail.com>
* Source/NSXMLDocument.m: Minor corrections in

View file

@ -42,6 +42,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
+ (NSXMLNode *) _objectForNode: (xmlNodePtr)node;
- (void) _addSubNode:(NSXMLNode *)subNode;
- (void) _removeSubNode:(NSXMLNode *)subNode;
- (void) _insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index;
@end
@implementation NSXMLDocument
@ -288,15 +289,11 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (void) insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index
{
NSXMLNodeKind kind = [child kind];
NSXMLNode *cur = nil;
xmlNodePtr curNode = NULL;
xmlNodePtr thisNode = (xmlNodePtr)[self _node];
xmlNodePtr childNode = (xmlNodePtr)[child _node];
NSUInteger childCount = [self childCount];
// Check to make sure this is a valid addition...
NSAssert(nil != child, NSInvalidArgumentException);
NSAssert(index <= [self childCount], NSInvalidArgumentException);
NSAssert(index <= childCount, NSInvalidArgumentException);
NSAssert(nil == [child parent], NSInvalidArgumentException);
kind = [child kind];
NSAssert(NSXMLAttributeKind != kind, NSInvalidArgumentException);
@ -308,22 +305,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
NSAssert(NSXMLNamespaceKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLNotationDeclarationKind != kind, NSInvalidArgumentException);
// Get all of the nodes...
childNode = ((xmlNodePtr)[child _node]);
cur = [self childAtIndex: index];
curNode = ((xmlNodePtr)[cur _node]);
if(0 == childCount || index == childCount)
{
xmlAddChild(thisNode, childNode);
}
else if(index < childCount)
{
xmlAddNextSibling(curNode, childNode);
}
[self _addSubNode:child];
[self _insertChild:child atIndex:index];
}
- (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index

View file

@ -39,6 +39,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (void) _addSubNode:(NSXMLNode *)subNode;
- (void) _removeSubNode:(NSXMLNode *)subNode;
- (id) _initWithNode:(xmlNodePtr)node kind:(NSXMLNodeKind)kind;
- (void) _insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index;
@end
@implementation NSXMLElement
@ -333,12 +334,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (void) insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index
{
NSXMLNodeKind kind = [child kind];
NSXMLNode *cur = nil;
xmlNodePtr curNode = NULL;
xmlNodePtr thisNode = (xmlNodePtr)[self _node];
xmlNodePtr childNode = (xmlNodePtr)[child _node];
NSUInteger childCount = [self childCount];
xmlNodePtr addedNode = NULL;
// Check to make sure this is a valid addition...
NSAssert(nil != child, NSInvalidArgumentException);
@ -353,26 +349,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
NSAssert(NSXMLNamespaceKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLNotationDeclarationKind != kind, NSInvalidArgumentException);
// Get all of the nodes...
childNode = ((xmlNodePtr)[child _node]);
cur = [self childAtIndex: index];
curNode = ((xmlNodePtr)[cur _node]);
if(0 == childCount || index == childCount)
{
addedNode = xmlAddChild(thisNode, childNode);
}
else if(index < childCount)
{
addedNode = xmlAddPrevSibling(curNode, childNode);
}
if (addedNode != childNode)
{
[child _setNode:NULL];
child = [NSXMLNode _objectForNode:addedNode];
}
[self _addSubNode:child];
[self _insertChild:child atIndex:index];
}
- (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index

View file

@ -555,15 +555,15 @@ NSArray *execute_xpath(NSXMLNode *node,
return [self notImplemented: _cmd]; // FIXME ... generate from libxml
}
- (NSXMLNode*) childAtIndex: (NSUInteger)index
- (xmlNodePtr) _childNodeAtIndex: (NSUInteger)index
{
NSUInteger count = 0;
xmlNodePtr node = (xmlNodePtr)(internal->node);
xmlNodePtr children = node->children;
if (!children)
return nil; // the Cocoa docs say it returns nil if there are no children
return NULL; // the Cocoa docs say it returns nil if there are no children
for (children = node->children; children && count != index; children = children->next)
for (children = node->children; children != NULL && count != index; children = children->next)
{
count++;
}
@ -571,7 +571,13 @@ NSArray *execute_xpath(NSXMLNode *node,
if (count != index)
[NSException raise: NSRangeException format: @"child index too large"];
return (NSXMLNode *)[NSXMLNode _objectForNode: children];
return children;
}
- (NSXMLNode*) childAtIndex: (NSUInteger)index
{
xmlNodePtr childNode = [self _childNodeAtIndex:index];
return (NSXMLNode *)[NSXMLNode _objectForNode: childNode];
}
- (NSUInteger) childCount
@ -615,6 +621,79 @@ NSArray *execute_xpath(NSXMLNode *node,
return childrenArray;
}
- (void) _insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index
{
// this private method provides the common insertion implementation used by NSXMLElement and NSXMLDocument
// Get all of the nodes...
xmlNodePtr parentNode = MY_NODE; // we are the parent
xmlNodePtr childNode = ((xmlNodePtr)[child _node]);
xmlNodePtr curNode = [self _childNodeAtIndex: index];
BOOL mergeTextNodes = NO; // is there a defined option for this?
if (mergeTextNodes || childNode->type == XML_ATTRIBUTE_NODE)
{
// this uses the built-in libxml functions which merge adjacent text nodes
xmlNodePtr addedNode = NULL;
//curNode = ((xmlNodePtr)[cur _node]);
if (curNode == NULL) //(0 == childCount || index == childCount)
{
addedNode = xmlAddChild(parentNode, childNode);
}
else //if(index < childCount)
{
addedNode = xmlAddPrevSibling(curNode, childNode);
}
if (addedNode != childNode)
{
[child _setNode:NULL];
child = [NSXMLNode _objectForNode:addedNode];
}
}
else
{
// here we avoid merging adjacent text nodes by linking the new node in "by hand"
childNode->parent = parentNode;
if (curNode)
{
// insert childNode before an existing node curNode
xmlNodePtr prevNode = curNode->prev;
curNode->prev = childNode;
childNode->next = curNode;
if (prevNode)
{
childNode->prev = prevNode;
prevNode->next = childNode;
}
else
{
// in this case, this is the new "first child", so update our parent to point to it
parentNode->children = childNode;
}
}
else
{
// not inserting before an existing node... add as new "last child"
xmlNodePtr formerLastChild = parentNode->last;
if (formerLastChild)
{
formerLastChild->next = childNode;
childNode->prev = formerLastChild;
parentNode->last = childNode;
}
else
{
// no former children -- this is the first
parentNode->children = childNode;
parentNode->last = childNode;
}
}
}
[self _addSubNode:child];
}
- (id) copyWithZone: (NSZone*)zone
{
id c = [[self class] allocWithZone: zone];