什么叫CFStringCreateFromExternalRepresentation?

时间:2012-05-19 23:01:38

标签: objective-c cocoa stack-trace core-foundation

我对此堆栈跟踪感到困惑(只显示了令人困惑的部分):

-[NSXMLDocument length]: unrecognized selector sent to instance 0x10187e010
An uncaught exception was raised
-[NSXMLDocument length]: unrecognized selector sent to instance 0x10187e010
(
   0   CoreFoundation                      0x00007fff8f5d6286 __exceptionPreprocess + 198
   1   libobjc.A.dylib                     0x00007fff9213bd5e objc_exception_throw + 43
   2   CoreFoundation                      0x00007fff8f6624ce -[NSObject doesNotRecognizeSelector:] + 190
   3   CoreFoundation                      0x00007fff8f5c3133 ___forwarding___ + 371
   4   CoreFoundation                      0x00007fff8f5c2f48 _CF_forwarding_prep_0 + 232
   5   CoreFoundation                      0x00007fff8f548c66 CFDataGetLength + 118
   6   CoreFoundation                      0x00007fff8f5791df CFStringCreateFromExternalRepresentation + 31
   7   asLJ                                0x0000000100013828 +[stripHTML stripAllHtmlFromString:] + 212

特别是,我不明白对CFStringCreateFromExternalRepresentation的调用发生在哪里,所以我不知道我的代码的哪一部分(+[stripHTML stripAllHtmlFromString:])导致异常。是什么导致了对CFStringCreateFromExternalRepresentation的调用?如果很明显,我做错了什么导致异常呢?将来,我该如何确定调用CFStringCreateFromExternalRepresentation的内容?

这是+[stripHTML stripAllHtmlFromString:]

+ (NSString *)stripAllHtmlFromString:(NSString *)inputString
{
    // based on code from http://sugarmaplesoftware.com/25/strip-html-tags/#comment-71

    NSError *theError = NULL;
    NSString *modifiedInputString = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n\n\n\n",inputString]; // adding some spare newlines at the end to ensure that things will work even with a short non-HTML string
    NSXMLDocument *theDocument = [[NSXMLDocument alloc] initWithXMLString:modifiedInputString
                                                                  options:NSXMLDocumentTidyHTML
                                                                    error:&theError];

    NSString *theXSLTString = @"<?xml version='1.0' encoding='utf-8'?>"
                                "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:xhtml='http://www.w3.org/1999/xhtml'>"
                                "<xsl:output method='text'/>"
                                "<xsl:template match='xhtml:head'></xsl:template>"
                                "<xsl:template match='xhtml:script'></xsl:template>"
                                "</xsl:stylesheet>";    
    NSData *theData = [theDocument objectByApplyingXSLTString:theXSLTString arguments:NULL error:&theError];
    [theDocument release];
    return [[[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding] autorelease];
}

2 个答案:

答案 0 :(得分:3)

哦,实际上,-objectByApplyingXSLTString:arguments:error:可能会返回NSXMLDocument而不是NSData。因此,对-[NSString initWithData:encoding:]的调用正在调用它认为是-length的内容NSData,但NSXMLDocument无法识别。{/ p>

答案 1 :(得分:0)

Ken Thomases's answer似乎完全正确 - 出于某种原因,对于非常短的输入(特别是空字符串),给定XSLT的-objectByApplyingXSLTString:arguments:error:返回NSXMLDocument(即使我不要以为它应该)。要修复它,我首先检测我们是否得到NSXMLDocument,如果是,请将其转换为XML的字符串表示形式并将其反馈给方法;否则假设我们得到了我们原先预期的NSData

用下面的代码替换给定方法的最后3行(来自NSData *theData = ... on)似乎解决了这个问题。

// Had a report of an exception that seemed to indicate objectByApplyingXSLTString:arguments:error: was returning an NSXMLDocument objectinstead of an NSData object, so let's guard against that.  (discussed at https://stackoverflow.com/q/10669479/291280 )
NSObject *XSTLresult = [theDocument objectByApplyingXSLTString:theXSLTString arguments:NULL error:&theError];
[theDocument release];
if ([XSTLresult isKindOfClass:[NSXMLDocument class]]) {
    // If the result is an NSXMLDocument, call XMLData to get an NSData object, turn it into a string, and feed that back into this method...
    return [self stripAllHtmlFromString:[[[NSString alloc]
                                          initWithData:[(NSXMLDocument *)XSTLresult XMLData]
                                          encoding:NSUTF8StringEncoding]
                                         autorelease]
            ];
} else {
    // Otherwise, assume we have an NSData object.
    return [[[NSString alloc] initWithData:(NSData *)XSTLresult encoding:NSUTF8StringEncoding] autorelease];
}