Class: RightScale::CloudApi::Parser::Sax

Inherits:
Object
  • Object
show all
Defined in:
lib/base/parsers/sax.rb

Constant Summary collapse

UTF_8_STR =
"UTF-8"
TEXT_MARK =
"@@text"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Sax

Returns a new instance of Sax.



48
49
50
51
52
53
54
# File 'lib/base/parsers/sax.rb', line 48

def initialize(options = {})
  @tag            = {}
  @path           = []
  @str_path       = []
  @options        = options
  @cached_strings = {}
end

Class Method Details

.parse(input, options = {}) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/base/parsers/sax.rb', line 36

def self.parse(input, options = {})
  # Parse the xml text
  # http://libxml.rubyforge.org/rdoc/
  xml_context          = ::XML::Parser::Context.string(input)
  xml_context.encoding = ::XML::Encoding::UTF_8 if options[:encoding] == UTF_8_STR
  sax_parser           = ::XML::SaxParser.new(xml_context)
  sax_parser.callbacks = new(options)
  sax_parser.parse
  sax_parser.callbacks.result
end

Instance Method Details

#cache_string(name) ⇒ Object



63
64
65
66
67
68
69
# File 'lib/base/parsers/sax.rb', line 63

def cache_string(name)
  unless @cached_strings[name]
    name = name.freeze
    @cached_strings[name] = name 
  end
  @cached_strings[name]
end

#on_cdata_block(cdata) ⇒ Object



170
171
# File 'lib/base/parsers/sax.rb', line 170

def on_cdata_block(cdata)
end

#on_characters(chars) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/base/parsers/sax.rb', line 110

def on_characters(chars)
  # Ignore lines that contains white spaces only
  return if chars[/\A\s*\z/m]
  # Put Text
  if  @options[:encoding] == UTF_8_STR
    # setting the encoding in context doesn't work(open issue with libxml-ruby).
    # force encode as a work around.
    # TODO remove the force encoding when issue in libxml is fixed
    chars = chars.force_encoding(UTF_8_STR) if chars.respond_to?(:force_encoding)
  end
  name = cache_string(TEXT_MARK)
  (@tag[name] ||= '') << chars
end

#on_comment(msg) ⇒ Object



125
126
127
128
129
# File 'lib/base/parsers/sax.rb', line 125

def on_comment(msg)
  # Put Comments
  name = cache_string('@@comment')
  (@tag[name] ||= '') << msg
end

#on_end_documentObject



194
195
# File 'lib/base/parsers/sax.rb', line 194

def on_end_document
end

#on_end_element_ns(name, prefix, uri) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/base/parsers/sax.rb', line 132

def on_end_element_ns(name, prefix, uri)
  name = cache_string(name)
  # Finalize tag's text
  if @tag.key?(TEXT_MARK) && @tag[TEXT_MARK].empty?
    # Delete text if it is blank
    @tag.delete(TEXT_MARK)
  elsif @tag.keys.count == 0
    # Set tag value to nil then the tag is blank
    @tag = nil
  elsif @tag.keys == [TEXT_MARK]
    # Set tag value to string if it has no any other data
    @tag = @tag[TEXT_MARK]
  end
  # Make sure we saved the changes
  if @path.last[name].is_a?(Array)
    # If it is an Array then update the very last item
    @path.last[name][-1] = @tag
  else
    # Otherwise just replace the tag
    @path.last[name] = @tag
  end
  # Pop parent tag
  @tag = @path.pop
end

#on_error(msg) ⇒ Object

Callbacks



74
75
76
# File 'lib/base/parsers/sax.rb', line 74

def on_error(msg)
  fail msg
end

#on_external_subset(name, external_id, system_id) ⇒ Object



190
191
# File 'lib/base/parsers/sax.rb', line 190

def on_external_subset (name, external_id, system_id)
end

#on_has_external_subsetObject



186
187
# File 'lib/base/parsers/sax.rb', line 186

def on_has_external_subset ()
end

#on_has_internal_subsetObject



174
175
# File 'lib/base/parsers/sax.rb', line 174

def on_has_internal_subset()
end

#on_internal_subset(name, external_id, system_id) ⇒ Object



178
179
# File 'lib/base/parsers/sax.rb', line 178

def on_internal_subset(name, external_id, system_id)
end

#on_is_standaloneObject



182
183
# File 'lib/base/parsers/sax.rb', line 182

def on_is_standalone ()
end

#on_processing_instruction(target, data) ⇒ Object



166
167
# File 'lib/base/parsers/sax.rb', line 166

def on_processing_instruction(target, data)
end

#on_reference(name) ⇒ Object



162
163
# File 'lib/base/parsers/sax.rb', line 162

def on_reference (name)
end

#on_start_documentObject



158
159
# File 'lib/base/parsers/sax.rb', line 158

def on_start_document
end

#on_start_element_ns(name, attr_hash, prefix, uri, namespaces) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/base/parsers/sax.rb', line 79

def on_start_element_ns(name, attr_hash, prefix, uri, namespaces)
  name = cache_string(name)
  # Push parent tag
  @path << @tag
  # Create a new tag
  if @tag[name]
    @tag[name] = [ @tag[name] ] unless @tag[name].is_a?(Array)
    @tag[name] << {}
    @tag = @tag[name].last
  else
    @tag[name] = {}
    @tag = @tag[name]
  end
  # Put attributes
  current_namespaces = Array(namespaces.keys)
  current_namespaces << nil if current_namespaces._blank?
  attr_hash.each do |key, value|
    current_namespaces.each do |namespace|
      namespace = namespace ? "#{namespace}:" : ''
      namespace_and_key = cache_string("@#{namespace}#{key}")
      @tag[namespace_and_key] = value
    end
  end
  # Put namespaces
  namespaces.each do |key, value|
    namespace       = cache_string(key ? "@xmlns:#{key}" : '@xmlns')
    @tag[namespace] = value
  end
end

#resultObject



57
58
59
60
# File 'lib/base/parsers/sax.rb', line 57

def result
  @cached_strings.clear
  @tag
end