File: parser.rb

package info (click to toggle)
ruby-aws-sdk-core 3.212.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,232 kB
  • sloc: ruby: 17,533; makefile: 4
file content (96 lines) | stat: -rw-r--r-- 2,714 bytes parent folder | download
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