Module: RForce::SoapPullable

Included in:
SoapResponseExpat, SoapResponseRexml
Defined in:
lib/rforce/soap_pullable.rb

Constant Summary collapse

SOAP_ENVELOPE =
'soapenv:Envelope'

Instance Method Summary collapse

Instance Method Details

#convert(string) ⇒ Object


93
94
95
96
97
98
99
100
101
102
# File 'lib/rforce/soap_pullable.rb', line 93

def convert(string)
  return nil if string.nil?
  s = string.strip

  case s
  when '' then nil
  when 'true', 'false' then ('true' == s)
  else s
  end
end

#local(tag) ⇒ Object

Split off the local name portion of an XML tag.


8
9
10
11
12
# File 'lib/rforce/soap_pullable.rb', line 8

def local(tag)
  first, second = tag.split ':'
  return first if second.nil?
  @namespaces.include?(first) ? second : tag
end

#tag_end(name) ⇒ Object


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
# File 'lib/rforce/soap_pullable.rb', line 33

def tag_end(name)
  return if @done || name == SOAP_ENVELOPE

  tag_name = local name
  working_hash = @stack.pop

  # We are either done or working on a certain depth in the current
  # stack.
  if @stack.empty?
    @parsed = working_hash
    @done = true
    return
  end

  index = @stack.size - 1

  # working_hash and @current_value have a mutually exclusive relationship.
  # If the current element doesn't have a value then it means that there
  # is a nested data structure.  In this case then working_hash is populated
  # and @current_value is nil.  Conversely, if @current_value has a value
  # then we do not have a nested data structure and working_hash will
  # be empty.
  raise 'Parser is confused' unless working_hash.empty? || @current_value.nil?

  use_value = working_hash.empty? ? convert(@current_value) : working_hash
  tag_sym = tag_name.to_sym
  element = @stack[index][tag_sym]

  if @stack[index].keys.include? tag_sym
    # This is here to handle the Id value being included twice and thus
    # producing an array.  We skip the second instance so the array is
    # not created.
    #
    # We also need to clear out the current value, so that the next
    # tag doesn't erroneously pick up the value of the Id.
    if tag_name == 'Id'
      @current_value = nil
      return
    end

    # We are here because the name of our current element is one that
    # already exists in the hash.  If this is the first encounter with
    # the duplicate tag_name then we convert the existing value to an
    # array otherwise we push the value we are working with and add it
    # to the existing array.
    if element.is_a?( Array )
      element << use_value
    else
      @stack[index][tag_sym] = [element, use_value]
    end
  else
    # We are here because the name of our current element has not been
    # assigned yet; anything inside 'records' should be an array
    @stack[index][tag_sym] = (:records == tag_sym ? [use_value] : use_value)
  end

  # We are done with the current tag so reset the data for the next one
  @current_value = nil
end

#tag_start(name, attrs) ⇒ Object


14
15
16
17
18
19
20
21
22
23
# File 'lib/rforce/soap_pullable.rb', line 14

def tag_start(name, attrs)
  # For shorter hash keys, we can strip any namespaces of the SOAP
  # envelope tag from the tags inside it.
  if name == SOAP_ENVELOPE
    @namespaces = attrs.keys.grep(/xmlns:/).map {|k| k.split(':').last}
    return
  end

  @stack.push MethodHash.new
end

#text(data) ⇒ Object


25
26
27
28
29
30
31
# File 'lib/rforce/soap_pullable.rb', line 25

def text(data)
  adding = data.strip.empty? ? nil : data

  if adding
    @current_value = (@current_value || '') + adding
  end
end