2015-10-26 26 views
5

Sto provando a generare un'eccezione dal codice java che includerà il messaggio da xsl: tag messaggio quando si utilizza Saxon.xslt: messaggio in Saxon 9.4 vs Saxon 9.6

Utilizzando il seguente file 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> 

Su sassone 9.4 con il seguente codice

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 <<<, che è il comportamento mi aspetto.

Ma Saxon 9.6 con un po 'di codice corretto a causa di API cambia

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 <<< e il xsl: messaggio viene da qualche parte persa.

Come è possibile ottenere il comportamento "9.4" su "9.6"?

risposta

1

Sfortunatamente, il nuovo messaggio Processing terminated... è hardcoded in net.sf.saxon.expr.instruct.Message (Message.java:253 in 9.6.0-7). Ecco una soluzione che potrebbe dare quello che ti serve:

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

Ciò è dovuto a chi ascolta il messaggio, al quale MessageEmitter è l'invio di messaggi. In sassone 9.6 il listener predefinito sta implementando UnfailingErrorListener che non può generare eccezioni (come tutti gli altri listener in 9.6), ma in 9.4 è stato possibile generare eccezioni dagli ascoltatori.

Tuttavia, è possibile implementare il proprio messaggio emettitore, che sarebbe un'eccezione, mentre incontrando xml: messaggio con Termina impostata su Sì, in questo modo:

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

e poi, registrarlo come questo:

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

In questo modo, verrà generata un'eccezione, quando c'è concludano xml: messaggio

+0

fai a sapere se c'è un modo per ottenere xsl: message numero di riga/colonna utilizzando emettitore? –