【问题标题】:Datatypes for use with NSXMLParser用于 NSXMLParser 的数据类型
【发布时间】:2010-10-19 08:00:35
【问题描述】:

我正在使用 NSXMLParser 解析来自远程服务器的 XML 数据。我按照教程启动并运行,对于我正在创建的对象中的任何 (NSString *) 成员来说一切正常。我还需要从 XML 数据中设置整数,例如:

<root>
    <child>
        <name> Hello </name>
        <number> 123 </number>
    </child>
    <child>
        <name> World</name>
        <number> 456 </number>
    </child>
</root>

在这种情况下,我将创建两个“子”对象。我正在使用:

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
      namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    ...
    [aChild setValue:currentElementValue forKey:elementName];
    ...
}

委托设置值。这就是我遇到问题的地方。 “NSString *name”成员每次都设置得很好,但是如果我使用 NSInteger,那么每当我尝试设置“number”时,我都会得到一个 EXC_BAD_ACCESS。所以我尝试使用“int”代替。但是现在不能使用key-value编程,需要手动寻找节点:

if([elementName isEqualToString:@"number"]) {
    aChild.number = [currentElementValue intValue]
}

这没关系,我可以处理它,因为我知道我将获得哪些节点,但情况会变得更糟。根据教程,当 currentElementValue 是“NSMutableString *”时,即使字符串正确,它也不会返回正确的整数。例如:

    NSLog(@"NSMutableString Value: %@, and intValue %d\n", currentElementValue, [currentElementValue intValue]); 
// Value will be 123 but intValue will be 0

所以我将 currentElementValue 设为 NSString 而不是 NSMutableString,这样我就可以获得正确的 intValue。但我在网上读到它是 NSMutableString 的原因是:

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

用于设置值的委托可以出现多次,但通常不会。所以我的问题是有人知道我做错了什么吗?这对于 NSXMLParser 来说似乎是一个非常微不足道的案例,所以我确定这是我误解的事情。

【问题讨论】:

    标签: iphone cocoa-touch nsxmlparser


    【解决方案1】:

    这里发生了一些事情。

    首先,您的 XML 字符数据中有明显的空白,例如

            <number> 456 </number>
    

    你真的应该去掉那个空格。这可能是导致[NSString intValue] 的返回值错误的原因。如果您可以从源头上删除它,那就太好了。如果没有,您可以通过以下方式在接收端将其剥离:

    currentElementValue = [currentElementValue stringByTrimmingCharactersInSet:
        [NSCharacterSet whitespaceAndNewlineCharacterSet]];
    

    您不能使用键/值的原因是您不能将 NSInteger 值存储在 NSMutableDictionary 中。字典中的键和值都必须从 NSObject 继承,而 NSInteger (我在这里猜测)只是一个平台安全的 int 类型定义。所以你应该改用 NSNumber:

    NSNumber *theInt = [NSNumber numberWithInt:[currentElementValue intValue]];
    [aChild setObject:theInt forKey:elementName];
    

    【讨论】:

    • 嗨,谢谢,我今晚下班后要试试这个。我发布的 XML 示例与我使用的有很大不同,“真正的”示例前后没有空格,并且我可以完全控制源。我让它与'int'一起工作,但如果使用 NSNumber 允许键/值将是
    • 太棒了。根据我链接的教程,我最初是在 foundCharacters 中分配 NSMutableString 并在 didEndElement 之后释放。我将每个 cmets 更改为这个问题,现在 [.. intValue] 确实返回一个整数,但我认为 NSNumber 会更好。再次感谢。
    【解决方案2】:
    1. intValue 应该与 NSStringNSMutableString 一样工作。你确定 Value 是 '123' 而不是 '\n123' (\n 表示换行符),如果字符串不是以十进制数字开头,那么intValue 将返回 0。

      李>
    2. 您是否正确清除了parser:didStartElement: 的可变字符串?如果您只在parser:didEndElement: 进行清理,那么parser:foundCharacters: 也会从父元素中收集字符。在这种情况下,它将在您的字符串前面加上换行符,intValue 将返回 0。

    3. 你是对的,parser:foundCharacters: 可以为单个元素多次调用。

    【讨论】:

    • 我实际上是在 parser:didEndElement 的末尾通过执行以下操作清除它: [currentElementValue release];当前元素值 = 无;。然后我在 parser:foundCharacters 中重新分配它,如果它还没有分配,如果它是我将字符附加到它。会像 Can Berk Guder 那样处理它
    • 关于 1:只有在存在非数字和非空白字符时才正确。 “123”的 intValue 仍返回 123。
    【解决方案3】:

    我不知道您的代码在哪里出错,但这是处理此问题的正确方法:

    NSMutableString *buffer = [[NSMutableString alloc] init];
    
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
        [buffer setString:@""];
    }
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
        if([elementName isEqualToString:@"number"]) {
            [aChild setNumber:[buffer intValue]];
            [buffer setString:@""];
        }
    }
    
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
        [buffer appendString:string];
    }
    

    【讨论】:

    • 您好,谢谢,您是在init方法中分配缓冲区,然后在dealloc中释放它吗?我在 parser:foundCharacters 中分配它并在 parser:didEndElement 完成时释放它。
    • 是的。如果你在 foundCharacters 中分配,你都会有内存泄漏,如果 foundCharacters 被多次调用,则会丢失数据。即使它不被多次调用(确实如此),为每个节点分配和释放一个字符串也是过大的。
    猜你喜欢
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 2023-02-23
    • 2014-07-29
    • 2016-10-27
    相关资源
    最近更新 更多