2

我有以下用于通过 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]调用捕获,则应该是这种情况)。

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

非常感谢!

4

1 回答 1

1

libxml错误发生在 的第 13479 行的深处xpath.c,最终调用xmlGenericErrorDefaultFunc()的第 71 行error.c,打印到stderr. stderr因此,最简单的方法是在 XSLT 处理进行时进行捕获:

- (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情况下为引用),使用. 这会更安全,但也更复杂(如果可能的话)。xmlGenericErrorDefaultFuncinitGenericErrorDefaultFuncxmlerror.h

于 2013-04-22T07:43:32.063 回答