2015-10-26 4 views
5

Я пытаюсь передать исключение из java-кода, который будет включать сообщение из тега xsl: message при использовании Saxon.xslt: сообщение в Saxon 9.4 vs Saxon 9.6

Используя следующий файл XSLT

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <xsl:message terminate="yes">exception message</xsl:message> 
    </xsl:template> 
</xsl:stylesheet> 

На Saxon 9.4 со следующим кодом

public static void main(String[] args) throws TransformerException { 
    try { 
     TransformerFactory fact = new net.sf.saxon.TransformerFactoryImpl(); 
     Transformer newTransformer = fact.newTransformer(new StreamSource(new File("throw.xslt"))); 
     ((net.sf.saxon.Controller)newTransformer).setRecoveryPolicy(Configuration.DO_NOT_RECOVER); 
     ((net.sf.saxon.Controller)newTransformer).setMessageEmitter(new MessageWarner()); 
     newTransformer.transform(new StreamSource(new File("input.xml")), new StreamResult(new File("output.xml"))); 
    } catch (TransformerException e) { 
     System.out.println("THIS IS EXCEPTION: " + e.getMessage() + " <<<"); 
     throw e; 
    } 
} 

это дает THIS IS EXCEPTION: exception message <<<, что поведение я ожидал.

Но на Saxon 9.6 с небольшим количеством скорректированной кода из-за API изменения

public static void main(String[] args) throws TransformerException { 
    try { 
     TransformerFactory fact = new net.sf.saxon.TransformerFactoryImpl(); 
     Transformer newTransformer = fact.newTransformer(new StreamSource(new File("throw.xslt"))); 
     ((net.sf.saxon.jaxp.TransformerImpl)newTransformer).getUnderlyingController().setRecoveryPolicy(Configuration.DO_NOT_RECOVER); 
     ((net.sf.saxon.jaxp.TransformerImpl)newTransformer).getUnderlyingController().setMessageEmitter(new MessageWarner()); 
     newTransformer.transform(new StreamSource(new File("input.xml")), new StreamResult(new File("output.xml"))); 
    } catch (TransformerException e) { 
     System.out.println("THIS IS EXCEPTION: " + e.getMessage() + " <<<"); 
     throw e; 
    } 
} 

это дает THIS IS EXCEPTION: Processing terminated by xsl:message at line 4 in throw.xslt <<< и XSL: сообщение где-то теряется.

Как достичь "9.4" поведения на "9.6"?

ответ

1

К сожалению, новое сообщение Processing terminated... жестко закодировано в net.sf.saxon.expr.instruct.Message (Message.java:253 в 9.6.0-7). Вот обходной путь, который может дать вам то, что вам нужно:

public static void main(String[] args) throws TransformerException { 
    final StringWriter messageOut = new StringWriter(); 
    try { 
     TransformerFactory fact = new net.sf.saxon.TransformerFactoryImpl(); 
     Transformer newTransformer = fact.newTransformer(new StreamSource(new File("throw.xslt"))); 
     ((net.sf.saxon.jaxp.TransformerImpl)newTransformer).getUnderlyingController().setRecoveryPolicy(Configuration.DO_NOT_RECOVER); 
     ((net.sf.saxon.jaxp.TransformerImpl)newTransformer).getUnderlyingController().setMessageEmitter(new MessageEmitter() { 
       @Override 
       public void open() throws XPathException { 
        setWriter(messageOut); 
        super.open(); 
       } 
     }); 

     newTransformer.transform(new StreamSource(new File("input.xml")), new StreamResult(new File("output.xml"))); 
    } catch (TransformerException e) { 
     System.out.println("THIS IS EXCEPTION: " + e.getMessage() + " <<<"); 
     String message = messageOut.toString(); // this is the "exception message\n" that you want 
     // not sure why it has a \n on it 
     System.out.println("THIS IS THE MESSAGE WE WANT: " + message); 
     throw new TransformerException(message, e); // rethrow using the captured message, if you really want that "exception message" available to a caller in e.getMessage() 
    } 
} 
3

Это связано слушателю сообщения, к которому MessageEmitter отправляет сообщения. В саксоне 9.6 слушатель по умолчанию реализует UnfailingErrorListener, который не может генерировать исключение (как и все остальные слушатели в 9.6), но в 9.4 можно было исключить исключения из слушателей.

Однако, вы можете реализовать свой собственный сообщение эмиттер, который будет бросать исключение при встретив XML: сообщение с Terminate установлено Да, как это:

final class ExceptionThrowingMessageEmitter extends XMLEmitter { 
    boolean abort = false; 

    public void startDocument(int properties) throws XPathException { 
    setWriter(new StringWriter()); 
    abort = (properties & ReceiverOptions.TERMINATE) != 0; 
    super.startDocument(properties); 
    } 

    public void endDocument() throws XPathException { 
    XPathException de = new XPathException(getWriter().toString()); 
    de.setErrorCode("XTMM9000"); 
    if (abort) { 
     throw de; 
    } else { 
     //terminate set to no, do something like writing to the log file 
    } 
    } 

    public void close() { 
    // do nothing 
    } 
} 

, а затем, зарегистрировать его, как это:

transformer.getUnderlyingController().setMessageEmitter(new ExceptionThrowingMessageEmitter()); 

Таким образом, будет сгенерировано исключение, когда прекращает XML: сообщение

+0

вы знаете, если есть какой-нибудь способ получить XSL: сообщение номер строки/столбца с помощью эмиттер? –

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

  • Нет связанных вопросов^_^