// // MGMXMLElement.m // MGMXML // // Created by Mr. Gecko on 9/22/10. // Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // // Permission to use, copy, modify, and/or distribute this software for any purpose // with or without fee is hereby granted, provided that the above copyright notice // and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, // OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, // DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS // ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // #import "MGMXMLElement.h" #import "MGMXMLDocument.h" #import "MGMXMLAddons.h" @implementation MGMXMLElement - (id)initWithXMLString:(NSString *)string error:(NSError **)error { [super release]; MGMXMLDocument *document = [[MGMXMLDocument alloc] initWithXMLString:string options:0 error:error]; MGMXMLElement *element = nil; if (document!=nil) { element = [[document rootElement] retain]; if (element!=nil) [element detach]; [document release]; } return element; } - (NSArray *)elementsForName:(NSString *)name URI:(NSString *)URI resolvingNamespacePrefix:(BOOL)resolveNamespacePrefix { NSMutableArray *elements = [NSMutableArray array]; if (resolveNamespacePrefix && URI!=nil) { NSString *prefix = [self resolvePrefixForNamespaceURI:URI]; if (prefix!=nil) name = [NSString stringWithFormat:@"%@:%@", prefix, name]; } NSString *localName = [[self class] localNameForName:name]; BOOL hasPrefix = ([[self class] prefixForName:localName]!=nil); xmlNodePtr child = MGMXMLNodePtr->children; while (child!=NULL) { if (child->type==MGMXMLElementKind) { BOOL shouldAddElement = NO; if (URI==nil) { shouldAddElement = xmlStrEqual(child->name, [name xmlString]); } else { if (hasPrefix && xmlStrEqual(child->name, [name xmlString])) shouldAddElement = YES; else if (child->ns!=NULL) shouldAddElement = xmlStrEqual(child->name, [(hasPrefix ? localName : name) xmlString]) && xmlStrEqual(child->ns->href, [URI xmlString]); } if (shouldAddElement) [elements addObject:[MGMXMLElement nodeWithTypeXMLPtr:(xmlTypPtr)child]]; } child = child->next; } return elements; } - (NSArray *)elementsForName:(NSString *)name { NSString *localName = [[self class] localNameForName:name]; NSString *prefix = [[self class] prefixForName:name]; NSString *uri = nil; if (prefix!=nil) { if (MGMXMLNodePtr->doc==NULL) { NSLog(@"You may not search for elements with a namespace if there is no document."); return nil; } xmlNsPtr namespace = xmlSearchNs(MGMXMLNodePtr->doc, MGMXMLNodePtr, [prefix xmlString]); if (namespace!=NULL) uri = [NSString stringWithXMLString:namespace->href]; } return [self elementsForName:localName URI:uri resolvingNamespacePrefix:NO]; } - (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI { return [self elementsForName:localName URI:URI resolvingNamespacePrefix:YES]; } - (void)addAttribute:(MGMXMLNode *)attribute { if ([attribute kind]==MGMXMLAttributeKind && [attribute commonXML]->parent!=NULL) { [self removeAttributeForName:[attribute name]]; xmlAddChild(MGMXMLNodePtr, (xmlNodePtr)[attribute commonXML]); } } - (void)removeAttributeForName:(NSString *)name { xmlAttrPtr attribute = MGMXMLNodePtr->properties; while (attribute!=NULL) { if (xmlStrEqual(attribute->name, [name xmlString])) { [[self class] detatchAttribute:attribute fromNode:MGMXMLNodePtr]; if(attribute->_private == NULL) xmlFreeProp(attribute); break; } attribute = attribute->next; } } - (NSArray *)attributes { NSMutableArray *attributes = [NSMutableArray array]; xmlAttrPtr attribute = MGMXMLNodePtr->properties; while (attribute!=NULL) { [attributes addObject:[MGMXMLNode nodeWithTypeXMLPtr:(xmlTypPtr)attribute]]; attribute = attribute->next; } return attributes; } - (MGMXMLNode *)attributeForName:(NSString *)name { xmlAttrPtr attribute = MGMXMLNodePtr->properties; while (attribute!=NULL) { if (xmlStrEqual(attribute->name, [name xmlString])) return [MGMXMLNode nodeWithTypeXMLPtr:(xmlTypPtr)attribute]; attribute = attribute->next; } return nil; } - (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI { xmlNodePtr child = MGMXMLNodePtr; while (child!=NULL) { xmlNsPtr namespace = child->nsDef; while (namespace!=NULL) { if (xmlStrEqual(namespace->href, [namespaceURI xmlString])) { if (namespace->prefix!=NULL) return [NSString stringWithXMLString:namespace->prefix]; } namespace = namespace->next; } } return nil; } @end