【问题标题】:Collecting NSXMLDocument warning output收集 NSXMLDocument 警告输出
【发布时间】:2013-04-10 11:47:50
【问题描述】:

我有以下通过 XSLT 转换 XML 的辅助函数:

- (NSXMLDocument *)transform:(NSString *)xml :(NSString *)xslt
{
    NSError *xmlDocErr = nil;
    NSXMLDocument *transformedXmlDoc = nil;
    
    NSXMLDocument *xmlDoc = [[NSXMLDocument alloc]
                              initWithXMLString:xml
                              options:NSXMLDocumentValidate
                              error:&xmlDocErr];
    
    if (xmlDocErr) {
        NSLog(@"Error: %@", [xmlDocErr localizedDescription]);
    }
    else {
        transformedXmlDoc = [xmlDoc objectByApplyingXSLTString:xslt 
                                    arguments:nil
                                    error:&xmlDocErr];
        if (xmlDocErr) {
            NSLog(@"Error: %@", [xmlDocErr localizedDescription]);
        }
    }

    return transformedXmlDoc;
}

它按预期工作,但有一个小问题我可以求助。

当我尝试使用 NSXMLDocument 未知的 XSLT 函数(例如,EXSLTnode-set())时,我在 Xcode 中得到类似于以下内容的输出 - 特别是第一行是令人感兴趣的:

xmlXPathCompOpEval:找不到函数节点集

XPath 错误:未注册的函数运行时

错误:每个元素

无法评估“选择”表达式。

这很酷;这正是我所期望的。

然而,对我来说有趣的是,输出在任何地方都不包含"Error: "(如果该输出已被我的[xmlDocErr localizedDescription] 调用捕获,则应该是这种情况)。

那么,问题来了:我怎样才能获取上面的输出(以便我可以用它来向我的用户显示相关消息)?

非常感谢!

【问题讨论】:

    标签: objective-c cocoa nserror nsxml nsxmldocument


    【解决方案1】:

    错误发生在libxml 的深处,位于xpath.c 的第13479 行,最终在error.c 的第71 行调用xmlGenericErrorDefaultFunc(),打印到stderr。所以最简单的方法是在 XSLT 处理过程中捕获stderr

    - (NSXMLDocument *)transform:(NSString *)xml :(NSString *)xslt
    {
        NSError *xmlDocErr = nil;
        NSXMLDocument *transformedXmlDoc = nil;
    
        NSXMLDocument *xmlDoc = [[NSXMLDocument alloc]
                                 initWithXMLString:xml
                                 options:NSXMLDocumentValidate
                                 error:&xmlDocErr];
    
        if (xmlDocErr) {
            NSLog(@"Error: %@", [xmlDocErr localizedDescription]);
        }
        else {
            // Pipe for stderr
            NSPipe *pipe = [NSPipe pipe];
            // Duplicate of stderr (will use later)
            int cntl = fcntl(STDERR_FILENO,F_DUPFD);
            // Redirect stderr through our pipe
            dup2([[pipe fileHandleForWriting] fileDescriptor], STDERR_FILENO);
    
            transformedXmlDoc = [xmlDoc objectByApplyingXSLTString:xslt
                                                         arguments:nil
                                                             error:&xmlDocErr];
            // Get the data
            NSData *dat = [[pipe fileHandleForReading] availableData];
            // Redirect stderr through our duplicate, to restore default output behavior
            dup2(cntl, STDERR_FILENO);
            // Did anything get logged?
            if ([dat length]>0) {
                NSLog(@"Error: %@", [[NSString alloc] initWithData:dat encoding:NSASCIIStringEncoding]);
            }
            if (xmlDocErr) {
                NSLog(@"Error: %@", [xmlDocErr localizedDescription]);
            }
        }
    
        return transformedXmlDoc;
    }
    

    但这有点小题大做,所以要小心...

    如果您对该解决方案不满意,应该可以使用您自己的自定义错误处理函数覆盖变量xmlGenericError(默认情况下引用xmlGenericErrorDefaultFunc),使用initGenericErrorDefaultFunc on xmlerror.h 的第 864 行。那会更安全,但也更复杂(如果可能的话)。

    【讨论】:

    • 太棒了,@SimonM - 感谢您的挖掘。我会到处玩,看看我想出了什么。
    猜你喜欢
    • 2021-12-11
    • 1970-01-01
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多