* Source/NSXMLPrivate.h: Remvoe unused ivars.

* Source/NSXMLDocument.m: Get DTD from node and and validation
in init methods.
* Source/NSXMLDTD.m: Implement.
* Source/NSXMLNode.m: No children for attribute nodes.
* Tests/base/NSXMLNode/basic.m: Test empty attribute children


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34943 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
fredkiefer 2012-03-17 13:57:58 +00:00
parent e91304036b
commit fbccdda56f
6 changed files with 255 additions and 50 deletions

View file

@ -1,3 +1,12 @@
2012-03-17 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSXMLPrivate.h: Remvoe unused ivars.
* Source/NSXMLDocument.m: Get DTD from node and and validation in
init methods.
* Source/NSXMLDTD.m: Implement.
* Source/NSXMLNode.m: No children for attribute nodes.
* Tests/base/NSXMLNode/basic.m: Test empty attribute children
2012-03-16 Fred Kiefer <FredKiefer@gmx.de> 2012-03-16 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSXMLNode.m (-XMLStringWithOptions:): Protect the * Source/NSXMLNode.m (-XMLStringWithOptions:): Protect the

View file

@ -35,7 +35,53 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
+ (NSXMLDTDNode*) predefinedEntityDeclarationForName: (NSString*)name + (NSXMLDTDNode*) predefinedEntityDeclarationForName: (NSString*)name
{ {
[self notImplemented: _cmd]; // 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; return nil;
} }
@ -43,35 +89,100 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
{ {
if (GS_EXISTS_INTERNAL) if (GS_EXISTS_INTERNAL)
{ {
[internal->entities release];
[internal->elements release];
[internal->notations release];
[internal->original release];
} }
[super dealloc]; [super dealloc];
} }
- (void) addChild: (NSXMLNode*)child - (void) addChild: (NSXMLNode*)child
{ {
[self notImplemented: _cmd]; [self insertChild: child atIndex: [self childCount]];
} }
- (NSXMLDTDNode*) attributeDeclarationForName: (NSString*)name - (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; return nil;
} }
- (NSXMLDTDNode*) elementDeclarationForName: (NSString*)name - (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; return nil;
} }
- (NSXMLDTDNode*) entityDeclarationForName: (NSString*)name - (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; return nil;
} }
@ -102,8 +213,27 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
options: (NSUInteger)mask options: (NSUInteger)mask
error: (NSError**)error error: (NSError**)error
{ {
[self notImplemented: _cmd]; NSXMLDocument *tempDoc =
return nil; [[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 - (id) initWithKind: (NSXMLNodeKind)kind options: (NSUInteger)theOptions
@ -122,7 +252,22 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
- (void) insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index - (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 - (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index
@ -138,13 +283,28 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
- (NSXMLDTDNode*) notationDeclarationForName: (NSString*)name - (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 - (NSString*) publicID
@ -156,17 +316,34 @@ GS_PRIVATE_INTERNAL(NSXMLDTD)
- (void) removeChildAtIndex: (NSUInteger)index - (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 - (void) replaceChildAtIndex: (NSUInteger)index withNode: (NSXMLNode*)node
{ {
[self notImplemented: _cmd]; [self insertChild: node atIndex: index];
[self removeChildAtIndex: index + 1];
} }
- (void) setChildren: (NSArray*)children - (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 - (void) setPublicID: (NSString*)publicID

View file

@ -49,7 +49,6 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
{ {
if (GS_EXISTS_INTERNAL) if (GS_EXISTS_INTERNAL)
{ {
[internal->docType release];
[internal->MIMEType release]; [internal->MIMEType release];
} }
[super dealloc]; [super dealloc];
@ -70,7 +69,8 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
- (NSXMLDTD*) DTD - (NSXMLDTD*) DTD
{ {
return internal->docType; xmlDtdPtr dtd = xmlGetIntSubset(internal->node);
return (NSXMLDTD *)[NSXMLNode _objectForNode: (xmlNodePtr)dtd];
} }
- (void) _createInternal - (void) _createInternal
@ -139,10 +139,19 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
code: 0 code: 0
userInfo: nil]; userInfo: nil];
} }
return nil;
} }
// FIXME: Free old node
// Free old node
xmlFreeDoc((xmlDocPtr)internal->node);
[self _setNode: doc]; [self _setNode: doc];
if (mask & NSXMLDocumentValidate)
{
[self validateAndReturnError: error];
}
} }
return self; return self;
} }
@ -221,10 +230,16 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
- (void) setDTD: (NSXMLDTD*)documentTypeDeclaration - (void) setDTD: (NSXMLDTD*)documentTypeDeclaration
{ {
NSXMLDTD *old;
NSAssert(documentTypeDeclaration != nil, NSInvalidArgumentException); NSAssert(documentTypeDeclaration != nil, NSInvalidArgumentException);
// FIXME: do node house keeping, remove ivar, use intSubset
ASSIGNCOPY(internal->docType, documentTypeDeclaration); // detach the old DTD, this also removes the corresponding child
internal->node->extSubset = [documentTypeDeclaration _node]; old = [self DTD];
[old detach];
internal->node->intSubset = (xmlDtdPtr)[documentTypeDeclaration _node];
[self addChild: documentTypeDeclaration];
} }
- (void) setMIMEType: (NSString*)MIMEType - (void) setMIMEType: (NSString*)MIMEType
@ -300,7 +315,7 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
NSAssert(NSXMLNamespaceKind != kind, NSInvalidArgumentException); NSAssert(NSXMLNamespaceKind != kind, NSInvalidArgumentException);
NSAssert(NSXMLNotationDeclarationKind != kind, NSInvalidArgumentException); NSAssert(NSXMLNotationDeclarationKind != kind, NSInvalidArgumentException);
[self _insertChild:child atIndex:index]; [self _insertChild: child atIndex: index];
} }
- (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index - (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index
@ -387,14 +402,16 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
while ((key = [en nextObject]) != nil) while ((key = [en nextObject]) != nil)
{ {
params[index] = (xmlChar *)XMLSTRING(key); params[index] = (xmlChar *)XMLSTRING(key);
params[index+1] = (xmlChar *)XMLSTRING([arguments objectForKey: key]); params[index + 1] = (xmlChar *)XMLSTRING([arguments objectForKey: key]);
index += 2; index += 2;
} }
params[index] = NULL;
params[index + 1] = NULL;
} }
// Apply the stylesheet and get the result... // Apply the stylesheet and get the result...
resultDoc resultDoc = xsltApplyStylesheet(stylesheet, internal->node,
= xsltApplyStylesheet(stylesheet, internal->node, (const char **)params); (const char **)params);
// Cleanup... // Cleanup...
xsltFreeStylesheet(stylesheet); xsltFreeStylesheet(stylesheet);
@ -446,8 +463,8 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
NSXMLDocument *c = (NSXMLDocument*)[super copyWithZone: zone]; NSXMLDocument *c = (NSXMLDocument*)[super copyWithZone: zone];
[c setMIMEType: [self MIMEType]]; [c setMIMEType: [self MIMEType]];
// the extSubset isnt copied by libxml2 // the intSubset is copied by libxml2
[c setDTD: [self DTD]]; //[c setDTD: [self DTD]];
[c setDocumentContentKind: [self documentContentKind]]; [c setDocumentContentKind: [self documentContentKind]];
return c; return c;
} }

View file

@ -538,10 +538,10 @@ clearPrivatePointers(xmlNodePtr aNode)
if (aNode->type == XML_NAMESPACE_DECL) if (aNode->type == XML_NAMESPACE_DECL)
{ {
xmlNsPtr ns = (xmlNsPtr)aNode; xmlNsPtr ns = (xmlNsPtr)aNode;
ns->_private = NULL; ns->_private = NULL;
clearPrivatePointers((xmlNodePtr)ns->next); clearPrivatePointers((xmlNodePtr)(ns->next));
return; return;
} }
@ -551,6 +551,17 @@ clearPrivatePointers(xmlNodePtr aNode)
if (aNode->type == XML_ELEMENT_NODE) if (aNode->type == XML_ELEMENT_NODE)
{ {
clearPrivatePointers((xmlNodePtr)(aNode->properties)); clearPrivatePointers((xmlNodePtr)(aNode->properties));
clearPrivatePointers((xmlNodePtr)(aNode->nsDef));
}
if (aNode->type == XML_ELEMENT_DECL)
{
xmlElementPtr elem = (xmlElementPtr)aNode;
clearPrivatePointers((xmlNodePtr)(elem->attributes));
}
if (aNode->type == XML_DOCUMENT_NODE)
{
xmlDocPtr doc = (xmlDocPtr)aNode;
clearPrivatePointers((xmlNodePtr)(doc->intSubset));
} }
// FIXME: Handle more node types // FIXME: Handle more node types
} }
@ -924,7 +935,8 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
return 0; return 0;
} }
if (node->type == XML_NAMESPACE_DECL) if ((node->type == XML_NAMESPACE_DECL) ||
(node->type == XML_ATTRIBUTE_NODE))
{ {
return 0; return 0;
} }
@ -952,6 +964,7 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
if ((node == NULL) || if ((node == NULL) ||
(node->type == XML_NAMESPACE_DECL) || (node->type == XML_NAMESPACE_DECL) ||
(node->type == XML_ATTRIBUTE_NODE) ||
(node->children == NULL)) (node->children == NULL))
{ {
return nil; return nil;

View file

@ -136,25 +136,15 @@ StringFromXMLString(const unsigned char *bytes, unsigned length)
* is imported and before GSInternal.h is imported. * is imported and before GSInternal.h is imported.
*/ */
#define GS_NSXMLDocument_IVARS SUPERIVARS(GS_NSXMLNode_IVARS) \ #define GS_NSXMLDocument_IVARS SUPERIVARS(GS_NSXMLNode_IVARS) \
NSXMLDTD *docType; \
NSString *MIMEType; \ NSString *MIMEType; \
NSInteger contentKind; \ NSInteger contentKind; \
/* Instance variables for NSXMLDTD with/without the instance /* Instance variables for NSXMLDTD with/without the instance
* variable 'inherited' from NSXMLNode. * variable 'inherited' from NSXMLNode.
* This macro needs to be defined before the NSXMLDTD.h header * This macro needs to be defined before the NSXMLDTD.h header
* is imported and before GSInternal.h is imported. * is imported and before GSInternal.h is imported.
*/ */
#define GS_NSXMLDTD_IVARS SUPERIVARS(GS_NSXMLNode_IVARS) \ #define GS_NSXMLDTD_IVARS SUPERIVARS(GS_NSXMLNode_IVARS)
NSString *publicID; \
NSString *systemID; \
NSMutableDictionary *entities; \
NSMutableDictionary *elements; \
NSMutableDictionary *notations; \
NSMutableDictionary *attributes; \
NSString *original; \
/* Instance variables for NSXMLDTDNode with/without the instance /* Instance variables for NSXMLDTDNode with/without the instance
* variable 'inherited' from NSXMLNode. * variable 'inherited' from NSXMLNode.
@ -229,4 +219,3 @@ StringFromXMLString(const unsigned char *bytes, unsigned length)
#endif /* HAVE_LIBXML */ #endif /* HAVE_LIBXML */
#endif #endif

View file

@ -101,9 +101,9 @@ int main()
PASS_EQUAL([attr URI], nil, "attr node URI is nil"); PASS_EQUAL([attr URI], nil, "attr node URI is nil");
PASS_EQUAL([attr objectValue], @"value", "attr node object value works"); PASS_EQUAL([attr objectValue], @"value", "attr node object value works");
PASS_EQUAL([attr stringValue], @"value", "string value on attr node works"); PASS_EQUAL([attr stringValue], @"value", "string value on attr node works");
// In libxml2 the value is on a child node // In libxml2 the value is on a child node, but we don't report that
//PASS_EQUAL([attr children], nil, "attr node children is nil"); PASS_EQUAL([attr children], nil, "attr node children is nil");
//PASS([attr childCount] == 0, "No child on attr node"); PASS([attr childCount] == 0, "No child on attr node");
[attr setName: @"name"]; [attr setName: @"name"];
PASS_EQUAL([attr name], @"name", PASS_EQUAL([attr name], @"name",