1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
# frozen_string_literal: true
module Aws
# @api private
module Xml
# A SAX-style XML parser that uses a shape context to handle types.
class Parser
# @param [Seahorse::Model::ShapeRef] rules
def initialize(rules, options = {})
@rules = rules
@engine = options[:engine] || self.class.engine
end
# Parses the XML document, returning a parsed structure.
#
# If you pass a block, this will yield for XML
# elements that are not modeled in the rules given
# to the constructor.
#
# parser.parse(xml) do |path, value|
# puts "uhandled: #{path.join('/')} - #{value}"
# end
#
# The purpose of the unhandled callback block is to
# allow callers to access values such as the EC2
# request ID that are part of the XML body but not
# part of the operation result.
#
# @param [String] xml An XML document string to parse.
# @param [Structure] target (nil)
# @return [Structure]
def parse(xml, target = nil, &unhandled_callback)
xml = '<xml/>' if xml.nil? or xml.empty?
stack = Stack.new(@rules, target, &unhandled_callback)
@engine.new(stack).parse(xml.to_s)
stack.result
end
class << self
# @param [Symbol,Class] engine
# Must be one of the following values:
#
# * :ox
# * :oga
# * :libxml
# * :nokogiri
# * :rexml
def engine=(engine)
@engine = Class === engine ? engine : load_engine(engine)
end
# @return [Class] Returns the default parsing engine.
# One of:
#
# * {OxEngine}
# * {OgaEngine}
# * {LibxmlEngine}
# * {NokogiriEngine}
# * {RexmlEngine}
def engine
set_default_engine unless @engine
@engine
end
def set_default_engine
[:ox, :oga, :libxml, :nokogiri, :rexml].each do |name|
@engine ||= try_load_engine(name)
end
unless @engine
raise 'Unable to find a compatible xml library. ' \
'Ensure that you have installed or added to your Gemfile one of ' \
'ox, oga, libxml, nokogiri or rexml'
end
end
private
def load_engine(name)
require "aws-sdk-core/xml/parser/#{name}_engine"
const_name = name[0].upcase + name[1..-1] + 'Engine'
const_get(const_name)
end
def try_load_engine(name)
load_engine(name)
rescue LoadError
false
end
end
set_default_engine
end
end
end
|