Using the code
This is an XML parser for iPhone apps. You can use the code in your iPhone XCode project by creating the class files and just passing the XML file to the static method of the parser class, and you get a filled XMLNode class structure which is like the root node of the standard XMLDocument class in many languages. For those of you used to C#, the style of doing this would be very familiar.
The XMLNode class has in it the name of the node and the value of the node. So for the following XML node line, in a file:
<NodeName>Node Value</NodeName>
the variable NSString nodeName would be NodeName, and NSString nodeValue would be "Node Value".
The XMLNode class stores XMLNode objects which are its children in the NSMutableArray childNodes variable. So you would iterate over all the children, accessing their node name and value information.
#import <foundation>
@interface XMLNode : NSObject {
NSString *nodeName, *nodeValue;
NSMutableArray *childNodes;
}
@property (retain, nonatomic) NSString *nodeName, *nodeValue;
@property (retain, nonatomic) NSMutableArray *childNodes;
- (id) init;
- (void) dealloc;
- (void) MyRelease;
@end
#import "XMLNode.h"
@implementation XMLNode
@synthesize nodeName, nodeValue, childNodes;
- (id) init
{
if((self = [super init]))
{
self.childNodes = [NSMutableArray arrayWithCapacity: 1];
}
return self;
}
- (void) MyRelease
{
for(int i=0; i < self.childNodes.count; i++)
{
[[self.childNodes objectAtIndex: i] MyRelease];
}
[self release];
}
- (void) dealloc
{
if(self.nodeName != nil)
[self.nodeName release];
if(self.nodeValue != nil)
[self.nodeValue release];
[self.childNodes release];
[super dealloc];
}
@end
The XMLParser class has two static methods, one of which is ParseFile, which expects you to pass it an NSData structure with the contents of the XML file you want parsed. The other method is not to be called (ParseString). The return value of the ParseFile method is just the root XMLNode instance in which is contained all the child nodes with the name/value pairs. You just iterate through this tree to access the XML data.
#import <foundation>
#import "XMLNode.h"
@interface XMLParser : NSObject {
}
+ (XMLNode *) ParseFile: (NSData *) data;
+ (int) ParseString: (NSString *) strData: (XMLNode *) parentNode: (int) pos;
@end
#import "XMLParser.h"
@implementation XMLParser
NSString *strData, *strData2, *strData3;
+ (XMLNode *) ParseFile: (NSData *) data
{
strData = [[NSString alloc] initWithData: data
encoding:NSASCIIStringEncoding];
strData2 = [strData stringByReplacingOccurrencesOfString: @"\n" withString: @""];
strData3 = [strData2 stringByReplacingOccurrencesOfString: @"\t" withString: @""];
XMLNode *rootNode = [XMLNode new];
[self ParseString: strData3: rootNode: 0];
return rootNode;
}
+ (int) ParseString: (NSString *) strData: (XMLNode *) parentNode: (int) pos
{
int i=pos;
while (i < [strData length]) {
NSRange l1;
l1.location = i;
l1.length = [strData length] - i;
NSRange r1 = [strData rangeOfString: @"<" options: NSLiteralSearch range: l1];
if(r1.length > 0)
{
i = r1.location + 1;
l1.location = i;
l1.length = [strData length] - i;
NSRange r2 = [strData rangeOfString: @">" options: NSLiteralSearch range: l1];
XMLNode *node1 = [XMLNode new];
if(r2.length > 0)
{
i = r2.location + 1;
NSRange nodeNameRange;
nodeNameRange.location = r1.location + 1;
nodeNameRange.length = r2.location - r1.location - 1;
node1.nodeName = [[NSString alloc] initWithString: [strData
substringWithRange: nodeNameRange]];
parentNode.childNodes addObject: node1];
i = nodeNameRange.location + nodeNameRange.length + 1;
NSString *nextChar = [strData substringWithRange: NSMakeRange(i, 1)];
NSString *nextCharNot = [strData substringWithRange:
NSMakeRange(i, 2)];
int hasChildNodes = 0;
while([nextChar isEqualToString: @"<"] == YES
&& [nextCharNot isEqualToString: @"</"] != YES)
{
hasChildNodes = 1;
i = [self ParseString:strData :node1 :i];
if(i < [strData length])
{
nextChar = [strData substringWithRange: NSMakeRange(i, 1)];
nextCharNot = [strData substringWithRange:
NSMakeRange(i, 2)];
}
else
{
return [strData length];
}
NSString *endTag = [[NSString alloc] initWithFormat:
@"</%s>", [node1.nodeName UTF8String]];
NSRange rDataEnd = [strData rangeOfString: endTag
options: NSLiteralSearch range:
NSMakeRange(i, [strData length] - i)];
if(hasChildNodes == 0)
{
node1.nodeValue = [[NSString alloc] initWithString:
[strData substringWithRange:
NSMakeRange(i, rDataEnd.location - i)]];
}
return rDataEnd.location + rDataEnd.length;
}
}
return [strData length];
}
@end
I have been coding since 1984 in a variety of languages. I originally started as a game programmer and then switched to business programming from 1990. I still program games.