diff --git a/ChangeLog b/ChangeLog index 7c094ebec..a09670e94 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-03-18 Fred Kiefer + + * Source/NSXMLDTDNode.m: Correct node type, at least for entity nodes. + * Source/NSXMLDTD.m: Use predefined entities from libxml2. + * Source/NSXMLNode.m: Rewrite the ownership transfer to preserve + names in dictionaries. + 2012-03-17 Fred Kiefer * Source/NSXMLPrivate.h: Remvoe unused ivars. diff --git a/Source/NSXMLDTD.m b/Source/NSXMLDTD.m index ab84d9489..b33f14808 100644 --- a/Source/NSXMLDTD.m +++ b/Source/NSXMLDTD.m @@ -35,54 +35,8 @@ GS_PRIVATE_INTERNAL(NSXMLDTD) + (NSXMLDTDNode*) predefinedEntityDeclarationForName: (NSString*)name { - // FIXME: We should cache these instances - if ([name isEqualToString: @"lt"]) - { - NSXMLDTDNode *node; - - node = [[NSXMLDTDNode alloc] initWithKind: NSXMLEntityDeclarationKind]; - [node setName: @"lt"]; - [node setStringValue: @"<"]; - return AUTORELEASE(node); - } - if ([name isEqualToString: @"gt"]) - { - NSXMLDTDNode *node; - - node = [[NSXMLDTDNode alloc] initWithKind: NSXMLEntityDeclarationKind]; - [node setName: @"gt"]; - [node setStringValue: @">"]; - return AUTORELEASE(node); - } - if ([name isEqualToString: @"amp"]) - { - NSXMLDTDNode *node; - - node = [[NSXMLDTDNode alloc] initWithKind: NSXMLEntityDeclarationKind]; - [node setName: @"amp"]; - [node setStringValue: @"&"]; - return AUTORELEASE(node); - } - if ([name isEqualToString: @"quot"]) - { - NSXMLDTDNode *node; - - node = [[NSXMLDTDNode alloc] initWithKind: NSXMLEntityDeclarationKind]; - [node setName: @"qout"]; - [node setStringValue: @"\""]; - return AUTORELEASE(node); - } - if ([name isEqualToString: @"apos"]) - { - NSXMLDTDNode *node; - - node = [[NSXMLDTDNode alloc] initWithKind: NSXMLEntityDeclarationKind]; - [node setName: @"apos"]; - [node setStringValue: @"'"]; - return AUTORELEASE(node); - } - - return nil; + xmlEntityPtr node = xmlGetPredefinedEntity(XMLSTRING(name)); + return (NSXMLDTDNode*)[self _objectForNode: (xmlNodePtr)node]; } - (void) dealloc @@ -159,7 +113,7 @@ GS_PRIVATE_INTERNAL(NSXMLDTD) - (NSXMLDTDNode*) entityDeclarationForName: (NSString*)name { - //xmlGetEntityFromDtd + //xmlGetEntityFromDtd xmlDtdPtr node = internal->node; xmlNodePtr children = NULL; const xmlChar *xmlName = XMLSTRING(name); diff --git a/Source/NSXMLDTDNode.m b/Source/NSXMLDTDNode.m index a2bc6bfd4..8855c4c6a 100644 --- a/Source/NSXMLDTDNode.m +++ b/Source/NSXMLDTDNode.m @@ -24,7 +24,7 @@ #import "common.h" -#define GS_XMLNODETYPE xmlDtd +#define GS_XMLNODETYPE xmlEntity #define GSInternal NSXMLDTDNodeInternal #import "NSXMLPrivate.h" @@ -69,11 +69,21 @@ GS_PRIVATE_INTERNAL(NSXMLDTDNode) - (id) initWithXMLString: (NSString*)string { - // internal->node = xmlNewDtd(NULL,NULL,NULL); - // TODO: Parse the string and get the info to create this... + NSXMLDTDNode *result = nil; + NSError *error; + NSXMLDocument *tempDoc = + [[NSXMLDocument alloc] initWithXMLString: string + options: 0 + error: &error]; + if (tempDoc != nil) + { + result = RETAIN([tempDoc rootElement]); + [result detach]; // detach from document. + } + [tempDoc release]; + [self release]; - [self notImplemented: _cmd]; - return nil; + return result; } - (BOOL) isExternal diff --git a/Source/NSXMLNode.m b/Source/NSXMLNode.m index 08aa1e1d4..001ef0a59 100644 --- a/Source/NSXMLNode.m +++ b/Source/NSXMLNode.m @@ -479,8 +479,18 @@ isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB) /* here we avoid merging adjacent text nodes by linking * the new node in "by hand" */ + xmlDocPtr tmp = childNode->doc; + + if (tmp) + { + xmlDOMWrapAdoptNode(NULL, childNode->doc, childNode, parentNode->doc, parentNode, 0); + } + else + { + xmlSetTreeDoc(childNode, parentNode->doc); + } + childNode->parent = parentNode; - xmlSetTreeDoc(childNode, parentNode->doc); if (curNode) { // insert childNode before an existing node curNode @@ -1046,9 +1056,25 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces) { // the top level node frees the entire tree if (node->type == XML_DOCUMENT_NODE) - xmlFreeDoc((xmlDocPtr)node); + { + xmlFreeDoc((xmlDocPtr)node); + } + else if (node->type == XML_ENTITY_DECL && + ((xmlEntityPtr)node)->etype == XML_INTERNAL_PREDEFINED_ENTITY) + { + // Don't free internal entity nodes + } else - xmlFreeNode(node); + { + xmlDocPtr tmp = node->doc; + + xmlFreeNode(node); + // Free the private document we allocated in detach + if (tmp) + { + xmlFreeDoc(tmp); + } + } } } } @@ -1071,9 +1097,23 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces) } else { - // separate our node from its parent and siblings - xmlUnlinkNode(node); - xmlSetTreeDoc(node, NULL); + if (node->doc) + { + /* Create a private document and move the node over. + * This is needed so that the strings of the nodes subtree + * get stored in the dictionary of this new document. + */ + // FIXME: Should flag this doc so it wont get returned in + // the method rootDocument + xmlDocPtr tmp = xmlNewDoc((xmlChar *)"1.0"); + + xmlDOMWrapAdoptNode(NULL, node->doc, node, tmp, NULL, 0); + } + else + { + // separate our node from its parent and siblings + xmlUnlinkNode(node); + } } if (parent) @@ -1199,9 +1239,24 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces) node = xmlNewDtd(NULL, (xmlChar *)"", (xmlChar *)"",(xmlChar *)""); break; - case NSXMLEntityDeclarationKind: case NSXMLElementDeclarationKind: - case NSXMLNotationDeclarationKind: + { + xmlElementPtr ret; + ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement)); + memset(ret, 0, sizeof(xmlElement)); + ret->type = XML_ELEMENT_DECL; + ret->name = xmlStrdup((xmlChar *)""); + node = ret; + break; + } + + case NSXMLEntityDeclarationKind: + node = xmlNewEntity(NULL, (xmlChar *)"", 0, (xmlChar *)"", + (xmlChar *)"", (xmlChar *)""); + break; + + case NSXMLNotationDeclarationKind: + // FIXME node = xmlNewNode(NULL, (xmlChar *)""); break;