忽略特定節點或分支的最簡單解決方案是創建自己的XPath類XML路徑並維護元素堆棧。
因此,無論何時您解析新元素,您都會將堆棧上的節點推入並更新當前的XML路徑。然後當你偶然發現標籤時,你只需從堆棧中彈出元素。
但是,您的堆棧可能不一致,因爲您可能想忽略一些分支,您可以隨時保留並比較堆棧上結束標記和最後一個節點的XMLPath。
在下面給出的示例中,我使用點分隔符存儲XML路徑。它很便宜且易於分析和比較。
由於這種方法的一個好處,你可以實現一些簡單的比較算法,而忽略或XML結構,但潛水的中間匹配特定的樹枝和解析出特定節點更深。
擁有堆棧元素是一項巨大的好處,因爲如果您需要填充位於層次結構內部的某些信息,則始終可以引用相關節點。
// Base node class
@interface MYNode : NSObject
@property NSString* XMLPath;
@end
// Some custom node subclass
@interface MYRootNode : MYNode @end
// Some other custom node subclass
@interface MYBlockNode : MYNode @end
// NSXMLParserDelegate interface
@interface MYXMLParserDelegate : NSObject<NSXMLParserDelegate>
@property NSMutableArray* elementStack;
@property NSString* XMLPath;
@property MYRootNode* rootNode;
@end
// NSXMLParserDelegate implementation
@implementation MYXMLParserDelegate
#pragma mark - Initializer
- (id)init {
if(self = [super init]) {
self.elementStack = [NSMutableArray new];
}
return self;
}
#pragma mark - XMLPath manipulation methods
- (void)addXMLPathComponent:(NSString*)component {
NSString* newXMLPath;
if(self.XMLPath.length) {
newXMLPath = [self.XMLPath stringByAppendingFormat:@".%@", component];
} else {
newXMLPath = component;
}
self.XMLPath = newXMLPath;
}
- (void)removeLastXMLPathComponent {
NSRange range = [self.XMLPath rangeOfString:@"." options:NSBackwardsSearch];
if(range.location != NSNotFound) {
self.XMLPath = [self.XMLPath substringToIndex:range.location];
}
}
#pragma mark - NSXMLParserDelegate
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
MYNode* node;
// Add XML path component
[self addXMLPathComponent:elementName];
// Process relevant nodes
if([self.XMLPath isEqualToString:@"document.page"])
{
node = [[MYRootNode alloc] initWithAttributes:attributeDict];
// Save root node
self.rootNode = node;
}
else if([self.XMLPath isEqualToString:@"document.page.block"])
{
node = [[MYBlockNode alloc] initWithAttributes:attributeDict];
}
// Push relevant node on stack
if(node) {
node.XMLPath = self.XMLPath;
[self.elementStack addObject:node];
NSLog(@"-> %@", self.XMLPath);
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
MYNode* node = [self.elementStack lastObject];
// Remove node from stack if XML path match found
if([node.XMLPath isEqualToString:self.XMLPath]) {
[self.elementStack removeLastObject];
NSLog(@"<- %@", self.XMLPath);
}
// Pop XML path component
[self removeLastXMLPathComponent];
}
@end
這會排除壞行爲嗎?或只是元素badactions? – 2012-04-26 20:27:24
是的,這會忽略下badactions的行動,因爲XML解析器是連續的,通常被稱爲「事件驅動」的解析器或「SAX」解析器。 http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/XMLParsing/Articles/ParserArchitecture.html,http://en.wikipedia.org/wiki/Simple_API_for_XML – 2012-04-26 20:43:10
感謝克里斯......但回答@ user1118321給了更優雅,但... – 2012-04-26 21:28:28