fidothe/saxon-rb

View on GitHub
lib/saxon/processor.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
97%
require 'saxon/s9api'
require 'saxon/source'
require 'saxon/configuration'
require 'saxon/document_builder'
require 'saxon/xpath'
require 'saxon/xslt'
require 'saxon/serializer'

module Saxon
  # Saxon::Processor wraps the S9API::Processor object. This is the object
  # responsible for creating an XSLT compiler or an XML Document object.
  #
  # The Processor is threadsafe, and can be shared between threads. But, most
  # importantly XSLT or XML objects created by a Processor can only be used
  # with other XSLT or XML objects created by the same Processor instance.
  class Processor
    # Provides a processor with default configuration. Essentially a singleton
    # instance
    # @return [Saxon::Processor]
    def self.default
      @processor ||= create(Saxon::Configuration.default)
    end

    # @param config [File, String, IO, Saxon::Configuration] an open File, or string,
    #   containing a Saxon configuration file; an existing Saxon::Configuration
    #   object
    # @return [Saxon::Processor]
    def self.create(config = nil)
      Saxon::Loader.load!
      case config
      when nil
        licensed_or_config_source = false
      when Saxon::Configuration
        licensed_or_config_source = config.to_java
      else
        licensed_or_config_source = Saxon::Source.create(config).to_java
      end
      s9_processor = S9API::Processor.new(licensed_or_config_source)
      new(s9_processor)
    end

    # @api private
    # @param [net.sf.saxon.s9api.Processor] s9_processor The Saxon Processor
    #   instance to wrap
    def initialize(s9_processor)
      @s9_processor = s9_processor
    end

    # Generate a new DocumentBuilder that uses this Processor. Sharing
    # DocumentBuilders across threads is not safe.
    #
    # @yield A DocumentBuilder configuration DSL block, see
    #   {Saxon::DocumentBuilder.create}
    # @return [Saxon::DocumentBuilder] A new Saxon::DocumentBuilder
    def document_builder(&block)
      Saxon::DocumentBuilder.create(self, &block)
    end

    # Declare custom collations for use by XSLT, XPath, and XQuery processors
    #
    # @param collations [Hash<String => java.text.Collator>] collations to
    #   declare, as a hash of URI => Collator
    def declare_collations(collations)
      collations.each do |uri, collation|
        @s9_processor.declareCollation(uri, collation)
      end
    end
    # Generate a new <tt>XPath::Compiler</tt> that uses this
    # <tt>Processor</tt>. Sharing <tt>XPath::Compiler</tt>s across threads is
    # fine as long as the static context is not changed.
    #
    # @yield An XPath compiler DSL block, see {Saxon::XPath::Compiler.create}
    # @return [Saxon::XPath::Compiler] a new XPath compiler
    def xpath_compiler(&block)
      Saxon::XPath::Compiler.create(self, &block)
    end

    # Generate a new <tt>XSLT::Compiler</tt> that uses this
    # <tt>Processor</tt>. Sharing <tt>XSLT::Compiler</tt>s across threads is
    # fine as long as the static context is not changed.
    #
    # @yield An XSLT compiler DSL block, see {Saxon::XSLT::Compiler.create}
    # @return [Saxon::XSLT::Compiler] a new XSLT compiler
    def xslt_compiler(&block)
      Saxon::XSLT::Compiler.create(self, &block)
    end

    # Generate a new +Serializer+ for directly serializing XDM Values that uses
    # this +Processor+. +Serializer+s are effectively one-shot objects, and
    # shouldn't be reused.
    #
    # @yield the block passed will be called bound to the serializer instance. See
    #   {Saxon::Serializer::Object.create}
    # @return [Saxon::Serializer::Object]
    def serializer(&block)
      Saxon::Serializer::Object.create(self, &block)
    end

    # @return [net.sf.saxon.s9api.Processor] The underlying Saxon processor
    def to_java
      @s9_processor
    end

    # compare equal if the underlying java processor is the same instance for
    # self and other
    # @param other object to compare against
    def ==(other)
      other.to_java === to_java
    end

    # @return [Saxon::Configuration] This processor's configuration instance
    def config
      @config ||= Saxon::Configuration.create(self)
    end

    # Create a {DocumentBuilder} and construct a {Source} and parse some XML.
    # The args are passed to {Saxon::Source.create}, and the returned {Source}
    # is parsed using {DocumentBuilder#build}. If a {Source} is passed in, parse
    # that. Any options in +opts+ will be ignored in that case.
    #
    # @param input [Saxon::Source, IO, File, String, Pathname, URI] the input to
    #   be turned into a {Source} and parsed.
    # @param opts [Hash] for Source creation. See {Saxon::Source.create}.
    # @return [Saxon::XDM::Node] the XML document
    def XML(input, opts = {})
      source = Source.create(input, opts)
      document_builder.build(source)
    end

    # Construct a {Source} containing an XSLT stylesheet, create an
    # {XSLT::Compiler}, and compile the source, returning the {XSLT::Executable}
    # produced. If a {Source} is passed as +input+, then it will be passed
    # through to the compiler and any source-related options in +opts+ will be
    # ignored.
    #
    # @param input [Saxon::Source, IO, File, String, Pathname, URI] the input to
    #   be turned into a {Source} and parsed.
    # @param opts [Hash] for Source creation. See {Saxon::Source.create}.
    # @yield the block is executed as an {XSLT::EvaluationContext::DSL} instance
    #   and applied to the compiler
    # @return [Saxon::XSLT::Executable] the XSLT Executable
    def XSLT(input, opts = {}, &block)
      source = Source.create(input, opts)
      xslt_compiler(&block).compile(source)
    end
  end
end