Xalan with Ruby (either command line or via Jrb)?

Does anyone have any experience will using Xalan from a Ruby program
(Rails app. especially useful)?

I'm willing to entertain running command lines but would like to use Jrb
(I've already got that working).

I'd consider JRuby but feel like that might be too heavyweight.

Any advice/feedback would be appreciated.

Thanks,
Wes

···

--
Posted via http://www.ruby-forum.com/.

Wes Gamble wrote:

Does anyone have any experience will using Xalan from a Ruby program
(Rails app. especially useful)?

I'm willing to entertain running command lines but would like to use Jrb
(I've already got that working).

I'd consider JRuby but feel like that might be too heavyweight.

Any advice/feedback would be appreciated.

Thanks,
Wes

I seem to have gotten this working - a basic Xalan XSL transform from
one file to another. The do_XSL_transform takes the input file name,
output file name, and XSL stylesheet file name as parameters.

Wes

···

==========================================

require 'rjb'

require_gem 'rjb', '>= 1.0.2'

module XalanSupport
  def XalanSupport.load_Xalan_libraries
    ['serializer.jar', 'xml-apis.jar', 'xercesImpl.jar',
'xalan.jar'].each do |lib_name|
      Rjb::load("#{RAILS_ROOT}/lib/#{lib_name}", ['-Xmx512M'])
    end
  end

  def XalanSupport.do_XSL_transform(infile, outfile, xsl)
    #Load all of the Jars
    XalanSupport.load_Xalan_libraries

    #Load all the classes
    stream_source_class =
Rjb::import('javax.xml.transform.stream.StreamSource')
    stream_result_class =
Rjb::import('javax.xml.transform.stream.StreamResult')
    file_output_stream_class = Rjb::import('java.io.FileOutputStream')
    transformer_factory_class =
Rjb::import('javax.xml.transform.TransformerFactory')

    #Create the XSL transformer
    transformer_factory = transformer_factory_class.newInstance
    transformer =
transformer_factory.newTransformer(stream_source_class.new(xsl))

    #Set up the input and output
    source = stream_source_class.new(infile)
    result =
stream_result_class.new(file_output_stream_class.new(outfile))

    transformer.transform(source, result)
  end
end

--
Posted via http://www.ruby-forum.com/\.

What I'd like to do with this, however, is to be able to return the
output of the transform directly to the browser, which would imply that
I would need to be able to grab output from a
javax.xml.transform.stream.StreamResult object and stream it back to the
browser. That way I don't have to generate an output file which I'm
just going to send back to the browser anyway.

But what would be the best way to connect a Java stream to a Ruby IO
object? Seems like I would have to have some mediator between the two
that would shuttle the data off the Java IO object onto the Ruby one.

Make sense?

Wes

···

--
Posted via http://www.ruby-forum.com/.

A better solution - use strings for input/output and no need to write
files. The return value from this method is the transformed XML.

···

==============================================================================
require 'rjb'

require_gem 'rjb', '>= 1.0.2'

module XalanSupport
  def XalanSupport.load_Xalan_libraries
    ['serializer.jar', 'xml-apis.jar', 'xercesImpl.jar',
'xalan.jar'].each do |lib_name|
      Rjb::load("#{RAILS_ROOT}/lib/#{lib_name}", ['-Xmx512M'])
    end
  end

  def XalanSupport.do_XSL_transform(instring, xsl_file_name)
    #Load all of the Jars
    XalanSupport.load_Xalan_libraries

    #Load all the classes
    string_reader_class = Rjb::import('java.io.StringReader')
    string_writer_class = Rjb::import('java.io.StringWriter')
    stream_source_class =
Rjb::import('javax.xml.transform.stream.StreamSource')
    stream_result_class =
Rjb::import('javax.xml.transform.stream.StreamResult')
    transformer_factory_class =
Rjb::import('javax.xml.transform.TransformerFactory')

    #Set up the input and output
    input_string_reader = string_reader_class.new(instring)
    output_string_writer = string_writer_class.new
    source = stream_source_class.new(input_string_reader)
    result = stream_result_class.new(output_string_writer)

    #Create the XSL transformer
    transformer_factory = transformer_factory_class.newInstance
    transformer =
transformer_factory.newTransformer(stream_source_class.new(xsl_file_name))

    transformer.transform(source, result)

    result.getWriter.getBuffer.toString
  end
end

--
Posted via http://www.ruby-forum.com/.

Two more things:

1) This:

['serializer.jar', 'xml-apis.jar', 'xercesImpl.jar', 'xalan.jar'].each
do |lib_name|
  Rjb::load("#{RAILS_ROOT}/lib/#{lib_name}", ['-Xmx512M'])
end

is not the best way to do the Rjb::load business, since Rjb::load is
what establishes the JVM. What the code above does is attempt to load
the JVM and change the classpath 4 different times, which doesn't really
make sense. What that probably should be is:

classpath = ''

['serializer.jar', 'xml-apis.jar', 'xercesImpl.jar', 'xalan.jar'].each
do |lib_name|
  classpath << "#{lib_name}:" #Use ; for Windows
end

Rjb::load("#{classpath}", ['-Xmx512M'])

In fact, I ended up doing the Rjb::load once in my application.

2) As it turns out, under J2SE 1.5.0 (Java 5, whatever), you don't
actually _need_ Xalan to do XSL transformations if you are ok with the
default implementation provided with the JDK. So the solution posted
previously works without any Rjb::load() statements and just the
contents of the XalanSupport.do_XSL_transform method.

Wes

···

--
Posted via http://www.ruby-forum.com/.