我有一个类似于这样的XML文件:
[...]
<parent>
<title>...</title>
[...]
<child>
<title>...</title>
我有一个本地核心数据库,我的父实体可以有很多孩子。父实体是XML中的父标记,child是我的子实体。
如何使用NSXMLParser
基于XML结构将我的两个实体分离并解析为单独的NSManagedObject?
我目前有以下方法:
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
我不确定我可以在何处以及如何获得我的父实体,建议?
答案 0 :(得分:2)
我使用NSMutableArray作为堆栈:
一旦找到parent tag
,我就创建一个parent
对象,并将其放在该堆栈上。
一旦找到child
标记,我就创建一个子对象并将其放在堆栈中。现在,当找到一个标签时,应该将其保存为对象的属性,我只需将其添加到最后一个对象。
如果我有一个孩子在堆栈顶部,我知道它的父母是它下面的对象。现在我可以建立任何形式的关系。
如果找到了child的父级的结束标记,我将从堆栈中删除最后一个对象。
一个最小的例子:
我们要解析
<root>
<parent>
<title>Parent1</title>
<child>
<title>Child 1</title>
</child>
<child>
<title>Child 2</title>
</child>
</parent>
<parent>
<title>Parent 2</title>
<child>
<title>Child 3</title>
</child>
<child>
<title>Child 3</title>
</child>
</parent>
</root>
我们的数据结构:
@interface TitledObject : NSObject
@property (nonatomic, copy) NSString *title;
@end
@implementation TitledObject
-(NSString *)description
{
return [NSString stringWithFormat:@"%@: %@", NSStringFromClass([self class]), _title];
}
@end
@interface Parent :TitledObject
@property (nonatomic, strong) NSMutableArray *children;
@end
@implementation Parent
@end
@interface Child : TitledObject
@property (nonatomic, weak) Parent *parent;
@end
@implementation Child;
-(NSString *)description
{
NSString *s = [super description];
s = [s stringByAppendingString:[NSString stringWithFormat:@" , child of %@", self.parent]];
return s;
}
@end
解析器:
@interface XMLReader : NSObject <NSXMLParserDelegate>
@property (nonatomic, strong) NSString *string;
@property (nonatomic, strong) NSMutableArray *stack;
@property (nonatomic, strong) NSMutableArray *results;
-(id) initWithString:(NSString *)string;
@end
@implementation XMLReader{
NSMutableString *title;
}
-(id)initWithString:(NSString *)string
{
if(self = [super init]){
_string = string;
_stack = [NSMutableArray array];
_results = [NSMutableArray array];
}
return self;
}
-(void)parse
{
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:[self.string dataUsingEncoding:NSUTF8StringEncoding]];
parser.delegate = self;
[parser parse];
}
-(void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"parent"]) {
[self.stack addObject:[[Parent alloc] init]];
} else if ([elementName isEqualToString:@"child"]) {
Child *child = [[Child alloc] init];
child.parent = [self.stack lastObject];
[child.parent.children addObject:child];
[self.stack addObject:child];
} else if ([elementName isEqualToString:@"title"]) {
title = [@"" mutableCopy];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"title"])
[(TitledObject *)[self.stack lastObject] setTitle:title];
else if (! [elementName isEqualToString:@"root"]){
[self.results addObject:[self.stack lastObject]];
[self.stack removeLastObject];
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[title appendString:string];
}
@end
我们使用它:
XMLReader *reader = [[XMLReader alloc] initWithString:xmlString];
[reader parse];
并访问结果:
NSLog(@"%@", reader.results);
输出:
(
"Child: Child 1 , child of Parent: Parent1",
"Child: Child 2 , child of Parent: Parent1",
"Parent: Parent1",
"Child: Child 3 , child of Parent: Parent 2",
"Child: Child 3 , child of Parent: Parent 2",
"Parent: Parent 2"
)
您可以使用托管对象代替我的简单数据结构。