1

我在要阅读的 xml 中有以下操作。但我只想阅读<goodactions><niceactions>。我需要在didStartElement委托函数中放置标志吗?

<goodactions>
  <action name=\"play\" id=\"0\"/>
  <action name=\"eat\" id=\"1\" />
  <action name=\"sleep\" id=\"2\" />
  <action name=\"study\" id=\"3\"/>
</goodactions>
<badactions>
  <action name=\"smoke\" id=\"0\"/>
  <action name=\"watch_tv\" id=\"1\"/>
</badactions>
<niceactions>
  <action name=\"cycling\" id=\"0\"/>
  <action name=\"swimming\" id=\"1\"/>
</niceactions>
4

3 回答 3

3

也许你在问别的问题,但一个简单的布尔值可能就足够了。

BOOL ignoreElement; 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {

    if ([elementName isEqualToString:@"badactions"]) {

        self.ignoreElement = YES; 

    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {

    if (!self.ignoreElement) {
        // data from other elements
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {

    if ([elementName isEqualToString:@"badactions"]) {

        self.ignoreElement = NO; 

    }

}
于 2012-04-26T19:49:27.607 回答
1

是的,我就是这样做的。当您的委托-parser:didStartElement::::方法被调用时,如果元素名称为“badactions”,请设置一个标志以忽略所有内容。-parser:didEndElement:如果元素名称为“badactions”,则重置标志。像这样的东西:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if ([elementName isEqualToString:@"badactions"])
    {
        _ignoreElement = YES;
        return;
    }
    if (!_ignoreElement)
    {
         // handle other elements here
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    // Reset if we were ignoring a badactions element
    if (([elementName isEqualToString:@"badactions"]) && (_ignoreElement))
    {
         _ignoreElement = NO;
    }
}
于 2012-04-26T19:47:09.607 回答
0

忽略特定节点或分支的最简单解决方案是创建自己的 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
于 2014-12-28T14:32:09.433 回答