Search code examples
javaxmlxslttransformer-model

TransformerConfigurationException:Could not compile sytlesheet


When I try to transform xml with xslt in my web application, the TransformerConfigurtionException exception is thrown in weblogic 10.3 server. The same web application code works fine in Tomcat 7.0. I have no clue what could be cause for this exception.

Exception:
javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet
ERROR: 'Syntax error in 'format-date($date,'[MNn][D],[Y]','en',(),())'.'
FATAL ERROR: 'Could not compile stylesheet'

After removing the format-date function in xslt, i got another exception (javax.xml.tranform.TransformerException:java.lang.ArrayIndexOutOfBoundsException

Code:

TransformerFactory factory = TransformerFactory.newInstance();

  try
  {
   factory.newTransformer().transform( new StreamSource( new StringReader( xml ) ), new StreamResult( transformResult ) );

   Source documentInfoSource = new StringSource( new String( transformResult.toByteArray() ) );
   transformResult.reset();

   factory.setURIResolver( new URIResolver()
   {
    @Override
    public Source resolve(String href, String base) throws TransformerException
    {
     try
     {
      return new StreamSource( EcrionDocumentRenderServiceImpl.class.getClassLoader().getResourceAsStream( href ) );
     }

     catch( Exception e )
     {
      throw new TransformerException( e );
     }
    }

   } );
   factory.newTransformer( new StreamSource( Thread.currentThread().getContextClassLoader().getResourceAsStream( "template.xsl" ) ) ).transform( documentInfoSource, new StreamResult( transformResult ) );TransformerFactory factory = TransformerFactory.newInstance();

  try
  {
   factory.newTransformer().transform( new StreamSource( new StringReader( xml ) ), new StreamResult( transformResult ) );

   Source documentInfoSource = new StringSource( new String( transformResult.toByteArray() ) );
   transformResult.reset();

   factory.setURIResolver( new URIResolver()
   {
    @Override
    public Source resolve(String href, String base) throws TransformerException
    {
     try
     {
      return new StreamSource( EcrionDocumentRenderServiceImpl.class.getClassLoader().getResourceAsStream( href ) );
     }

     catch( Exception e )
     {
      throw new TransformerException( e );
     }
    }

   } );
   factory.newTransformer( new StreamSource( Thread.currentThread().getContextClassLoader().getResourceAsStream( "template.xsl" ) ) ).transform( documentInfoSource, new StreamResult( transformResult ) );

Solution

  • format-date() is an XSLT 2.0 function. When you load an XSLT transformer using the JAXP TransformerConfigurationFactory, you have no way of controlling whether the processor that is returned is an XSLT 1.0 or 2.0 processor - it depends on what happens to be found on the classpath. My guess is that there was no XSLT 2.0 processor on the classpath, so the default built-in Xalan processor has been loaded, and this does not support XSLT 2.0 (and therefore format-date()).

    If your code is dependent on XSLT 2.0, then

    a) make sure Saxon is on the classpath

    b) load it explicitly by replacing

    TransformerFactory factory = TransformerFactory.newInstance();
    

    with

    TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl();