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

W

Wes Gamble

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
 
W

Wes Gamble

Wes said:
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
 
W

Wes Gamble

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
 
W

Wes Gamble

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
 
W

Wes Gamble

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top