This repository has been archived on 2018-06-04. You can view files and clone it, but cannot push or open issues/pull-requests.
iMoodUpdater/OSX/XMLTree.m

384 lines
8.0 KiB
Objective-C

#import "XMLTree.h"
@interface XMLTree (PrivateAPI)
@end // End Private API
@implementation XMLTree
-(void)dealloc
{
//NSLog( @"dealloc %@", self );
if( _tree != NULL )
CFRelease( _tree );
if( _node != NULL )
CFRelease( _node );
_tree = NULL;
_node = NULL;
} // end dealloc
+(XMLTree *)treeWithURL:(NSURL *)url
{
return [[[XMLTree alloc] initWithURL:url] autorelease];
} // end treeWithURL
-(XMLTree *)init
{
if( [super init] == nil )
return nil;
_tree = NULL;
_node = NULL;
return self;
} // end init
-(XMLTree *)initWithCFXMLTreeRef:(CFXMLTreeRef)ref
{
if( [self init] == nil )
return nil;
// Clean up?
if( _tree != NULL )
CFRelease( _tree );
if( _node != NULL )
CFRelease( _node );
_tree = ref;
_node = CFXMLTreeGetNode( _tree );
CFRetain( _tree );
CFRetain( _node );
return self;
} // end initWithCFXMLTreeRef:
-(XMLTree *)initWithURL:(NSURL *)url
{
CFDataRef xmlData;
if( (xmlData = (CFDataRef)malloc( sizeof( CFDataRef ) ) ) == NULL){
NSLog(@"Couldn't allocate any memory.");
return nil;
} // end if: malloc fail
_tree = CFXMLTreeCreateWithDataFromURL(
kCFAllocatorDefault,
(CFURLRef)url,
kCFXMLParserSkipWhitespace,
NULL ); //CFIndex
_node = CFXMLTreeGetNode( _tree );
// _tree is implicitly retained
CFRetain( _node );
return self;
} // end initWithURL
/* ******** A B O U T C H I L D R E N ******** */
-(int)count
{
if( _tree == NULL )
return -1;
return CFTreeGetChildCount( _tree );
} // end count
-(XMLTree *)childAtIndex:(int)index
{
CFXMLTreeRef child;
if( _tree == NULL )
return nil;
if( index >= CFTreeGetChildCount( _tree ) )
return nil;
child = CFTreeGetChildAtIndex(_tree, index);
return [[XMLTree alloc] initWithCFXMLTreeRef:child];
} // end childAtIndex:
-(XMLTree *)childNamed:(NSString *)name
{
CFXMLTreeRef childTree;
CFXMLNodeRef childNode;
CFStringRef childName;
int childCount;
int i;
if( _tree == NULL )
return nil;
childCount = CFTreeGetChildCount( _tree );
for( i = 0; i < childCount; i++ ){
childTree = CFTreeGetChildAtIndex(_tree, i );
childNode = CFXMLTreeGetNode( childTree );
childName = CFXMLNodeGetString( childNode );
if( CFStringCompare( (CFStringRef)name, childName, NULL ) == kCFCompareEqualTo )
return [[XMLTree alloc] initWithCFXMLTreeRef:childTree];
} // end for: each child
return nil;
} // end childNamed:
-(XMLTree *)descendentNamed:(NSString *)name
{
CFXMLTreeRef descTree;
if( _tree == NULL )
return nil;
descTree = XMLTreeDescendentNamed( (CFStringRef)name, _tree );
if( descTree == NULL )
return nil;
return [[XMLTree alloc] initWithCFXMLTreeRef:descTree];
} // end descendentNamed:
/* ******** A B O U T S E L F ******** */
-(NSString *)name
{
NSString *name;
if( _node == NULL )
return nil;
name = [[NSString alloc] initWithString:(NSString *)CFXMLNodeGetString(_node)];
return name;
} // end name
/*!
@discussion
Returns the node type, as defined by Apple's XML parser.
The values will be one of the following constants:
<pre>
enum CFXMLNodeTypeCode {
kCFXMLNodeTypeDocument = 1,
kCFXMLNodeTypeElement = 2,
kCFXMLNodeTypeAttribute = 3,
kCFXMLNodeTypeProcessingInstruction = 4,
kCFXMLNodeTypeComment = 5,
kCFXMLNodeTypeText = 6,
kCFXMLNodeTypeCDATASection = 7,
kCFXMLNodeTypeDocumentFragment = 8,
kCFXMLNodeTypeEntity = 9,
kCFXMLNodeTypeEntityReference = 10,
kCFXMLNodeTypeDocumentType = 11,
kCFXMLNodeTypeWhitespace = 12,
kCFXMLNodeTypeNotation = 13,
kCFXMLNodeTypeElementTypeDeclaration = 14,
kCFXMLNodeTypeAttributeListDeclaration = 15
};
</pre>
*/
-(CFXMLNodeTypeCode)type
{
return CFXMLNodeGetTypeCode(_node);
} // end type
-(NSDictionary *)attributes
{
CFXMLElementInfo eInfo;
if( CFXMLNodeGetTypeCode( _node ) != kCFXMLNodeTypeElement )
return nil;
eInfo = *(CFXMLElementInfo *)CFXMLNodeGetInfoPtr(_node);
return (NSDictionary *)eInfo.attributes;
} // end attributes
-(NSString *)attributeNamed:(NSString *)name
{
if( _tree == NULL )
return nil;
return [[[self attributes] objectForKey:name] description];
} // end attributeNamed:
-(NSString *)description
{
NSMutableString *descr;
descr = [[NSMutableString alloc] init];
//NSLog( @"Description for type %d", CFXMLNodeGetTypeCode(_node) );
switch( CFXMLNodeGetTypeCode(_node) ){
case kCFXMLNodeTypeDocument:
case kCFXMLNodeTypeElement:
XMLTreeDescription( (CFMutableStringRef)descr, _tree );
break;
case kCFXMLNodeTypeProcessingInstruction:
case kCFXMLNodeTypeAttribute:
case kCFXMLNodeTypeComment:
case kCFXMLNodeTypeText:
case kCFXMLNodeTypeCDATASection:
case kCFXMLNodeTypeDocumentFragment:
case kCFXMLNodeTypeEntity:
case kCFXMLNodeTypeEntityReference:
case kCFXMLNodeTypeDocumentType:
case kCFXMLNodeTypeWhitespace:
case kCFXMLNodeTypeNotation:
case kCFXMLNodeTypeElementTypeDeclaration:
case kCFXMLNodeTypeAttributeListDeclaration:
default:
[descr appendString:(NSString *)CFXMLNodeGetString(_node)];
} // end switch
return descr;
} // end description
-(NSString *)xml
{
CFDataRef xmlData;
if( _tree == NULL )
return nil;
xmlData = CFXMLTreeCreateXMLData(
kCFAllocatorDefault,
_tree );
if( xmlData == NULL )
return nil;
return [[NSString alloc] initWithData:(NSData *)xmlData encoding:NSASCIIStringEncoding];
} // end xml
@end // End implementation
CFStringRef XMLTreeDescription( CFMutableStringRef descr, CFXMLTreeRef tree )
{
CFXMLTreeRef childTree;
CFXMLNodeRef childNode;
int childCount;
int i;
childCount = CFTreeGetChildCount( tree );
for( i = 0; i < childCount; i++ ){
childTree = CFTreeGetChildAtIndex( tree, i );
childNode = CFXMLTreeGetNode( childTree );
switch( CFXMLNodeGetTypeCode( childNode ) ){
case kCFXMLNodeTypeText:
CFStringAppend( descr, CFXMLNodeGetString( childNode ) );
break;
case kCFXMLNodeTypeElement:
XMLTreeDescription( descr, childTree );
break;
default:
break;
} // end switch: node type
} // end for
return descr;
} // end XMLTreeDescription
CFXMLTreeRef XMLTreeDescendentNamed( CFStringRef name, CFXMLTreeRef tree )
{
CFXMLTreeRef childTree;
CFXMLTreeRef descTree;
CFXMLNodeRef childNode;
CFStringRef childName;
int childCount;
int i;
childCount = CFTreeGetChildCount( tree );
for( i = 0; i < childCount; i++ ){
childTree = CFTreeGetChildAtIndex( tree, i );
childNode = CFXMLTreeGetNode( childTree );
childName = CFXMLNodeGetString( childNode );
// Is this it?
if( CFStringCompare( name, childName, NULL ) == kCFCompareEqualTo )
return childTree;
// If child is an element, search recursively
if( CFXMLNodeGetTypeCode( childNode ) == kCFXMLNodeTypeElement ){
descTree = XMLTreeDescendentNamed( name, childTree );
// Got a match?
if( descTree != NULL )
return descTree;
} // end if: element node type
} // end for
return NULL;
} // end XMLTreeDescendentNamed: