123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 |
- #import "NSXMLElement+XMPP.h"
- #import "NSNumber+XMPP.h"
- #if ! __has_feature(objc_arc)
- #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
- #endif
- @implementation NSXMLElement (XMPP)
- /**
- * Convenience methods for Creating elements.
- **/
- + (NSXMLElement *)elementWithName:(NSString *)name numberValue:(NSNumber *)number
- {
- return [self elementWithName:name stringValue:[number stringValue]];
- }
- - (id)initWithName:(NSString *)name numberValue:(NSNumber *)number
- {
- return [self initWithName:name stringValue:[number stringValue]];
- }
- + (NSXMLElement *)elementWithName:(NSString *)name objectValue:(id)objectValue
- {
- if([objectValue isKindOfClass:[NSString class]])
- {
- return [self elementWithName:name stringValue:objectValue];
- }
- else if([objectValue isKindOfClass:[NSNumber class]])
- {
- return [self elementWithName:name numberValue:objectValue];
- }
- else if([objectValue respondsToSelector:@selector(stringValue)])
- {
- return [self elementWithName:name stringValue:[objectValue stringValue]];
- }
- else
- {
- return [self elementWithName:name];
- }
- }
- - (id)initWithName:(NSString *)name objectValue:(id)objectValue
- {
- if([objectValue isKindOfClass:[NSString class]])
- {
- return [self initWithName:name stringValue:objectValue];
- }
- else if([objectValue isKindOfClass:[NSNumber class]])
- {
- return [self initWithName:name numberValue:objectValue];
- }
- else if([objectValue respondsToSelector:@selector(stringValue)])
- {
- return [self initWithName:name stringValue:[objectValue stringValue]];
- }
- else
- {
- return [self initWithName:name];
- }
- }
- /**
- * Quick method to create an element
- **/
- + (NSXMLElement *)elementWithName:(NSString *)name xmlns:(NSString *)ns
- {
- NSXMLElement *element = [NSXMLElement elementWithName:name];
- [element setXmlns:ns];
- return element;
- }
- - (id)initWithName:(NSString *)name xmlns:(NSString *)ns
- {
- if ((self = [self initWithName:name]))
- {
- [self setXmlns:ns];
- }
- return self;
- }
- - (NSArray *)elementsForXmlns:(NSString *)ns
- {
- NSMutableArray *elements = [NSMutableArray array];
-
- for (NSXMLNode *node in [self children])
- {
- if ([node isKindOfClass:[NSXMLElement class]])
- {
- NSXMLElement *element = (NSXMLElement *)node;
-
- if ([[element xmlns] isEqual:ns])
- {
- [elements addObject:element];
- }
- }
- }
-
- return elements;
- }
- - (NSArray *)elementsForXmlnsPrefix:(NSString *)nsPrefix
- {
- NSMutableArray *elements = [NSMutableArray array];
-
- for (NSXMLNode *node in [self children])
- {
- if ([node isKindOfClass:[NSXMLElement class]])
- {
- NSXMLElement *element = (NSXMLElement *)node;
-
- if ([[element xmlns] hasPrefix:nsPrefix])
- {
- [elements addObject:element];
- }
- }
- }
-
- return elements;
- }
- /**
- * This method returns the first child element for the given name (as an NSXMLElement).
- * If no child elements exist for the given name, nil is returned.
- **/
- - (NSXMLElement *)elementForName:(NSString *)name
- {
- NSArray *elements = [self elementsForName:name];
- if ([elements count] > 0)
- {
- return elements[0];
- }
- else
- {
- // There is a bug in the NSXMLElement elementsForName: method.
- // Consider the following XML fragment:
- //
- // <query xmlns="jabber:iq:private">
- // <x xmlns="some:other:namespace"></x>
- // </query>
- //
- // Calling [query elementsForName:@"x"] results in an empty array!
- //
- // However, it will work properly if you use the following:
- // [query elementsForLocalName:@"x" URI:@"some:other:namespace"]
- //
- // The trouble with this is that we may not always know the xmlns in advance,
- // so in this particular case there is no way to access the element without looping through the children.
- //
- // This bug was submitted to apple on June 1st, 2007 and was classified as "serious".
- //
- // --!!-- This bug does NOT exist in DDXML --!!--
-
- return nil;
- }
- }
- /**
- * This method returns the first child element for the given name and given xmlns (as an NSXMLElement).
- * If no child elements exist for the given name and given xmlns, nil is returned.
- **/
- - (NSXMLElement *)elementForName:(NSString *)name xmlns:(NSString *)xmlns
- {
- NSArray *elements = [self elementsForLocalName:name URI:xmlns];
- if ([elements count] > 0)
- {
- return elements[0];
- }
- else
- {
- return nil;
- }
- }
- - (NSXMLElement *)elementForName:(NSString *)name xmlnsPrefix:(NSString *)xmlnsPrefix{
-
- NSXMLElement *result = nil;
-
- for (NSXMLNode *node in [self children])
- {
- if ([node isKindOfClass:[NSXMLElement class]])
- {
- NSXMLElement *element = (NSXMLElement *)node;
-
- if ([[element name] isEqualToString:name] && [[element xmlns] hasPrefix:xmlnsPrefix])
- {
- result = element;
- break;
- }
- }
- }
-
- return result;
- }
- /**
- * This method removes the first child element for the given name.
- * If no child elements exist for the given name, this method does nothing.
- **/
- - (void)removeElementForName:(NSString *)name
- {
- NSXMLElement *element = [self elementForName:name];
- if(element)
- {
- [self removeChildAtIndex:[[self children] indexOfObject:element]];
- }
- }
- /**
- * This method removes the all child elements for the given name.
- * If no child elements exist for the given name, this method does nothing.
- **/
- - (void)removeElementsForName:(NSString *)name
- {
- NSArray *elements = [self elementsForName:name];
-
- for(NSXMLElement *element in elements)
- {
- [self removeChildAtIndex:[[self children] indexOfObject:element]];
- }
- }
- /**
- * This method removes the first child element for the given name and given xmlns.
- * If no child elements exist for the given name and given xmlns, this method does nothing.
- **/
- - (void)removeElementForName:(NSString *)name xmlns:(NSString *)xmlns
- {
- NSXMLElement *element = [self elementForName:name xmlns:xmlns];
-
- if(element)
- {
- [self removeChildAtIndex:[[self children] indexOfObject:element]];
- }
- }
- /**
- * This method removes the first child element for the given name and given xmlns prefix.
- * If no child elements exist for the given name and given xmlns prefix, this method does nothing.
- **/
- - (void)removeElementForName:(NSString *)name xmlnsPrefix:(NSString *)xmlnsPrefix
- {
- NSXMLElement *element = [self elementForName:name xmlnsPrefix:xmlnsPrefix];
-
- if(element)
- {
- [self removeChildAtIndex:[[self children] indexOfObject:element]];
- }
- }
- /**
- * Returns the common xmlns "attribute", which is only accessible via the namespace methods.
- * The xmlns value is often used in jabber elements.
- **/
- - (NSString *)xmlns
- {
- return [[self namespaceForPrefix:@""] stringValue];
- }
- - (void)setXmlns:(NSString *)ns
- {
- // If we use setURI: then the xmlns won't be displayed in the XMLString.
- // Adding the namespace this way works properly.
-
- [self addNamespace:[NSXMLNode namespaceWithName:@"" stringValue:ns]];
- }
- /**
- * Shortcut to get a pretty (formatted) string representation of the element.
- **/
- - (NSString *)prettyXMLString
- {
- return [self XMLStringWithOptions:(NSXMLNodePrettyPrint | NSXMLNodeCompactEmptyElement)];
- }
- /**
- * Shortcut to get a compact string representation of the element.
- **/
- - (NSString *)compactXMLString
- {
- return [self XMLStringWithOptions:NSXMLNodeCompactEmptyElement];
- }
- /**
- * Shortcut to avoid having to use NSXMLNode everytime
- **/
- - (void)addAttributeWithName:(NSString *)name intValue:(int)intValue
- {
- [self addAttributeWithName:name numberValue:@(intValue)];
- }
- - (void)addAttributeWithName:(NSString *)name boolValue:(BOOL)boolValue
- {
- [self addAttributeWithName:name numberValue:@(boolValue)];
- }
- - (void)addAttributeWithName:(NSString *)name floatValue:(float)floatValue
- {
- [self addAttributeWithName:name numberValue:@(floatValue)];
- }
- - (void)addAttributeWithName:(NSString *)name doubleValue:(double)doubleValue
- {
- [self addAttributeWithName:name numberValue:@(doubleValue)];
- }
- - (void)addAttributeWithName:(NSString *)name integerValue:(NSInteger)integerValue
- {
- [self addAttributeWithName:name numberValue:@(integerValue)];
- }
- - (void)addAttributeWithName:(NSString *)name unsignedIntegerValue:(NSUInteger)unsignedIntegerValue
- {
- [self addAttributeWithName:name numberValue:@(unsignedIntegerValue)];
- }
- - (void)addAttributeWithName:(NSString *)name stringValue:(NSString *)string
- {
- [self addAttribute:[NSXMLNode attributeWithName:name stringValue:string]];
- }
- - (void)addAttributeWithName:(NSString *)name numberValue:(NSNumber *)number
- {
- [self addAttributeWithName:name stringValue:[number stringValue]];
- }
- - (void)addAttributeWithName:(NSString *)name objectValue:(id)objectValue
- {
- if([objectValue isKindOfClass:[NSString class]])
- {
- [self addAttributeWithName:name stringValue:objectValue];
- }
- else if([objectValue isKindOfClass:[NSNumber class]])
- {
- [self addAttributeWithName:name numberValue:objectValue];
- }
- else if([objectValue respondsToSelector:@selector(stringValue)])
- {
- [self addAttributeWithName:name stringValue:[objectValue stringValue]];
- }
- }
- /**
- * The following methods return the corresponding value of the attribute with the given name.
- **/
- - (int)attributeIntValueForName:(NSString *)name
- {
- return [[self attributeStringValueForName:name] intValue];
- }
- - (BOOL)attributeBoolValueForName:(NSString *)name
- {
- NSString *attributeStringValueForName = [self attributeStringValueForName:name];
-
- BOOL result = NO;
-
- // An XML boolean datatype can have the following legal literals: true, false, 1, 0
-
- if ([attributeStringValueForName isEqualToString:@"true"] || [attributeStringValueForName isEqualToString:@"1"])
- {
- result = YES;
- }
- else if([attributeStringValueForName isEqualToString:@"false"] || [attributeStringValueForName isEqualToString:@"0"])
- {
- result = NO;
- }
- else
- {
- result = [attributeStringValueForName boolValue];
- }
-
- return result;
- }
- - (float)attributeFloatValueForName:(NSString *)name
- {
- return [[self attributeStringValueForName:name] floatValue];
- }
- - (double)attributeDoubleValueForName:(NSString *)name
- {
- return [[self attributeStringValueForName:name] doubleValue];
- }
- - (int32_t)attributeInt32ValueForName:(NSString *)name
- {
- int32_t result = 0;
- [NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoInt32:&result];
- return result;
- }
- - (uint32_t)attributeUInt32ValueForName:(NSString *)name
- {
- uint32_t result = 0;
- [NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoUInt32:&result];
- return result;
- }
- - (int64_t)attributeInt64ValueForName:(NSString *)name
- {
- int64_t result;
- [NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoInt64:&result];
- return result;
- }
- - (uint64_t)attributeUInt64ValueForName:(NSString *)name
- {
- uint64_t result;
- [NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoUInt64:&result];
- return result;
- }
- - (NSInteger)attributeIntegerValueForName:(NSString *)name
- {
- NSInteger result;
- [NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoNSInteger:&result];
- return result;
- }
- - (NSUInteger)attributeUnsignedIntegerValueForName:(NSString *)name
- {
- NSUInteger result = 0;
- [NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoNSUInteger:&result];
- return result;
- }
- - (NSString *)attributeStringValueForName:(NSString *)name
- {
- return [[self attributeForName:name] stringValue];
- }
- - (NSNumber *)attributeNumberIntValueForName:(NSString *)name
- {
- return @([self attributeIntValueForName:name]);
- }
- - (NSNumber *)attributeNumberBoolValueForName:(NSString *)name
- {
- return @([self attributeBoolValueForName:name]);
- }
- - (NSNumber *)attributeNumberFloatValueForName:(NSString *)name
- {
- return @([self attributeFloatValueForName:name]);
- }
- - (NSNumber *)attributeNumberDoubleValueForName:(NSString *)name
- {
- return @([self attributeDoubleValueForName:name]);
- }
- - (NSNumber *)attributeNumberInt32ValueForName:(NSString *)name
- {
- return @([self attributeInt32ValueForName:name]);
- }
- - (NSNumber *)attributeNumberUInt32ValueForName:(NSString *)name
- {
- return @([self attributeUInt32ValueForName:name]);
- }
- - (NSNumber *)attributeNumberInt64ValueForName:(NSString *)name
- {
- return @([self attributeInt64ValueForName:name]);
- }
- - (NSNumber *)attributeNumberUInt64ValueForName:(NSString *)name
- {
- return @([self attributeUInt64ValueForName:name]);
- }
- - (NSNumber *)attributeNumberIntegerValueForName:(NSString *)name
- {
- return @([self attributeIntegerValueForName:name]);
- }
- - (NSNumber *)attributeNumberUnsignedIntegerValueForName:(NSString *)name
- {
- return @([self attributeUnsignedIntegerValueForName:name]);
- }
- /**
- * The following methods return the corresponding value of the attribute with the given name.
- * If the attribute does not exist, the given defaultValue is returned.
- **/
- - (int)attributeIntValueForName:(NSString *)name withDefaultValue:(int)defaultValue
- {
- NSXMLNode *attr = [self attributeForName:name];
- return (attr) ? [[attr stringValue] intValue] : defaultValue;
- }
- - (BOOL)attributeBoolValueForName:(NSString *)name withDefaultValue:(BOOL)defaultValue
- {
- NSXMLNode *attr = [self attributeForName:name];
- return (attr) ? [[attr stringValue] boolValue] : defaultValue;
- }
- - (float)attributeFloatValueForName:(NSString *)name withDefaultValue:(float)defaultValue
- {
- NSXMLNode *attr = [self attributeForName:name];
- return (attr) ? [[attr stringValue] floatValue] : defaultValue;
- }
- - (double)attributeDoubleValueForName:(NSString *)name withDefaultValue:(double)defaultValue
- {
- NSXMLNode *attr = [self attributeForName:name];
- return (attr) ? [[attr stringValue] doubleValue] : defaultValue;
- }
- - (int32_t)attributeInt32ValueForName:(NSString *)name withDefaultValue:(int32_t)defaultValue
- {
- int32_t result = 0;
- if ([NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoInt32:&result])
- return result;
- else
- return defaultValue;
- }
- - (uint32_t)attributeUInt32ValueForName:(NSString *)name withDefaultValue:(uint32_t)defaultValue
- {
- uint32_t result = 0;
- if ([NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoUInt32:&result])
- return result;
- else
- return defaultValue;
- }
- - (int64_t)attributeInt64ValueForName:(NSString *)name withDefaultValue:(int64_t)defaultValue
- {
- int64_t result = 0;
- if ([NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoInt64:&result])
- return result;
- else
- return defaultValue;
- }
- - (uint64_t)attributeUInt64ValueForName:(NSString *)name withDefaultValue:(uint64_t)defaultValue
- {
- uint64_t result = 0;
- if ([NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoUInt64:&result])
- return result;
- else
- return defaultValue;
- }
- - (NSInteger)attributeIntegerValueForName:(NSString *)name withDefaultValue:(NSInteger)defaultValue
- {
- NSInteger result = 0;
- if ([NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoNSInteger:&result])
- return result;
- else
- return defaultValue;
- }
- - (NSUInteger)attributeUnsignedIntegerValueForName:(NSString *)name withDefaultValue:(NSUInteger)defaultValue
- {
- NSUInteger result = 0;
- if ([NSNumber xmpp_parseString:[self attributeStringValueForName:name] intoNSUInteger:&result])
- return result;
- else
- return defaultValue;
- }
- - (NSString *)attributeStringValueForName:(NSString *)name withDefaultValue:(NSString *)defaultValue
- {
- NSXMLNode *attr = [self attributeForName:name];
- return (attr) ? [attr stringValue] : defaultValue;
- }
- - (NSNumber *)attributeNumberIntValueForName:(NSString *)name withDefaultValue:(int)defaultValue
- {
- return @([self attributeIntValueForName:name withDefaultValue:defaultValue]);
- }
- - (NSNumber *)attributeNumberBoolValueForName:(NSString *)name withDefaultValue:(BOOL)defaultValue
- {
- return @([self attributeBoolValueForName:name withDefaultValue:defaultValue]);
- }
- /**
- * Returns all the attributes in a dictionary.
- **/
- - (NSMutableDictionary *)attributesAsDictionary
- {
- NSArray *attributes = [self attributes];
- NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:[attributes count]];
-
- NSUInteger i;
- for(i = 0; i < [attributes count]; i++)
- {
- NSXMLNode *node = attributes[i];
-
- result[[node name]] = [node stringValue];
- }
- return result;
- }
- /**
- * The following methods return the corresponding value of the node.
- **/
- - (int)stringValueAsInt
- {
- return [[self stringValue] intValue];
- }
- - (BOOL)stringValueAsBool
- {
- return [[self stringValue] boolValue];
- }
- - (float)stringValueAsFloat
- {
- return [[self stringValue] floatValue];
- }
- - (double)stringValueAsDouble
- {
- return [[self stringValue] doubleValue];
- }
- - (int32_t)stringValueAsInt32
- {
- int32_t result;
- if ([NSNumber xmpp_parseString:[self stringValue] intoInt32:&result])
- return result;
- else
- return 0;
- }
- - (uint32_t)stringValueAsUInt32
- {
- uint32_t result;
- if ([NSNumber xmpp_parseString:[self stringValue] intoUInt32:&result])
- return result;
- else
- return 0;
- }
- - (int64_t)stringValueAsInt64
- {
- int64_t result = 0;
- if ([NSNumber xmpp_parseString:[self stringValue] intoInt64:&result])
- return result;
- else
- return 0;
- }
- - (uint64_t)stringValueAsUInt64
- {
- uint64_t result = 0;
- if ([NSNumber xmpp_parseString:[self stringValue] intoUInt64:&result])
- return result;
- else
- return 0;
- }
- - (NSInteger)stringValueAsNSInteger
- {
- NSInteger result = 0;
- if ([NSNumber xmpp_parseString:[self stringValue] intoNSInteger:&result])
- return result;
- else
- return 0;
- }
- - (NSUInteger)stringValueAsNSUInteger
- {
- NSUInteger result = 0;
- if ([NSNumber xmpp_parseString:[self stringValue] intoNSUInteger:&result])
- return result;
- else
- return 0;
- }
- /**
- * Shortcut to avoid having to use NSXMLNode everytime
- **/
- - (void)addNamespaceWithPrefix:(NSString *)prefix stringValue:(NSString *)string
- {
- [self addNamespace:[NSXMLNode namespaceWithName:prefix stringValue:string]];
- }
- /**
- * Just to make your code look a little bit cleaner.
- **/
- - (NSString *)namespaceStringValueForPrefix:(NSString *)prefix
- {
- return [[self namespaceForPrefix:prefix] stringValue];
- }
- - (NSString *)namespaceStringValueForPrefix:(NSString *)prefix withDefaultValue:(NSString *)defaultValue
- {
- NSXMLNode *namespace = [self namespaceForPrefix:prefix];
- return (namespace) ? [namespace stringValue] : defaultValue;
- }
- @end
|