2013-04-17 59 views
2

我有以下的辅助功能通过XSLT转换XML:收集NSXMLDocument报警输出

- (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; 
} 

它正常工作,但有一个轻微的怪癖,我可以使用援助。

当我尝试使用XSLT功能是未知NSXMLDocument(比如,EXSLTnode-set()),我得到在Xcode输出类似下面 - 第一线,特别是利益:

xmlXPathCompOpEval: function node-set not found

XPath error: Unregistered function runtime

error: element for-each

Failed to evaluate the 'select' expression.

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

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

所以,这里的问题:我怎样才能抓住上述输出(以便我可以用它来显示相关消息给我的用户)?

非常感谢!

回答

1

的误差内libxml深情况的发生,在线路的xpath.c 13479,这结束了对error.c 71行,打印到stderr主叫xmlGenericErrorDefaultFunc()。因此,要做到这一点最简单的方法是捕获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; 
} 

但是,这是一个黑客位的,所以要小心......

如果你不对该解决方案感到满意的话,应该可以使用xmlerror.h的第864行的initGenericErrorDefaultFunc替代使用自己的自定义错误处理函数的变量xmlGenericError(默认情况下,其参考号为xmlGenericErrorDefaultFunc)。这会更安全,但也更复杂(如果可能的话)。

+0

太棒了,@SimonM - 感谢您的挖掘。我会玩,看看我想出了什么。 – ABach