get latest NSXML... changes into our branch

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/branches/nsxml_using_libxml2@35061 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Doug Simons 2012-04-12 21:00:14 +00:00
parent 894e266ec8
commit 40eca0fb8d
6 changed files with 1960 additions and 947 deletions

View file

@ -24,7 +24,11 @@
#import "common.h"
#define GSInternal NSXMLDTDInternal
#if defined(HAVE_LIBXML)
#define GS_XMLNODETYPE xmlDtd
#define GSInternal NSXMLDTDInternal
#import "NSXMLPrivate.h"
#import "GSInternal.h"
GS_PRIVATE_INTERNAL(NSXMLDTD)
@ -33,45 +37,108 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
+ (NSXMLDTDNode*) predefinedEntityDeclarationForName: (NSString*)name
{
[self notImplemented: _cmd];
return nil;
xmlEntityPtr node = xmlGetPredefinedEntity(XMLSTRING(name));
return (NSXMLDTDNode*)[self _objectForNode: (xmlNodePtr)node];
}
- (void) dealloc
{
if (GS_EXISTS_INTERNAL)
{
[internal->publicID release];
[internal->systemID release];
[internal->entities release];
[internal->elements release];
[internal->notations release];
[internal->original release];
}
[super dealloc];
}
- (void) addChild: (NSXMLNode*)child
{
[self notImplemented: _cmd];
[self insertChild: child atIndex: [self childCount]];
}
- (NSXMLDTDNode*) attributeDeclarationForName: (NSString*)name
elementName: (NSString*)elementName
elementName: (NSString*)elementName
{
[self notImplemented: _cmd];
xmlDtdPtr node = internal->node;
xmlNodePtr children = NULL;
const xmlChar *xmlName = XMLSTRING(name);
const xmlChar *xmlElementName = XMLSTRING(elementName);
if ((node == NULL) ||
(node->children == NULL))
{
return nil;
}
for (children = node->children; children; children = children->next)
{
if (children->type == XML_ATTRIBUTE_DECL)
{
xmlAttributePtr attr = (xmlAttributePtr)children;
if ((xmlStrcmp(attr->name, xmlName) == 0) &&
(xmlStrcmp(attr->elem, xmlElementName) == 0))
{
return (NSXMLDTDNode*)[NSXMLNode _objectForNode: children];
}
}
}
return nil;
}
- (NSXMLDTDNode*) elementDeclarationForName: (NSString*)name
{
[self notImplemented: _cmd];
xmlDtdPtr node = internal->node;
xmlNodePtr children = NULL;
const xmlChar *xmlName = XMLSTRING(name);
if ((node == NULL) ||
(node->children == NULL))
{
return nil;
}
for (children = node->children; children; children = children->next)
{
if (children->type == XML_ELEMENT_DECL)
{
xmlElementPtr elem = (xmlElementPtr)children;
if (xmlStrcmp(elem->name, xmlName) == 0)
{
return (NSXMLDTDNode*)[NSXMLNode _objectForNode: children];
}
}
}
return nil;
}
- (NSXMLDTDNode*) entityDeclarationForName: (NSString*)name
{
[self notImplemented: _cmd];
//xmlGetEntityFromDtd
xmlDtdPtr node = internal->node;
xmlNodePtr children = NULL;
const xmlChar *xmlName = XMLSTRING(name);
if ((node == NULL) ||
(node->children == NULL))
{
return nil;
}
for (children = node->children; children; children = children->next)
{
if (children->type == XML_ENTITY_DECL)
{
xmlEntityPtr entity = (xmlEntityPtr)children;
if (xmlStrcmp(entity->name, xmlName) == 0)
{
return (NSXMLDTDNode*)[NSXMLNode _objectForNode: children];
}
}
}
return nil;
}
@ -93,8 +160,8 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
NSXMLDTD *doc;
data = [NSData dataWithContentsOfURL: url];
doc = [self initWithData: data options: 0 error: 0];
[doc setURI: [url absoluteString]];
doc = [self initWithData: data options: mask error: error];
[doc setURI: [url absoluteString]];
return doc;
}
@ -102,25 +169,61 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
options: (NSUInteger)mask
error: (NSError**)error
{
[self notImplemented: _cmd];
return nil;
NSXMLDocument *tempDoc =
[[NSXMLDocument alloc] initWithData: data
options: mask
error: error];
if (tempDoc != nil)
{
NSArray *children = [tempDoc children];
NSEnumerator *enumerator = [children objectEnumerator];
NSXMLNode *child;
self = [self initWithKind: NSXMLDTDKind options: mask];
while ((child = [enumerator nextObject]) != nil)
{
[child detach]; // detach from document.
[self addChild: child];
}
[tempDoc release];
}
return self;
}
- (id) initWithKind: (NSXMLNodeKind)kind options: (NSUInteger)theOptions
{
if (NSXMLDTDKind == kind)
{
/* Create holder for internal instance variables so that we'll have
* all our ivars available rather than just those of the superclass.
*/
GS_CREATE_INTERNAL(NSXMLDTD)
return [super initWithKind: kind options: theOptions];
}
else
{
[self release];
return [[NSXMLNode alloc] initWithKind: kind
options: theOptions];
}
return [super initWithKind: kind options: theOptions];
}
- (void) insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index
{
[self notImplemented: _cmd];
NSXMLNodeKind kind = [child kind];
NSUInteger childCount = [self childCount];
// Check to make sure this is a valid addition...
NSAssert(nil != child, NSInvalidArgumentException);
NSAssert(index <= childCount, NSInvalidArgumentException);
NSAssert(nil == [child parent], NSInvalidArgumentException);
NSAssert(NSXMLAttributeKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLDTDKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLDocumentKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLElementKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLInvalidKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLNamespaceKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLTextKind != kind, NSInvalidArgumentException);
[self _insertChild: child atIndex: index];
}
- (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index
@ -136,57 +239,90 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
- (NSXMLDTDNode*) notationDeclarationForName: (NSString*)name
{
NSXMLDTDNode *notation = [internal->notations objectForKey: name];
xmlDtdPtr node = internal->node;
xmlNodePtr children = NULL;
const xmlChar *xmlName = XMLSTRING(name);
if (notation == nil)
if ((node == NULL) ||
(node->children == NULL))
{
[self notImplemented: _cmd];
return nil;
}
return notation;
for (children = node->children; children; children = children->next)
{
if (children->type == XML_NOTATION_NODE)
{
if (xmlStrcmp(children->name, xmlName) == 0)
{
return (NSXMLDTDNode*)[NSXMLNode _objectForNode: children];
}
}
}
return nil;
}
- (NSString*) publicID
{
if (internal->publicID == nil)
{
[self notImplemented: _cmd];
}
return internal->publicID;
xmlDtd *node = internal->node;
return StringFromXMLStringPtr(node->ExternalID);
}
- (void) removeChildAtIndex: (NSUInteger)index
{
[self notImplemented: _cmd];
NSXMLNode *child;
if (index >= [self childCount])
{
[NSException raise: NSRangeException
format: @"index too large"];
}
child = [self childAtIndex: index];
[child detach];
}
- (void) replaceChildAtIndex: (NSUInteger)index withNode: (NSXMLNode*)node
{
[self notImplemented: _cmd];
[self insertChild: node atIndex: index];
[self removeChildAtIndex: index + 1];
}
- (void) setChildren: (NSArray*)children
{
[self notImplemented: _cmd];
NSUInteger count = [self childCount];
while (count-- > 0)
{
[self removeChildAtIndex: count];
}
[self insertChildren: children atIndex: 0];
}
- (void) setPublicID: (NSString*)publicID
{
[self notImplemented: _cmd];
xmlDtd *node = internal->node;
node->ExternalID = XMLStringCopy(publicID);
}
- (void) setSystemID: (NSString*)systemID
{
[self notImplemented: _cmd];
xmlDtd *node = internal->node;
node->SystemID = XMLStringCopy(systemID);
}
- (NSString*) systemID
{
if (internal->systemID == nil)
{
[self notImplemented: _cmd];
}
return internal->systemID;
xmlDtd *node = internal->node;
return StringFromXMLStringPtr(node->SystemID);
}
@end
#endif /* HAVE_LIBXML */

View file

@ -24,7 +24,11 @@
#import "common.h"
#define GSInternal NSXMLDTDNodeInternal
#if defined(HAVE_LIBXML)
#define GS_XMLNODETYPE xmlEntity
#define GSInternal NSXMLDTDNodeInternal
#import "NSXMLPrivate.h"
#import "GSInternal.h"
GS_PRIVATE_INTERNAL(NSXMLDTDNode)
@ -44,27 +48,44 @@ GS_PRIVATE_INTERNAL(NSXMLDTDNode)
return internal->DTDKind;
}
- (void) _createInternal
{
GS_CREATE_INTERNAL(NSXMLDTDNode);
}
- (id) initWithKind: (NSXMLNodeKind)kind options: (NSUInteger)theOptions
{
if (NSXMLEntityDeclarationKind == kind
|| NSXMLElementDeclarationKind == kind
|| NSXMLNotationDeclarationKind == kind)
{
/* Create holder for internal instance variables so that we'll have
* all our ivars available rather than just those of the superclass.
*/
GS_CREATE_INTERNAL(NSXMLDTDNode)
return [super initWithKind: kind options: theOptions];
}
else
{
[self release];
return [[NSXMLNode alloc] initWithKind: kind
options: theOptions];
}
return [super initWithKind: kind options: theOptions];
}
- (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 childAtIndex: 0]);
[result detach]; // detach from document.
}
[tempDoc release];
[self release];
[self notImplemented: _cmd];
return nil;
return result;
}
- (BOOL) isExternal
@ -78,12 +99,12 @@ GS_PRIVATE_INTERNAL(NSXMLDTDNode)
- (NSString*) notationName
{
return StringFromXMLStringPtr(MY_DTD->name);
return StringFromXMLStringPtr(internal->node->name);
}
- (NSString*) publicID
{
return StringFromXMLStringPtr(MY_DTD->ExternalID);
return StringFromXMLStringPtr(internal->node->ExternalID);
}
- (void) setDTDKind: (NSXMLDTDNodeKind)kind
@ -93,23 +114,24 @@ GS_PRIVATE_INTERNAL(NSXMLDTDNode)
- (void) setNotationName: (NSString*)notationName
{
MY_DTD->name = XMLSTRING(notationName);
internal->node->name = XMLSTRING(notationName);
}
- (void) setPublicID: (NSString*)publicID
{
MY_DTD->ExternalID = XMLSTRING(publicID);
internal->node->ExternalID = XMLSTRING(publicID);
}
- (void) setSystemID: (NSString*)systemID
{
MY_DTD->ExternalID = XMLSTRING(systemID);
internal->node->ExternalID = XMLSTRING(systemID);
}
- (NSString*) systemID
{
return StringFromXMLStringPtr(MY_DTD->SystemID);
return StringFromXMLStringPtr(internal->node->SystemID);
}
@end
#endif /* HAVE_LIBXML */

View file

@ -25,37 +25,19 @@
#import "common.h"
#define GSInternal NSXMLDocumentInternal
#if defined(HAVE_LIBXML)
#define GS_XMLNODETYPE xmlDoc
#define GSInternal NSXMLDocumentInternal
#import "NSXMLPrivate.h"
#import "GSInternal.h"
#ifdef HAVE_LIBXSLT
#import <libxslt/xslt.h>
#import <libxslt/xsltInternals.h>
#import <libxslt/transform.h>
#import <libxslt/xsltutils.h>
#endif
GS_PRIVATE_INTERNAL(NSXMLDocument)
//#import <Foundation/NSXMLParser.h>
#import <Foundation/NSError.h>
#if defined(HAVE_LIBXML)
extern void clearPrivatePointers(xmlNodePtr aNode);
// Private methods to manage libxml pointers...
@interface NSXMLNode (Private)
- (void *) _node;
- (void) _setNode: (void *)_anode;
+ (NSXMLNode *) _objectForNode: (xmlNodePtr)node;
- (void) _addSubNode:(NSXMLNode *)subNode;
- (void) _removeSubNode:(NSXMLNode *)subNode;
- (void) _insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index;
- (id) _initWithNode:(xmlNodePtr)node kind:(NSXMLNodeKind)kind;
@end
@implementation NSXMLDocument
+ (Class) replacementClassForClass: (Class)cls
@ -67,7 +49,6 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
{
if (GS_EXISTS_INTERNAL)
{
[internal->docType release];
[internal->MIMEType release];
}
[super dealloc];
@ -75,8 +56,8 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSString*) characterEncoding
{
if (MY_DOC->encoding)
return [NSString stringWithUTF8String: (const char *)MY_DOC->encoding];
if (internal->node->encoding)
return StringFromXMLStringPtr(internal->node->encoding);
else
return nil;
}
@ -88,7 +69,8 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSXMLDTD*) DTD
{
return internal->docType;
xmlDtdPtr dtd = xmlGetIntSubset(internal->node);
return (NSXMLDTD *)[NSXMLNode _objectForNode: (xmlNodePtr)dtd];
}
- (void) _createInternal
@ -114,7 +96,6 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
return doc;
}
- (id) initWithData: (NSData*)data
options: (NSUInteger)mask
error: (NSError**)error
@ -158,9 +139,19 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
code: 0
userInfo: nil];
}
return nil;
}
// Free old node
xmlFreeDoc((xmlDocPtr)internal->node);
[self _setNode: doc];
if (mask & NSXMLDocumentValidate)
{
[self validateAndReturnError: error];
}
}
return self;
}
@ -174,7 +165,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
{
[self release];
return [[NSXMLNode alloc] initWithKind: kind
options: theOptions];
options: theOptions];
}
}
@ -213,7 +204,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (BOOL) isStandalone
{
return (MY_DOC->standalone == 1);
return (internal->node->standalone == 1);
}
- (NSString*) MIMEType
@ -223,13 +214,17 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSXMLElement*) rootElement
{
xmlNodePtr rootElem = xmlDocGetRootElement(MY_DOC);
xmlNodePtr rootElem = xmlDocGetRootElement(internal->node);
return (NSXMLElement *)[NSXMLNode _objectForNode: rootElem];
}
- (void) setCharacterEncoding: (NSString*)encoding
{
MY_DOC->encoding = xmlStrdup(XMLSTRING(encoding));
if (internal->node->encoding != NULL)
{
xmlFree((xmlChar *)internal->node->encoding);
}
internal->node->encoding = XMLStringCopy(encoding);
}
- (void) setDocumentContentKind: (NSXMLDocumentContentKind)kind
@ -239,9 +234,16 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (void) setDTD: (NSXMLDTD*)documentTypeDeclaration
{
NSXMLDTD *old;
NSAssert(documentTypeDeclaration != nil, NSInvalidArgumentException);
ASSIGNCOPY(internal->docType, documentTypeDeclaration);
MY_DOC->extSubset = [documentTypeDeclaration _node];
// detach the old DTD, this also removes the corresponding child
old = [self DTD];
[old detach];
internal->node->intSubset = (xmlDtdPtr)[documentTypeDeclaration _node];
[self addChild: documentTypeDeclaration];
}
- (void) setMIMEType: (NSString*)MIMEType
@ -251,8 +253,6 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (void) setRootElement: (NSXMLNode*)root
{
id oldElement = [self rootElement];
if (root == nil)
{
return;
@ -265,24 +265,58 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
self];
}
xmlDocSetRootElement(MY_DOC, [root _node]);
// remove all sub nodes
[self setChildren: nil];
// FIXME: Should we use addChild: here?
xmlDocSetRootElement(internal->node, [root _node]);
// Do our subNode housekeeping...
[self _removeSubNode: oldElement];
[self _addSubNode: root];
}
- (void) setStandalone: (BOOL)standalone
{
MY_DOC->standalone = standalone;
internal->node->standalone = standalone;
}
- (void) setURI: (NSString*)URI
{
xmlDocPtr node = internal->node;
if (node->URL != NULL)
{
xmlFree((xmlChar *)node->URL);
}
node->URL = XMLStringCopy(URI);
}
- (NSString*) URI
{
xmlDocPtr node = internal->node;
if (node->URL)
{
return StringFromXMLStringPtr(node->URL);
}
else
{
return nil;
}
}
- (void) setVersion: (NSString*)version
{
if ([version isEqualToString: @"1.0"] || [version isEqualToString: @"1.1"])
{
MY_DOC->version = XMLStringCopy(version);
}
xmlDocPtr node = internal->node;
if (node->version != NULL)
{
xmlFree((xmlChar *)node->version);
}
node->version = XMLStringCopy(version);
}
else
{
[NSException raise: NSInvalidArgumentException
@ -292,8 +326,10 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSString*) version
{
if (MY_DOC->version)
return StringFromXMLStringPtr(MY_DOC->version);
xmlDocPtr node = internal->node;
if (node->version)
return StringFromXMLStringPtr(node->version);
else
return @"1.0";
}
@ -317,7 +353,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
NSAssert(NSXMLNamespaceKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLNotationDeclarationKind != kind, NSInvalidArgumentException);
[self _insertChild:child atIndex:index];
[self _insertChild: child atIndex: index];
}
- (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index
@ -376,25 +412,9 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSData *) XMLDataWithOptions: (NSUInteger)options
{
NSString *xmlString = [self XMLStringWithOptions: options];
NSData *data = [NSData dataWithBytes: [xmlString UTF8String]
length: [xmlString length]];
return data;
}
- (NSString *) XMLStringWithOptions: (NSUInteger)options
{
NSString *string = nil;
xmlChar *buf = NULL;
int length;
xmlDocDumpFormatMemoryEnc(MY_DOC, &buf, &length, "utf-8", 1);
if (buf != 0 && length > 0)
{
string = StringFromXMLString(buf, length);
free(buf);
}
return string;
return [xmlString dataUsingEncoding: NSUTF8StringEncoding
allowLossyConversion: NO];
}
- (id) objectByApplyingXSLT: (NSData*)xslt
@ -420,13 +440,16 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
while ((key = [en nextObject]) != nil)
{
params[index] = (xmlChar *)XMLSTRING(key);
params[index+1] = (xmlChar *)XMLSTRING([arguments objectForKey: key]);
params[index + 1] = (xmlChar *)XMLSTRING([arguments objectForKey: key]);
index += 2;
}
params[index] = NULL;
params[index + 1] = NULL;
}
// Apply the stylesheet and get the result...
resultDoc = xsltApplyStylesheet(stylesheet, MY_DOC, (const char **)params);
resultDoc = xsltApplyStylesheet(stylesheet, internal->node,
(const char **)params);
// Cleanup...
xsltFreeStylesheet(stylesheet);
@ -468,14 +491,20 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
xmlValidCtxtPtr ctxt = xmlNewValidCtxt();
// FIXME: Should use xmlValidityErrorFunc and userData
// to get the error
BOOL result = (BOOL)(xmlValidateDocument(ctxt, MY_DOC));
BOOL result = (BOOL)(xmlValidateDocument(ctxt, internal->node));
xmlFreeValidCtxt(ctxt);
return result;
}
- (xmlNodePtr) _copyNode
- (id) copyWithZone: (NSZone *)zone
{
return (xmlNodePtr)xmlCopyDoc(MY_DOC, 1); // make a deep copy
NSXMLDocument *c = (NSXMLDocument*)[super copyWithZone: zone];
[c setMIMEType: [self MIMEType]];
// the intSubset is copied by libxml2
//[c setDTD: [self DTD]];
[c setDocumentContentKind: [self documentContentKind]];
return c;
}
- (BOOL) isEqual: (id)other
@ -484,6 +513,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
{
return YES;
}
// FIXME
return [[self rootElement] isEqual: [other rootElement]];
}
@end

View file

@ -24,41 +24,39 @@
#import "common.h"
#define GSInternal NSXMLElementInternal
#if defined(HAVE_LIBXML)
#define GSInternal NSXMLElementInternal
#define GS_XMLNODETYPE xmlNode
#import "NSXMLPrivate.h"
#import "GSInternal.h"
GS_PRIVATE_INTERNAL(NSXMLElement)
#if defined(HAVE_LIBXML)
extern void clearPrivatePointers(xmlNodePtr aNode);
// Private methods to manage libxml pointers...
@interface NSXMLNode (Private)
- (void *) _node;
- (void) _setNode: (void *)_anode;
+ (NSXMLNode *) _objectForNode: (xmlNodePtr)node;
- (void) _addSubNode:(NSXMLNode *)subNode;
- (void) _removeSubNode:(NSXMLNode *)subNode;
- (id) _initWithNode:(xmlNodePtr)node kind:(NSXMLNodeKind)kind;
- (void) _insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index;
- (void) _updateExternalRetains;
- (void) _invalidate;
@end
extern void cleanup_namespaces(xmlNodePtr node, xmlNsPtr ns);
extern void ensure_oldNs(xmlNodePtr node);
@implementation NSXMLElement
- (void) dealloc
{
/*
if (GS_EXISTS_INTERNAL && _internal != nil)
if (GS_EXISTS_INTERNAL && internal != nil)
{
while ([self childCount] > 0)
{
[self removeChildAtIndex: [self childCount] - 1];
}
/*
NSArray *subNodes = [internal->subNodes copy];
NSEnumerator *enumerator = [subNodes objectEnumerator];
NSXMLNode *subNode;
while ((subNode = [enumerator nextObject]) != nil)
{
if ([subNode kind] == NSXMLNamespaceKind)
{
[self removeNamespaceForPrefix: [subNode name]];
}
}
*/
}
*/
[super dealloc];
}
@ -76,17 +74,13 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
{
if (NSXMLElementKind == kind)
{
if ((self = [super initWithKind:kind options:theOptions]))
{
internal->objectValue = @"";
}
return self;
return [super initWithKind: kind options: theOptions];
}
else
{
[self release];
return [[NSXMLNode alloc] initWithKind: kind
options: theOptions];
options: theOptions];
}
}
@ -97,26 +91,30 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (id) initWithName: (NSString*)name URI: (NSString*)URI
{
if ((self = [super initWithKind: NSXMLElementKind]) != nil)
if ((self = [self initWithKind: NSXMLElementKind]) != nil)
{
[self setName:name];
ASSIGNCOPY(internal->URI, URI);
internal->objectValue = @"";
[self setName: name];
// Without this check this could unset a namespace set via the name
if (URI != nil)
{
[self setURI: URI];
}
}
return self;
}
- (id) initWithName: (NSString*)name stringValue: (NSString*)string
{
if ([self initWithName: name URI: nil] != nil)
if ((self = [self initWithName: name URI: nil]) != nil)
{
NSXMLNode *t;
t = [[NSXMLNode alloc] initWithKind: NSXMLTextKind];
[t setStringValue: string];
[self addChild: t];
[t release];
}
return nil;
return self;
}
- (id) initWithXMLString: (NSString*)string
@ -133,99 +131,228 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
[result detach]; // detach from document.
}
[tempDoc release];
[self release];
return result;
}
- (id) objectValue
{
if (internal->objectValue == nil)
{
return @"";
}
return internal->objectValue;
}
- (NSArray*) elementsForName: (NSString*)name
{
NSString *prefix = [[self class] prefixForName: name];
if ((nil != prefix) && [prefix length] > 0)
{
NSXMLNode *ns = [self namespaceForPrefix: prefix];
if (nil != ns)
{
NSString *localName = [[self class] localNameForName: name];
// Namespace nodes have the URI as their stringValue
return [self elementsForLocalName: localName URI: [ns stringValue]];
}
}
{
NSMutableArray *results = [NSMutableArray arrayWithCapacity: 10];
xmlNodePtr cur = NULL;
const xmlChar *xmlName = XMLSTRING(name);
for (cur = internal->node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE)
{
// no namespace or default namespace
if ((xmlStrcmp(xmlName, cur->name) == 0) &&
((cur->ns == NULL) || (cur->ns->prefix == NULL) ||
(xmlStrcmp(cur->ns->prefix, (const xmlChar*)"") == 0)))
{
NSXMLNode *node = [NSXMLNode _objectForNode: cur];
[results addObject: node];
}
}
}
return results;
}
}
- (NSArray*) elementsForLocalName: (NSString*)localName URI: (NSString*)URI
{
NSMutableArray *results = [NSMutableArray arrayWithCapacity: 10];
xmlNodePtr cur = NULL;
const xmlChar *href = XMLSTRING(URI);
const xmlChar *xmlName = XMLSTRING(localName);
xmlNsPtr parentNS = xmlSearchNsByHref(internal->node->doc, internal->node, href);
for (cur = MY_NODE->children; cur != NULL; cur = cur->next)
for (cur = internal->node->children; cur != NULL; cur = cur->next)
{
NSString *n = StringFromXMLStringPtr(cur->name);
if ([n isEqualToString: name])
{
NSXMLNode *node = (NSXMLNode *)(cur->_private);
[results addObject: node];
}
if (cur->type == XML_ELEMENT_NODE)
{
if (xmlStrcmp(xmlName, cur->name) == 0)
{
xmlNsPtr childNS = parentNS;
if (cur->nsDef != NULL)
{
childNS = xmlSearchNsByHref(internal->node->doc, cur, href);
}
if (((childNS != NULL) &&
((cur->ns == childNS) ||
((cur->ns == NULL) &&
(xmlStrcmp(childNS->prefix, (const xmlChar*)"") == 0)))) ||
((cur->ns != NULL) && (xmlStrcmp(cur->ns->href, href) == 0)))
{
NSXMLNode *node = [NSXMLNode _objectForNode: cur];
[results addObject: node];
}
}
}
}
return results;
}
- (NSArray*) elementsForLocalName: (NSString*)localName URI: (NSString*)URI
{
[self notImplemented: _cmd];
return nil;
}
- (void) addAttribute: (NSXMLNode*)attribute
{
xmlNodePtr node = (xmlNodePtr)(internal->node);
xmlNodePtr node = internal->node;
xmlAttrPtr attr = (xmlAttrPtr)[attribute _node];
xmlAttrPtr oldAttr = xmlHasProp(node, attr->name);
xmlAttrPtr oldAttr;
if (nil != [attribute parent])
{
[NSException raise: @"NSInvalidArgumentException"
format: @"Tried to add attribute to multiple parents."];
}
{
[NSException raise: NSInternalInconsistencyException
format: @"Tried to add attribute to multiple parents."];
}
if (attr->ns != NULL)
{
xmlNsPtr ns = attr->ns;
xmlDocPtr tmp = attr->doc;
BOOL resolved = NO;
if (ns->href == NULL)
{
xmlNsPtr newNs = xmlSearchNs(node->doc, node, ns->prefix);
if (newNs != NULL)
{
ns = newNs;
attr->ns = ns;
resolved = YES;
}
}
else //if (ns->prefix == NULL)
{
xmlNsPtr newNs = xmlSearchNsByHref(node->doc, node, ns->href);
if (newNs != NULL)
{
ns = newNs;
attr->ns = ns;
resolved = YES;
}
}
if (!resolved && (tmp != NULL))
{
xmlNsPtr cur = tmp->oldNs;
xmlNsPtr last = NULL;
xmlNsPtr oldNs1;
// Need to transfer the namespace to the new tree
// Unlink in old
while (cur)
{
if (cur == ns)
{
if (last == NULL)
{
tmp->oldNs = NULL;
}
else
{
last->next = ns->next;
}
cur->next = NULL;
break;
}
cur = cur->next;
}
// Insert in new
ensure_oldNs(node);
oldNs1 = node->doc->oldNs;
while (oldNs1)
{
if (oldNs1->next == NULL)
{
oldNs1->next = cur;
break;
}
oldNs1 = oldNs1->next;
}
}
#if LIBXML_VERSION >= 20620
xmlDOMWrapAdoptNode(NULL, attr->doc, (xmlNodePtr)attr,
node->doc, node, 0);
#else
xmlSetTreeDoc((xmlNodePtr)attr, node->doc);
#endif
xmlFreeDoc(tmp);
oldAttr = xmlHasNsProp(node, attr->name, ns->href);
}
else
{
oldAttr = xmlHasProp(node, attr->name);
}
if (NULL != oldAttr)
{
/*
* As per Cocoa documentation, we only add the attribute if it's not
* already set. xmlHasProp() also looks at the DTD for default attributes
* and we need to make sure that we only bail out here on #FIXED
* attributes.
*/
{
/*
* As per Cocoa documentation, we only add the attribute if it's not
* already set. xmlHasProp() also looks at the DTD for default attributes
* and we need to make sure that we only bail out here on #FIXED
* attributes.
*/
// Do not replace plain attributes.
if (XML_ATTRIBUTE_NODE == oldAttr->type)
// Do not replace plain attributes.
if (XML_ATTRIBUTE_NODE == oldAttr->type)
{
return;
}
else if (XML_ATTRIBUTE_DECL == oldAttr->type)
else if (XML_ATTRIBUTE_DECL == oldAttr->type)
{
// If the attribute is from a DTD, do not replace it if it's #FIXED
xmlAttributePtr attrDecl = (xmlAttributePtr)oldAttr;
if (XML_ATTRIBUTE_FIXED == attrDecl->def)
{
return;
}
// If the attribute is from a DTD, do not replace it if it's #FIXED
xmlAttributePtr attrDecl = (xmlAttributePtr)oldAttr;
if (XML_ATTRIBUTE_FIXED == attrDecl->def)
{
return;
}
}
}
}
xmlAddChild(node, (xmlNodePtr)attr);
[self _addSubNode:attribute];
[self _addSubNode: attribute];
}
- (void) removeAttributeForName: (NSString*)name
{
xmlNodePtr node = (xmlNodePtr)(internal->node);
xmlAttrPtr attr = xmlHasProp(node, (xmlChar *)[name UTF8String]);
xmlAttrPtr newAttr = NULL;
NSXMLNode *attrNode = nil;
if (NULL == attr)
{
return;
}
NSXMLNode *attrNode = [self attributeForName: name];
// We need a copy of the node because xmlRemoveProp() frees attr:
newAttr = xmlCopyProp(NULL, attr);
attrNode = [NSXMLNode _objectForNode: (xmlNodePtr)attr];
// This is supposed to return failure for DTD defined attributes
if (0 == xmlRemoveProp(attr))
{
[attrNode _setNode: newAttr];
[self _removeSubNode: attrNode];
}
else
{
// In this case we throw away our copy again.
xmlFreeProp(newAttr);
}
[attrNode detach];
}
- (void) setAttributes: (NSArray*)attributes
@ -233,6 +360,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
NSEnumerator *enumerator = [attributes objectEnumerator];
NSXMLNode *attribute;
// FIXME: Remove all previous attributes
while ((attribute = [enumerator nextObject]) != nil)
{
[self addAttribute: attribute];
@ -249,7 +377,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
NSEnumerator *en = [attributes keyEnumerator];
NSString *key;
// [internal->attributes removeAllObjects];
// FIXME: Remove all previous attributes
while ((key = [en nextObject]) != nil)
{
NSString *val = [[attributes objectForKey: key] stringValue];
@ -262,12 +390,15 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSArray*) attributes
{
NSMutableArray *attributes = [NSMutableArray array];
xmlNodePtr node = MY_NODE;
struct _xmlAttr * attributeNode = node->properties;
xmlNodePtr node = internal->node;
xmlAttrPtr attributeNode = node->properties;
while (attributeNode)
{
NSXMLNode *attribute = [NSXMLNode _objectForNode:(xmlNodePtr)attributeNode];
[attributes addObject:attribute];
NSXMLNode *attribute;
attribute = [NSXMLNode _objectForNode: (xmlNodePtr)attributeNode];
[attributes addObject: attribute];
attributeNode = attributeNode->next;
}
return attributes;
@ -275,93 +406,182 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSXMLNode*) attributeForName: (NSString*)name
{
NSXMLNode *result = nil;
xmlChar *xmlName = xmlCharStrdup([name UTF8String]);
xmlAttrPtr attributeNode = xmlHasProp(MY_NODE, xmlName);
if (NULL != attributeNode)
NSString *prefix = [[self class] prefixForName: name];
if ((nil != prefix) && [prefix length] > 0)
{
NSXMLNode *ns = [self namespaceForPrefix: prefix];
if (nil != ns)
{
NSString *localName = [[self class] localNameForName: name];
// Namespace nodes have the URI as their stringValue
return [self attributeForLocalName: localName URI: [ns stringValue]];
}
}
{
result = [NSXMLNode _objectForNode:(xmlNodePtr)attributeNode];
NSXMLNode *result = nil;
xmlNodePtr node = internal->node;
xmlAttrPtr attributeNode = xmlHasProp(node, XMLSTRING(name));
if (NULL != attributeNode)
{
result = [NSXMLNode _objectForNode: (xmlNodePtr)attributeNode];
}
return result;
}
free(xmlName); // Free the name string since it's no longer needed.
xmlName = NULL;
return result; // [internal->attributes objectForKey: name];
}
- (NSXMLNode*) attributeForLocalName: (NSString*)localName
URI: (NSString*)URI
{
[self notImplemented: _cmd];
return nil;
NSXMLNode *result = nil;
xmlNodePtr node = internal->node;
xmlAttrPtr attributeNode = xmlHasNsProp(node, XMLSTRING(localName),
XMLSTRING(URI));
if (NULL != attributeNode)
{
result = [NSXMLNode _objectForNode: (xmlNodePtr)attributeNode];
}
return result;
}
- (void) addNamespace: (NSXMLNode*)aNamespace
{
xmlNsPtr ns = (xmlNsPtr)[aNamespace _node];
xmlNsPtr ns = xmlCopyNamespace((xmlNsPtr)[aNamespace _node]);
xmlNodePtr node = internal->node;
const xmlChar *prefix = ns->prefix;
if (MY_NODE->ns == NULL)
if (node->nsDef == NULL)
{
MY_NODE->ns = ns;
node->nsDef = ns;
}
else
{
xmlNsPtr cur = MY_NODE->ns;
const xmlChar *prefix = ns->prefix;
xmlNsPtr cur = node->nsDef;
xmlNsPtr last = NULL;
while (xmlStrcmp(prefix, cur->prefix) != 0)
while (cur != NULL)
{
if ((prefix != NULL) &&
(cur->prefix != NULL) &&
(xmlStrcmp(prefix, cur->prefix) == 0))
{
break;
}
if (cur->next == NULL)
{
cur->next = ns;
return;
}
last = cur;
cur = cur->next;
}
// Found the same prefix
if (cur->href == NULL)
{
// This was a fake namespace we added
if (node->ns == cur)
{
node->ns = ns;
}
if (last == NULL)
{
node->nsDef = ns;
}
else
{
last->next = ns;
}
ns->next = cur->next;
cur->next = NULL;
}
}
// Are we setting a default namespace?
if ((node->ns == NULL) && (xmlStrcmp(prefix, (const xmlChar*)"") == 0))
{
node->ns = ns;
}
// Need to replace fake namespaces in subnodes
cleanup_namespaces(node, ns);
}
- (void) removeNamespaceForPrefix: (NSString*)name
{
[self notImplemented: _cmd];
xmlNodePtr node = internal->node;
if (node->nsDef != NULL)
{
xmlNsPtr cur = node->nsDef;
xmlNsPtr last = NULL;
const xmlChar *prefix = XMLSTRING(name);
while (cur != NULL)
{
if ((cur->prefix != NULL) &&
(xmlStrcmp(prefix, cur->prefix) == 0))
{
if (last == NULL)
{
internal->node->nsDef = cur->next;
}
else
{
last->next = cur->next;
}
cur->next = NULL;
if (node->ns == cur)
{
node->ns = NULL;
}
xmlFreeNs(cur);
return;
}
last = cur;
cur = cur->next;
}
}
}
- (void) setNamespaces: (NSArray*)namespaces
{
NSEnumerator *en = [namespaces objectEnumerator];
NSXMLNode *namespace = nil;
xmlNsPtr cur = NULL;
// FIXME: Remove old namespaces
// xmlFreeNsList(MY_NODE->ns);
// MY_NODE->ns = NULL;
// Remove old namespaces
xmlFreeNsList(internal->node->nsDef);
internal->node->nsDef = NULL;
// Add new ones
while ((namespace = (NSXMLNode *)[en nextObject]) != nil)
{
xmlNsPtr ns = (xmlNsPtr)[namespace _node];
if (MY_NODE->ns == NULL)
{
MY_NODE->ns = ns;
cur = ns;
}
else
{
cur->next = ns;
cur = ns;
}
[self addNamespace: namespace];
}
}
- (NSArray*) namespaces
{
// FIXME: Should use xmlGetNsList()
// FIXME: Should we use xmlGetNsList()?
NSMutableArray *result = nil;
xmlNsPtr ns = MY_NODE->ns;
xmlNsPtr ns = internal->node->nsDef;
if (ns)
{
xmlNsPtr cur = NULL;
result = [NSMutableArray array];
for (cur = ns; cur != NULL; cur = cur->next)
{
[result addObject: [NSXMLNode _objectForNode: (xmlNodePtr)cur]];
[result addObject: [NSXMLNode _objectForNode:
(xmlNodePtr)xmlCopyNamespace(cur)]];
}
}
@ -370,19 +590,23 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSXMLNode*) namespaceForPrefix: (NSString*)name
{
// FIXME: Should use xmlSearchNs()
xmlNsPtr ns = MY_NODE->ns;
if (ns)
if (name != nil)
{
const xmlChar *prefix = XMLSTRING(name);
xmlNsPtr cur = NULL;
for (cur = ns; cur != NULL; cur = cur->next)
{
if (xmlStrcmp(prefix, cur->prefix) == 0)
{
return [NSXMLNode _objectForNode: (xmlNodePtr)cur];
}
}
xmlNodePtr node = internal->node;
xmlNsPtr ns;
ns = xmlSearchNs(node->doc, node, prefix);
if ((ns == NULL) && ([name length] == 0))
{
prefix = NULL;
ns = xmlSearchNs(node->doc, node, prefix);
}
if (ns != NULL)
{
return [NSXMLNode _objectForNode: (xmlNodePtr)xmlCopyNamespace(ns)];
}
}
return nil;
@ -392,6 +616,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
{
NSString *prefix = [[self class] prefixForName: name];
// Return the default namespace for an empty prefix
if (nil != prefix)
{
return [self namespaceForPrefix: prefix];
@ -402,20 +627,12 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSString*) resolvePrefixForNamespaceURI: (NSString*)namespaceURI
{
// FIXME Should use xmlSearchNsByHref()
xmlNsPtr ns = MY_NODE->ns;
const xmlChar *uri = XMLSTRING(namespaceURI);
xmlNsPtr ns = xmlSearchNsByHref(internal->node->doc, internal->node, uri);
if (ns)
{
const xmlChar *uri = XMLSTRING(namespaceURI);
xmlNsPtr cur = NULL;
for (cur = ns; cur != NULL; cur = cur->next)
{
if (xmlStrcmp(uri, cur->href) == 0)
{
return StringFromXMLStringPtr(cur->prefix);
}
}
return StringFromXMLStringPtr(ns->prefix);
}
return nil;
@ -460,7 +677,7 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
if (index >= [self childCount])
{
[NSException raise: NSRangeException
format: @"index too large"];
format: @"index too large"];
}
child = [self childAtIndex: index];
@ -490,9 +707,11 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
[self removeChildAtIndex: index + 1];
}
static void joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *nodesToDelete)
static void
joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *nodesToDelete)
{
NSXMLNode *objA = (nodeA->_private), *objB = (nodeB->_private);
NSXMLNode *objA = (nodeA->_private);
NSXMLNode *objB = (nodeB->_private);
xmlTextMerge(nodeA, nodeB); // merge nodeB into nodeA
@ -500,13 +719,16 @@ static void joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *no
{
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];
/* set it to be invalid and make sure it's not
* pointing to a freed node
*/
[objB _invalidate];
[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
[objB _setNode: nodeA]; // nodeA is the remaining (merged) node
}
}
@ -515,29 +737,41 @@ static void joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *no
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))
{
[(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)))
|| (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)))
|| (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??)
/* 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);
}
@ -548,21 +782,11 @@ static void joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *no
subEnum = [nodesToDelete objectEnumerator];
while ((subNode = [subEnum nextObject]))
{
[self _removeSubNode:subNode];
[self _removeSubNode: subNode];
}
[self _updateExternalRetains];
}
}
- (id) copyWithZone: (NSZone *)zone
{
NSXMLElement *c = [[self class] alloc]; ///(NSXMLElement*)[super copyWithZone: zone];
xmlNodePtr newNode = (xmlNodePtr)xmlCopyNode(MY_NODE, 1); // copy recursively
clearPrivatePointers(newNode); // clear out all of the _private pointers in the entire tree
c = [c _initWithNode:newNode kind:internal->kind];
return c;
}
@end
#endif
#endif /* HAVE_LIBXML */

File diff suppressed because it is too large Load diff

View file

@ -25,8 +25,35 @@
#ifndef _INCLUDED_NSXMLPRIVATE_H
#define _INCLUDED_NSXMLPRIVATE_H
#import "config.h"
#import "GNUstepBase/GSConfig.h"
#import "common.h"
#ifdef HAVE_LIBXML
/* Avoid problems on systems where the xml headers use 'id'
*/
#define id GSXMLID
/* libxml headers */
#include <libxml/tree.h>
#include <libxml/entities.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/HTMLparser.h>
#include <libxml/xmlmemory.h>
#include <libxml/xmlsave.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#ifdef HAVE_LIBXSLT
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#endif /* HAVE_LIBXSLT */
#undef id
#endif /* HAVE_LIBXML */
#define EXPOSE_NSXMLDTD_IVARS 1
#define EXPOSE_NSXMLDTDNode_IVARS 1
@ -42,7 +69,9 @@
inline static unsigned char *XMLStringCopy(NSString *source)
{
char *xmlstr;
unsigned int len = [source maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;
unsigned int len;
len = [source maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;
if (len == 0)
return NULL;
xmlstr = malloc(len);
@ -80,38 +109,40 @@ StringFromXMLString(const unsigned char *bytes, unsigned length)
return AUTORELEASE(str);
}
#define MY_DOC ((xmlDoc *)internal->node)
#define MY_NODE ((xmlNode *)internal->node)
#define MY_ATTR ((xmlAttr *)internal->node)
#define MY_ELEM ((xmlElement *)internal->node)
#define MY_DTD ((xmlDtd *)internal->node)
/* Instance variables for NSXMLNode. This macro needs to be defined before
* the NSXMLNode.h header is imported and before GSInternal.h is imported.
*
* Description of internal ivars:
* - `children': The primary storage for the descendant nodes. We use an NSArray
* here until somebody finds out it's not fast enough.
* - `childCount': For efficiency, we cache the count. This means we need to
* update it whenever the children change.
* - `previousSibling', `nextSibling': Tree walking is a common operation for
* XML. [parent->children objectAtIndex: index + 1] would be a
* straightforward way to obtain the next sibling of the node, but it hurts
* performance quite a bit. So we cache the siblings and update them when the
* nodes are changed.
* The 'kind' tells us what sort of node this is.
* The 'node' points to the underlying libxml2 node structure.
* The 'options' field is a bitmask of options for this node.
* The 'objectValue' is the object value set for the node.
* The 'subNodes' array is used to retain the objects pointed to by subnodes.
*
* When we create an Objective-C object for a node we also create objects
* for all parents up to the root object. (Reusing existing once as we find
* them in the _private points of parent nodes)
* This adds the object to the subnode array of the parent object, retaining
* the object in this process.
* This means a document object will retain all the objects we have created
* for its node tree, but we don't have to create all these objects at once.
* When we remove an object from its parent we always call the detach method.
* Here we unlink the libxml2 node and remove the object from its parent's
* subnode array, This will release the object.
* When an object gets deallocated it detaches all the subnodes, releasing
* them in the process and then it frees the node. That way each object takes
* care of freeing its own node, but nodes that don't have objects attached
* to them will get freed when their parent object (e.g. the NSXMLDocument)
* gets deallocated.
* For namespace nodes special rules apply as they don't have a parent pointer.
*
* URI is probably not needed at all ... I'm not sure
*/
#define GS_NSXMLNode_IVARS \
NSUInteger kind; \
NSXMLNode *parent; \
id objectValue; \
NSString *URI; \
NSXMLNode *previousSibling; \
NSXMLNode *nextSibling;\
GS_XMLNODETYPE *node; \
NSUInteger options; \
void *node; \
NSMutableArray *subNodes; \
int externalRetains; \
int retainedSelf; \
id objectValue; \
NSMutableArray *subNodes;
/* When using the non-fragile ABI, the instance variables are exposed to the
@ -132,25 +163,15 @@ StringFromXMLString(const unsigned char *bytes, unsigned length)
* is imported and before GSInternal.h is imported.
*/
#define GS_NSXMLDocument_IVARS SUPERIVARS(GS_NSXMLNode_IVARS) \
NSXMLDTD *docType; \
NSString *MIMEType; \
NSInteger contentKind; \
/* Instance variables for NSXMLDTD with/without the instance
* variable 'inherited' from NSXMLNode.
* This macro needs to be defined before the NSXMLDTD.h header
* is imported and before GSInternal.h is imported.
*/
#define GS_NSXMLDTD_IVARS SUPERIVARS(GS_NSXMLNode_IVARS) \
NSString *publicID; \
NSString *systemID; \
NSMutableDictionary *entities; \
NSMutableDictionary *elements; \
NSMutableDictionary *notations; \
NSMutableDictionary *attributes; \
NSString *original; \
#define GS_NSXMLDTD_IVARS SUPERIVARS(GS_NSXMLNode_IVARS)
/* Instance variables for NSXMLDTDNode with/without the instance
* variable 'inherited' from NSXMLNode.
@ -167,6 +188,7 @@ StringFromXMLString(const unsigned char *bytes, unsigned length)
*/
#define GS_NSXMLElement_IVARS SUPERIVARS(GS_NSXMLNode_IVARS)
#import "Foundation/NSArray.h"
#import "Foundation/NSData.h"
#import "Foundation/NSDebug.h"
@ -184,30 +206,19 @@ StringFromXMLString(const unsigned char *bytes, unsigned length)
#ifdef HAVE_LIBXML
/* Avoid problems on systems where the xml headers use 'id'
*/
#define id GSXMLID
/* libxml headers */
#include <libxml/tree.h>
#include <libxml/entities.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/HTMLparser.h>
#include <libxml/xmlmemory.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#ifdef HAVE_LIBXSLT
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#endif /* HAVE_LIBXSLT */
#undef id
// Private methods to manage libxml pointers...
@interface NSXMLNode (Private)
- (void *) _node;
- (void) _setNode: (void *)_anode;
+ (NSXMLNode *) _objectForNode: (xmlNodePtr)node;
- (void) _addSubNode: (NSXMLNode *)subNode;
- (void) _removeSubNode: (NSXMLNode *)subNode;
- (id) _initWithNode: (xmlNodePtr)node kind: (NSXMLNodeKind)kind;
- (xmlNodePtr) _childNodeAtIndex: (NSUInteger)index;
- (void) _insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index;
- (void) _invalidate;
@end
#endif /* HAVE_LIBXML */
#endif