lib/treat/workers/formatters/unserializers/xml.rb
# Unserialization of entities stored in XML format.
class Treat::Workers::Formatters::Unserializers::XML
require 'nokogiri'
# Unserialize an entity stored in XML format.
#
# Options: none.
def self.unserialize(document, options = {})
# Read in the XML file.
xml = File.read(document.file)
xml.gsub!('<treat>', '')
xml.gsub!('</treat>', '')
xml_reader = Nokogiri::XML::Reader.from_memory(xml)
current_element = nil
previous_depth = 0
# Read the XML file entity by entity.
while xml_reader.read
# The depth in the XML tree.
current_depth = xml_reader.depth
# If we are at the end of the children stack, pop up.
if previous_depth > current_depth && current_depth != 0
current_element = current_element.parent
end
# If an end element has been reached,
# change the depth and pop up on next
# iteration.
if xml_reader.node_type ==
Nokogiri::XML::Reader::TYPE_END_ELEMENT
previous_depth = current_depth
next
end
id = nil; value = ''
attributes = {}
edges = []
unless xml_reader.attributes.size == 0
xml_reader.attributes.each_pair do |k,v|
if k == 'id'
id = v.to_i
elsif k == 'edges'
a = v.split('--')
a.each do |b|
c = b.split(';')
c.each do |dep|
vals = []
dep.split(',').each do |name_val|
name_val = name_val[0..-2] if name_val[-1] == '}'
d = name_val.split(':')[1]
vals << d.strip if d
end
target, type, directed, direction = *vals
edges << [
target.to_i,
type,
(directed == 'true' ? true : false),
direction.to_i
]
end
end
elsif k == 'value'
value = v
else
v = v[1..-1].intern if v[0] == ':'
v = ":".intern if v == :''
v = v.to_i if v =~ /^[0-9]*$/
v = v.to_f if v =~ /^[0-9\.]*$/
v = false if v == 'false'
v = true if v == 'true'
attributes[k.intern] = v
end
end
end
current_value = ''
type = xml_reader.name.intern
if Treat.core.entities.list.include?(type)
if !current_element
current_element = self.revive(type, current_value, id)
else
current_element = current_element <<
self.revive(type, current_value, id)
end
current_element.features = attributes
current_element.features = attributes
edges.each do |edge|
target, type, directed, direction = *edge
current_element.link(target, type, directed, direction)
end
else
current_value = xml_reader.value ?
xml_reader.value.strip : ''
if current_value && current_value != ''
current_element.value = current_value
end
end
previous_depth = current_depth
end
document << current_element
document
end
def self.revive(type, value, id)
klass = Treat::Entities.const_get(type.cc)
klass.new(value, id)
end
end