2013-04-17 83 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