2013-04-17 2 views
2

У меня есть следующая вспомогательная функция для преобразования XML с помощью XSLT:Сбор 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 (скажем, EXSLT «s node-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, на линии 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; 
} 

Но это немного рубить, так что будьте осторожны ...

Если вы не удовлетворенное этим решением, должно быть возможно переопределить переменную (которая по умолчанию ссылается на xmlGenericErrorDefaultFunc) с собственной пользовательской функцией обработки ошибок, используя initGenericErrorDefaultFunc по строке 864 от xmlerror.h. Это было бы намного безопаснее, но также более сложно (если это вообще возможно).

+0

Фантастический, @SimonM - спасибо за это. Я буду играть и посмотреть, что я придумал. – ABach

Смежные вопросы