module Xommelier::Xml::Element::Serialization

Constants

SAVE_OPTIONS
SERIALIZATION_OPTIONS

Public Instance Methods

<=>(other) click to toggle source
Calls superclass method
# File lib/xommelier/xml/element/serialization.rb, line 148
def <=>(other)
  if text? && other.is_a?(String)
    text.to_s <=> other
  else
    super
  end
end
==(other) click to toggle source
Calls superclass method
# File lib/xommelier/xml/element/serialization.rb, line 156
def ==(other)
  if text? && other.is_a?(String)
    text.to_s == other
  else
    super
  end
end
=~(other) click to toggle source
Calls superclass method
# File lib/xommelier/xml/element/serialization.rb, line 164
def =~(other)
  if text? && other.is_a?(Regexp)
    text.to_s =~ other
  else
    super
  end
end
from_xml(xml, options = {}) click to toggle source
# File lib/xommelier/xml/element/serialization.rb, line 54
def from_xml(xml, options = {})
  xml = Nokogiri::XML(xml) if IO === xml || String === xml
  @_xml_node = options.delete(:node) { xml.at_xpath(element_xpath(xml.document, element_name)) }

  self.text = @_xml_node.inner_html if text? && @_xml_node.inner_html.present?

  self.class.attributes.values.each do |attribute|
    deserialize_attribute(attribute)
  end

  self.class.elements.values.each do |element|
    deserialize_element(element)
  end
end
Also aliased as: from_xommelier
from_xommelier(xml, options = {})
Alias for: from_xml
to_hash() click to toggle source
# File lib/xommelier/xml/element/serialization.rb, line 123
def to_hash
  attributes.dup.tap do |hash|
    @elements.each do |name, value|
      element = element_options(name)
      if element.multiple?
        if value.count > 1
          name = element.plural
          value = value.map(&:to_hash) if element.complex_type?
        else
          value = value.first.to_hash
        end
      else
        value = value.to_hash if element.complex_type?
      end
      hash[name] = value
    end
    hash[:text] = text if text?
  end
end
to_nokogiri() click to toggle source

@return [Nokogiri::XML::Node]

# File lib/xommelier/xml/element/serialization.rb, line 144
def to_nokogiri
  ensure_xml_document.root
end
to_s() click to toggle source
Calls superclass method
# File lib/xommelier/xml/element/serialization.rb, line 172
def to_s
  if text?
    text.to_s
  else
    super
  end
end
to_xml(options = {}) click to toggle source
# File lib/xommelier/xml/element/serialization.rb, line 71
def to_xml(options = {})
  options = SERIALIZATION_OPTIONS.merge(options)
  save_options = options.slice(:encoding, *SAVE_OPTIONS)
  options = options.except(*SAVE_OPTIONS)

  element_name = options.delete(:element_name) { self.element_name }
  element_name = element_name.to_s
  element_name << '_' if %w(text class id).include?(element_name)
  xmlns = options[:ns] || self.xmlns
  if options[:builder] # Non-root element
    builder = options.delete(:builder)
    attribute_values = {}
    namespaces = builder.doc.namespaces
    prefix = options[:prefix] || namespaces.key(xmlns.uri).try(:[], 6..-1).presence
  else # Root element
    builder = Nokogiri::XML::Builder.new(options)
    attribute_values = children_namespaces.inject(xmlns: xmlns.uri) do |hash, ns|
      hash["xmlns:#{ns.as}"] = ns.uri
      hash
    end
    attribute_values.delete("xmlns:#{xmlns.as}")
    attribute_values.delete('xmlns:xml')
    attribute_values.delete(:xmlns) if self.xmlns.default?
    namespaces = attribute_values
    prefix = nil
  end
  current_xmlns = builder.doc.namespaces[prefix ? "xmlns:#{prefix}" : 'xmlns']
  attributes.each do |name, value|
    attribute = attribute_options(name)
    attribute_name = attribute.attribute_name
    ns = attribute.ns
    if ns.uri != current_xmlns && (attr_prefix = namespaces.key(ns.uri).try(:[], 6..-1).presence)
      attribute_name = "#{attr_prefix}:#{attribute_name}"
    end
    serialize_attribute(attribute_name, value, attribute_values) if !value.nil? || attribute.required?
  end
  @_xml_node = (prefix ? builder[prefix] : builder)
               .send(element_name, attribute_values) do |xml|
    self.class.elements.each do |name, element|
      value = elements.fetch(name, options[:default])
      next if value.nil?
      element.override(xmlns: xmlns) do
        serialize_element(name, value, xml, element)
      end
    end
    xml.text(@text) if text?
  end.instance_variable_get(:@node)
  builder.to_xml(save_options)
end
Also aliased as: to_xommelier
to_xommelier(options = {})
Alias for: to_xml

Protected Instance Methods

children_namespaces(namespaces = Set[xmlns]) click to toggle source
# File lib/xommelier/xml/element/serialization.rb, line 188
def children_namespaces(namespaces = Set[xmlns])
  elements.inject(namespaces) do |result, (name, children)|
    element = self.class.elements[name]
    result << element.ns
    result += attributes.keys.map { |attr_name| attribute_options(attr_name).ns }
    if element.complex_type?
      Array(children).each do |child|
        result += child.children_namespaces
      end
    end
    result
  end
end
deserialize_attribute(attribute) click to toggle source

@param [Xommelier::Xml::Element::Structure::Attribute] attribute

# File lib/xommelier/xml/element/serialization.rb, line 220
def deserialize_attribute(attribute)
  ns = attribute.ns
  if ns == xmlns || attribute.xml?
    send(attribute.writer, @_xml_node[attribute.attribute_name])
  else
    send(attribute.writer, @_xml_node.attribute_with_ns(attribute.attribute_name, ns.uri.to_s).try(:value))
  end
end
deserialize_element(element) click to toggle source

@param [Xommelier::Xml::Element::Structure::Element] element

# File lib/xommelier/xml/element/serialization.rb, line 230
def deserialize_element(element)
  nodes = @_xml_node.xpath("./#{ns_element(element.ns.as, element.element_name)}", element.ns.to_hash)
  if nodes.any?
    if element.multiple?
      children = nodes.map { |node| typecast_element(node, element) }
      send(element.plural_writer, children)
    else
      send(element.writer, typecast_element(nodes[0], element))
    end
  end
end
element_xpath(xml_doc = xml_document, name = nil) click to toggle source
# File lib/xommelier/xml/element/serialization.rb, line 184
def element_xpath(xml_doc = xml_document, name = nil)
  self.class.element_xpath(xml_doc, name)
end
ensure_xml_document() click to toggle source
# File lib/xommelier/xml/element/serialization.rb, line 206
def ensure_xml_document
  to_xml unless xml_document
  xml_document
end
serialize_attribute(name, value, attributes) click to toggle source
# File lib/xommelier/xml/element/serialization.rb, line 215
def serialize_attribute(name, value, attributes)
  attributes[name] = value.to_xommelier
end
serialize_element(name, value, xml, element) click to toggle source

@param [Object] name @param [Object] value @param [Object] xml @param [Xommelier::Xml::Element::Structure::Element] element

# File lib/xommelier/xml/element/serialization.rb, line 256
def serialize_element(name, value, xml, element)
  if element.multiple?
    element.override(multiple: false) do
      value.each do |item|
        serialize_element(name, item, xml, element)
      end
    end
  else
    xmlns = element.overridden_xmlns || self.xmlns
    prefix = (xml.doc.namespaces.key(element.ns.uri).try(:[], 6..-1).presence if xmlns != xml.doc.namespaces['xmlns'])
    case value
    when Xommelier::Xml::Element
      value.to_xommelier(
        builder: xml,
        element_name: element.element_name,
        prefix: prefix,
        ns: element.ns
      )
    else
      (prefix ? xml[prefix] : xml).send(element.serializable_element_name) do
        xml.text(value.to_xommelier)
      end
    end
  end
end
typecast_element(node, options) click to toggle source

@param [Nokogiri::XML::Node] node @param [Xommelier::Xml::Element::Structure::Element] options

# File lib/xommelier/xml/element/serialization.rb, line 244
def typecast_element(node, options)
  if options.complex_type?
    options.type.from_xommelier(xml_document, node: node)
  else
    options.type.from_xommelier(node.text)
  end
end
xml_document() click to toggle source
# File lib/xommelier/xml/element/serialization.rb, line 202
def xml_document
  @_xml_node.try(:document)
end
xmlns_xpath(xml_document = self.xml_document) click to toggle source
# File lib/xommelier/xml/element/serialization.rb, line 211
def xmlns_xpath(xml_document = self.xml_document)
  self.class.xmlns_xpath(xml_document)
end