Implement -normalizeAdjacentTextNodesPreservingCDATA: and supporting methods; logic fix

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/branches/nsxml_using_libxml2@34768 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Doug Simons 2012-02-16 21:29:47 +00:00
parent e5691678b4
commit a74ecad5db
3 changed files with 82 additions and 7 deletions

View file

@ -1,3 +1,9 @@
2012-02-16 Doug Simons <doug.simons@testplant.com>
* Source/NSXMLElement.m: Implement -normalizeAdjacentTextNodesPreservingCDATA:
method and supporting methods.
* Source/NSXMLNode.m: Fix a logic error.
2012-02-14 13:07-EST Gregory John Casamento <greg.casamento@gmail.com>
* Source/NSXMLDocument.m: Implement DTD validation and

View file

@ -42,6 +42,8 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (void) _removeSubNode:(NSXMLNode *)subNode;
- (id) _initWithNode:(xmlNodePtr)node kind:(NSXMLNodeKind)kind;
- (void) _insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index;
- (void) _updateExternalRetains;
- (void) _invalidate;
@end
@implementation NSXMLElement
@ -436,9 +438,68 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
[self removeChildAtIndex: index + 1];
}
static void joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *nodesToDelete)
{
NSXMLNode *objA = (nodeA->_private), *objB = (nodeB->_private);
xmlTextMerge(nodeA, nodeB); // merge nodeB into nodeA
if (objA != nil) // objA gets the merged node
{
if (objB != nil) // objB is now invalid
{
[objB _invalidate]; // set it to be invalid and make sure it's not pointing to a freed node
[nodesToDelete addObject:objB];
}
}
else if (objB != nil) // there is no objA -- objB gets the merged node
{
[objB _setNode:nodeA]; // nodeA is the remaining (merged) node
}
}
- (void) normalizeAdjacentTextNodesPreservingCDATA: (BOOL)preserve
{
// FIXME: Implement this method...
NSEnumerator *subEnum = [internal->subNodes objectEnumerator];
NSXMLNode *subNode = nil;
NSMutableArray *nodesToDelete = [NSMutableArray array];
while ((subNode = [subEnum nextObject]))
{
xmlNodePtr node = [subNode _node];
xmlNodePtr prev = node->prev;
xmlNodePtr next = node->next;
if (node->type == XML_ELEMENT_NODE)
[(NSXMLElement *)subNode normalizeAdjacentTextNodesPreservingCDATA:preserve];
else if (node->type == XML_TEXT_NODE || (node->type == XML_CDATA_SECTION_NODE && !preserve))
{
if (next && (next->type == XML_TEXT_NODE
|| (next->type == XML_CDATA_SECTION_NODE && !preserve)))
{
//combine node & node->next
joinTextNodes(node, node->next, nodesToDelete);
}
if (prev && (prev->type == XML_TEXT_NODE
|| (prev->type == XML_CDATA_SECTION_NODE && !preserve)))
{
//combine node->prev & node
// join the text of both nodes
// assign the joined text to the earlier of the two nodes that has an ObjC object
// unlink the other node
// delete the other node's object (maybe add it to a list of nodes to delete when we're done? -- or just set its node to null, and then remove it from our subNodes when we're done iterating it) (or maybe we need to turn it into an NSInvalidNode too??)
joinTextNodes(node->prev, node, nodesToDelete);
}
}
}
if ([nodesToDelete count] > 0)
{
subEnum = [nodesToDelete objectEnumerator];
while ((subNode = [subEnum nextObject]))
{
[self _removeSubNode:subNode];
}
[self _updateExternalRetains];
}
}
- (id) copyWithZone: (NSZone *)zone

View file

@ -53,16 +53,16 @@ BOOL isEqualAttr(xmlAttrPtr attrA, xmlAttrPtr attrB)
xmlChar* nameB;
// what has to be the same for two attributes to be equal -- just their values??
if(attrA == NULL || attrB == NO)
{
return NO;
}
if(attrB == NULL && attrA == NULL)
{
return YES;
}
if(attrA == NULL || attrB == NULL)
{
return NO;
}
// get the content...
contentA = xmlNodeGetContent((const xmlNodePtr)attrA);
contentB = xmlNodeGetContent((const xmlNodePtr)attrB);
@ -196,6 +196,8 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
- (void) _addSubNode:(NSXMLNode *)subNode;
- (void) _removeSubNode:(NSXMLNode *)subNode;
- (id) _initWithNode:(xmlNodePtr)node kind:(NSXMLNodeKind)kind;
- (void) _updateExternalRetains;
- (void) _invalidate;
@end
@implementation NSXMLNode (Private)
@ -276,7 +278,7 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
- (void) _updateExternalRetains
{
xmlNodePtr pnode = MY_NODE->parent;
xmlNodePtr pnode = (MY_NODE ? MY_NODE->parent : NULL);
NSXMLNode *parent = (NSXMLNode *)(pnode ? pnode->_private : nil);
int oldCount = internal->externalRetains;
int extraRetains = ([self retainCount] > 1 ? 1 : 0); // start with 1 or 0 for ourself
@ -402,6 +404,12 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
return self;
}
- (void) _invalidate
{
internal->kind = NSXMLInvalidKind;
[self _setNode:NULL];
}
@end
void clearPrivatePointers(xmlNodePtr aNode)