忽略特定节点或分支的最简单解决方案是创建自己的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