试图剥离空格在NSXMLparser foundCharacters方法中不起作用

时间:2009-09-14 15:43:12

标签: iphone objective-c

我正在解析一个xml文件,我一直试图去除currentElementValue中的空白字符,因为它搞乱了一些事情。

我可以在输出窗口中看到有几个回车和标签存在

(gdb) po string
Keep the arms on the side, and lift your leg.
(gdb) po currentElementValue



        Keep the arms on the side, and lift your leg.
(gdb) 

这是我的foundCharacters函数,但我一直试图使用stringByTrimmingCharactersInSet但没有成功。

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 
    if(!currentElementValue) 
        currentElementValue = [[NSMutableString alloc] initWithString:string];
    else
    {       

        [currentElementValue appendString:string];

        currentElementValue = [currentElementValue stringByTrimmingCharactersInSet:
                               [NSCharacterSet newlineCharacterSet]];       
            NSString *instructions = @"instructions";   
        [directions setValue:string forKey:instructions];  //mm 
        [appDelegate.directions setValue:string forKey:instructions];
        //[appDelegate.directions setObject:string forKey:currentElementValue];
    //  [appDelegate
    }
}

我一直在收到这个错误 ***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'尝试使用appendString来改变不可变对象:' 这很奇怪,因为我的currentElementValue是一个NSMutableString .. 出了什么问题?有没有人有线索或想法?

4 个答案:

答案 0 :(得分:7)

让我们一步一步,找到你的错误,并解决内存泄漏问题:

首先,创建一个NSMutableString。大。 (+1保留计数)

然后将另一个字符串附加到NSMutableString上。没关系。 (仍然+1保留计数)。

然后你修剪newlineCharacterSet,它返回一个自动释放的NSString。由于此对象与原始对象不同,因此您泄漏了原始对象(因为它具有+1保留计数而您不再有指向它的指针),并且您现在有一个不可变的NSString可以引导。这意味着下次调用此方法时,您将尝试将一个字符串附加到NSString上,这将抛出“无法改变不可变对象”异常。

以下是解决此问题的快捷方法:

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 
    if(!currentElementValue) 
        currentElementValue = [[NSMutableString alloc] initWithString:string];
    else
    {           

        [currentElementValue appendString:string];

        NSString *trimmedString = [currentElementValue stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
        [currentElementValue setString:trimmedString];

        NSString *instructions = @"instructions";       
        [directions setValue:string forKey:instructions];  //mm 
        [appDelegate.directions setValue:string forKey:instructions];
        //[appDelegate.directions setObject:string forKey:currentElementValue];
    //  [appDelegate
    }
}

(将修剪过的字符串保存到另一个变量,然后使用NSMutableString的setString:方法传入内容,但不会丢失指向NSMutableString的指针)

答案 1 :(得分:0)

顺便说一句......我认为NSXMLParser应该提供处理空白的设置,即在XML / XSLT的W3.org规范中“保留空白” - 此外,我不想得到适合像修剪一样的字符集。基本上,我希望像在XML / XMSLT转换中那样访问“@text()”。所以,我做了一些挖掘并发现了这种方法。请注意,可以将空白字符串附加到累积的文本。在第一次尝试它不起作用,但我有更多的实验要做,并仔细检查我的语法(即,削减'n粘贴技能:))

- (void)parser:(NSXMLParser *)parser foundIgnorableWhitespace:(NSString *)whitespaceString

<强>参数: 解析器 解析器对象。

whitespaceString 一个字符串,表示当前元素的全部或部分可忽略的空白字符。

<强>讨论 可能无法通过单独调用此方法来提供元素的所有空白字符(包括回车符,制表符和换行符)。解析器可以向委托发送几个解析器:foundIgnorableWhitespace:消息来报告元素的空白字符。您应该将每次调用中的字符追加到当前的字符累积中。

答案 2 :(得分:0)

我找到了一种处理节点文本的简洁方法。它假定您拥有XML内容/格式的所有权。我现在正在做的是使用CDATA部分作为我的节点的“text()”属性。这不包括我用来制作我的xml文档的空格。

要阅读的代码如下:

- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock {
NSLog(@"%s", __FUNCTION__);
NSLog(@"[%@]", CDATABlock);

NSString *strData = [[NSString alloc] initWithData:CDATABlock encoding: NSUTF8StringEncoding ];

NSLog(@"convertToString=[%@]", strData);

}

并且XML片段是这样的(带有'着名引号'的教程):

<quote><![CDATA[And in the end...in your years.]]></quote>

并且跟踪输出如下:

2009-11-21 13:17:51.901 Fate[2241:4203] -[XMLReader parser:foundCDATA:]
2009-11-21 13:17:51.901 Fate[2241:4203] [<416e6420 696e2074 68652065 6e642c20 69742773 206e6f74 20746865 20796561 72732069 6e20796f 7572206c 69666520 74686174 20636f75 6e742e20 20497427 73207468 65206c69 66652069 6e20796f 75722079 65617273 2e>]
2009-11-21 13:17:55.774 Fate[2241:4203] convertToString=[And in the end, it's not the years in your life that count.  It's the life in your years.]]>

答案 3 :(得分:0)

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
  //  Removing whitspace and newline characters
  string   =   [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

  //  If no characters are left return
  if([string length] == 0) return;

  //Rest of the code for saving the string