def deserialize xml, typename=nil
if IS_JRUBY
type_attr = xml.attribute_nodes.find { |a| a.name == 'type' &&
a.namespace &&
a.namespace.prefix == 'xsi' }
else
type_attr = xml.attribute_with_ns('type', NS_XSI)
end
typename = (type_attr || typename).to_s
if typename =~ /^ArrayOf/
typename = demangle_array_type $'
return xml.children.select(&:element?).map { |c| deserialize c, typename }
end
t = @conn.type typename
if t <= BasicTypes::DataObject
props_desc = t.full_props_desc
h = {}
props_desc.select { |d| d['is-array'] }.each { |d| h[d['name'].to_sym] = [] }
xml.children.each do |c|
next unless c.element?
field = c.name.to_sym
d = t.find_prop_desc(field.to_s) or next
o = deserialize c, d['wsdl_type']
if h[field].is_a? Array
h[field] << o
else
h[field] = o
end
end
t.new h
elsif t == BasicTypes::ManagedObjectReference
@conn.type(xml['type']).new @conn, xml.text
elsif t <= BasicTypes::ManagedObject
@conn.type(xml['type'] || t.wsdl_name).new @conn, xml.text
elsif t <= BasicTypes::Enum
xml.text
elsif t <= BasicTypes::KeyValue
h = {}
xml.children.each do |c|
next unless c.element?
h[c.name] = c.text
end
[h['key'], h['value']]
elsif t <= String
xml.text
elsif t <= Symbol
xml.text.to_sym
elsif t <= Integer
xml.text.to_i
elsif t <= Float
xml.text.to_f
elsif t <= Time
Time.parse xml.text
elsif t == BasicTypes::Boolean
xml.text == 'true' || xml.text == '1'
elsif t == BasicTypes::Binary
xml.text.unpack('m')[0]
elsif t == BasicTypes::AnyType
fail "attempted to deserialize an AnyType"
else fail "unexpected type #{t.inspect} (#{t.ancestors * '/'})"
end
rescue
$stderr.puts "#{$!.class} while deserializing #{xml.name} (#{typename}):"
$stderr.puts xml.to_s
raise
end