Module: Rsxml::Xml

Defined in:
lib/rsxml/xml.rb

Constant Summary collapse

WRAP_ELEMENT =
"RsxmlXmlWrapper"

Class Method Summary collapse

Class Method Details

.explode_element(element) ⇒ Object

given a Nokogiri::XML::Element in element , produce a [[local_part, prefix, namespace], {[local_part, prefix, namespace]=>value} pair of exploded element name and attributes with exploded names



42
43
44
45
46
47
48
49
50
# File 'lib/rsxml/xml.rb', line 42

def explode_element(element)
  eelement = explode_node(element)

  eattrs = Hash[element.attributes.map do |name,attr|
                  [explode_node(attr), attr.value]
                end]

  [eelement, eattrs]
end

.explode_node(node) ⇒ Object



30
31
32
33
34
35
36
37
# File 'lib/rsxml/xml.rb', line 30

def explode_node(node)
  node_name = node.name
  if node.namespace
    node_prefix = node.namespace.prefix || "" # nokogiri has nil prefix for default namespace
    node_uri = node.namespace.href
  end
  node = node_uri ? [node_name, node_prefix, node_uri] : node_name
end

.namespace_bindings_from_defs(ns_defs) ⇒ Object

give a list of Nokogiri::XML::Namespace definitions, produce a Hash {prefix=>uri} of namespace bindings



54
55
56
57
58
59
# File 'lib/rsxml/xml.rb', line 54

def namespace_bindings_from_defs(ns_defs)
  (ns_defs||[]).reduce({}) do |h,ns_def|
    h[ns_def.prefix||""] = ns_def.href
    h
  end
end

.traverse(element, visitor, context = Visitor::Context.new) ⇒ Object

pre-order traversal of the Nokogiri Nodes, calling methods on the visitor with each Node



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rsxml/xml.rb', line 63

def traverse(element, visitor, context = Visitor::Context.new)
  ns_bindings = namespace_bindings_from_defs(element.namespace_definitions)
  context.ns_stack.push(ns_bindings)

  eelement, eattrs = explode_element(element)

  begin
    visitor.element(context, eelement, eattrs, ns_bindings) do
      element.children.each do |child|
        if child.element?
          traverse(child, visitor, context)
        elsif child.text?
          visitor.text(context, child.content)
        else
          Rsxml.log{|logger| logger.warn("unknown Nokogiri Node type: #{child.inspect}")}
        end
      end
    end
  ensure
    context.ns_stack.pop
  end

  visitor
end

.unwrap_fragment(node) ⇒ Object



22
23
24
25
26
27
28
# File 'lib/rsxml/xml.rb', line 22

def unwrap_fragment(node)
  if node.name==WRAP_ELEMENT
    node.children.first
  else
    node
  end
end

.wrap_fragment(fragment, ns_prefixes) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/rsxml/xml.rb', line 8

def wrap_fragment(fragment, ns_prefixes)
  return fragment if !ns_prefixes

  ns_attrs = Hash[ns_prefixes.map do |prefix,href|
                    prefix = nil if prefix.to_s.length == 0
                    [["xmlns", prefix].compact.join(":"), href]
                  end]
  xml = Builder::XmlMarkup.new
  xml.__send__(WRAP_ELEMENT, ns_attrs) do
    xml << fragment
  end
  xml.target!
end