Module: Rsxml::Namespace
- Defined in:
- lib/rsxml/namespace.rb
Class Method Summary collapse
-
.compact_attr_qnames(ns_stack, attrs) ⇒ Object
compact all attribute QNames to Strings.
-
.compact_qname(ns_stack, name) ⇒ Object
produce a QName String from a [LocalPart, prefix, URI] triple.
-
.explode_attr_qnames(ns_stack, attrs) ⇒ Object
explode attribute QNames to [LocalPart, prefix, URI] triples,.
-
.explode_qname(ns_stack, qname, attr = false) ⇒ Object
split a QName into [LocalPart, prefix, URI] triple.
-
.exploded_namespace_declarations(ns) ⇒ Object
produce a Hash of namespace declaration attributes with exploded QNames, from a Hash of namespace prefix bindings.
-
.extract_explicit_namespace_bindings(element_name, attrs) ⇒ Object
extract a Hash of prefix=>uri mappings from exploded QName element and attrs.
-
.find_namespace_uri(ns_stack, prefix, uri_check = nil) ⇒ Object
returns the namespace uri for a prefix, if declared in the stack.
-
.merge_namespace_bindings(ns1, ns2) ⇒ Object
merges two sets of namespace bindings, raising error on clash.
-
.namespace_attributes(ns) ⇒ Object
produces a Hash of compact namespace attributes from a Hash of namespace bindings.
-
.non_ns_attrs_ns_bindings(ns_stack, element_name, attrs) ⇒ Object
given the existing
ns_stack
of ns bindings, aelement_name
and it’sattributes
, return a pair[non_ns_attrs, ns_bindings]
containing non-ns related attributes, and namespace bindings for the current element, both those declared in attributes and declared implicitly through exploded element names. -
.partition_namespace_decls(attrs) ⇒ Object
split attributes into non-namespace related attrs and prefix=>uri namespace bindings.
-
.split_qname(qname) ⇒ Object
split a qname String into a [local_part, prefix] pair.
-
.undeclared_namespace_bindings(ns_stack, ns_explicit) ⇒ Object
figure out which explicit namespaces need declaring.
Class Method Details
.compact_attr_qnames(ns_stack, attrs) ⇒ Object
compact all attribute QNames to Strings
6 7 8 9 10 |
# File 'lib/rsxml/namespace.rb', line 6 def compact_attr_qnames(ns_stack, attrs) Hash[attrs.map do |name,value| [compact_qname(ns_stack, name), value] end] end |
.compact_qname(ns_stack, name) ⇒ Object
produce a QName String from a [LocalPart, prefix, URI] triple
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/rsxml/namespace.rb', line 26 def compact_qname(ns_stack, name) return name if name.is_a?(String) local_part, prefix, uri = name raise "invalid name: #{name}" if !prefix && uri if prefix if prefix!="xmlns" ns = find_namespace_uri(ns_stack, prefix, uri) raise "namespace prefix not bound to a namespace: '#{prefix}'" if ! ns end [prefix, local_part].map{|s| s.to_s unless s.to_s.empty?}.compact.join(':') else local_part end end |
.explode_attr_qnames(ns_stack, attrs) ⇒ Object
explode attribute QNames to [LocalPart, prefix, URI] triples,
13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/rsxml/namespace.rb', line 13 def explode_attr_qnames(ns_stack, attrs) Hash[attrs.map do |name, value| uq_name = explode_qname(ns_stack, name, true) local_part, prefix, uri = uq_name if !prefix || prefix=="" [local_part, value] else [uq_name, value] end end] end |
.explode_qname(ns_stack, qname, attr = false) ⇒ Object
split a QName into [LocalPart, prefix, URI] triple. fill out missing uris if necessary, and check QName is well specified
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 |
# File 'lib/rsxml/namespace.rb', line 44 def explode_qname(ns_stack, qname, attr=false) if qname.is_a?(Array) local_part, prefix, uri = qname if uri raise "invalid name: #{qname.inspect}" if !prefix bound_uri = find_namespace_uri(ns_stack, prefix) raise "namespace conflict: prefix '#{prefix}' refers to '#{uri}' and '#{bound_uri}'" if bound_uri && uri != bound_uri return [local_part, prefix, uri] elsif prefix uri = find_namespace_uri(ns_stack, prefix) raise "namespace prefix not bound: '#{prefix}'" if !uri return [local_part, prefix, uri] else return local_part end end local_part, prefix = split_qname(qname) if prefix if prefix=="xmlns" && attr [local_part, prefix] else uri = find_namespace_uri(ns_stack, prefix) raise "namespace prefix not bound: '#{prefix}'" if ! uri [local_part, prefix, uri] end else if attr local_part else default_uri = find_namespace_uri(ns_stack, "") if default_uri [local_part, "", default_uri] else local_part end end end end |
.exploded_namespace_declarations(ns) ⇒ Object
produce a Hash of namespace declaration attributes with exploded QNames, from a Hash of namespace prefix bindings
149 150 151 152 153 154 155 156 157 |
# File 'lib/rsxml/namespace.rb', line 149 def exploded_namespace_declarations(ns) Hash[ns.map do |prefix, uri| if prefix=="" ["xmlns", uri] else [[prefix, "xmlns"], uri] end end] end |
.extract_explicit_namespace_bindings(element_name, attrs) ⇒ Object
extract a Hash of prefix=>uri mappings from exploded QName element and attrs
121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/rsxml/namespace.rb', line 121 def extract_explicit_namespace_bindings(element_name, attrs) element_name_local_part, element_name_prefix, element_name_uri = element_name ns = {} ns[element_name_prefix] = element_name_uri if element_name_prefix && element_name_uri attrs.each do |name, value| attr_local_part, attr_prefix, attr_uri = name if attr_prefix && attr_uri raise "bindings clash: '#{attr_prefix}'=>'#{ns[attr_prefix]}' , '#{attr_prefix}'=>'#{attr_uri}'" if ns.has_key?(attr_prefix) && ns[attr_prefix]!=attr_uri ns[attr_prefix] = attr_uri end end ns end |
.find_namespace_uri(ns_stack, prefix, uri_check = nil) ⇒ Object
returns the namespace uri for a prefix, if declared in the stack
96 97 98 99 100 101 |
# File 'lib/rsxml/namespace.rb', line 96 def find_namespace_uri(ns_stack, prefix, uri_check=nil) tns = ns_stack.reverse.find{|ns| ns.has_key?(prefix)} uri = tns[prefix] if tns raise "prefix: '#{prefix}' is bound to uri: '#{uri}', but should be '#{uri_check}'" if uri_check && uri && uri!=uri_check uri end |
.merge_namespace_bindings(ns1, ns2) ⇒ Object
merges two sets of namespace bindings, raising error on clash
172 173 174 175 176 177 178 179 |
# File 'lib/rsxml/namespace.rb', line 172 def merge_namespace_bindings(ns1, ns2) m = ns1.clone ns2.each do |k,v| raise "bindings clash: '#{k}'=>'#{m[k]}' , '#{k}'=>'#{v}'" if m.has_key?(k) && m[k]!=v m[k]=v end m end |
.namespace_attributes(ns) ⇒ Object
produces a Hash of compact namespace attributes from a Hash of namespace bindings
161 162 163 164 165 166 167 168 169 |
# File 'lib/rsxml/namespace.rb', line 161 def namespace_attributes(ns) Hash[ns.map do |prefix, uri| if prefix=="" ["xmlns", uri] else [["xmlns", prefix].join(":"), uri] end end] end |
.non_ns_attrs_ns_bindings(ns_stack, element_name, attrs) ⇒ Object
given the existing ns_stack
of ns bindings, a element_name
and it’s attributes
, return a pair [non_ns_attrs, ns_bindings]
containing non-ns related attributes, and namespace bindings for the current element, both those declared in attributes and declared implicitly through exploded element names
185 186 187 188 189 190 191 192 193 |
# File 'lib/rsxml/namespace.rb', line 185 def non_ns_attrs_ns_bindings(ns_stack, element_name, attrs) non_ns_attrs, ns_declared = partition_namespace_decls(attrs) ns_explicit = extract_explicit_namespace_bindings(element_name, attrs) ns_undeclared = undeclared_namespace_bindings(ns_stack + [ns_declared], ns_explicit) ns_bindings = merge_namespace_bindings(ns_declared, ns_undeclared) [non_ns_attrs, ns_bindings] end |
.partition_namespace_decls(attrs) ⇒ Object
split attributes into non-namespace related attrs and prefix=>uri namespace bindings
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/rsxml/namespace.rb', line 104 def partition_namespace_decls(attrs) nonns_attrs = [] ns_bindings = [] attrs.each do |name, value| local_part, prefix = split_qname(name) if prefix && prefix=="xmlns" ns_bindings << [local_part, value] elsif !prefix && local_part=="xmlns" ns_bindings << ["", value] else nonns_attrs << [name, value] end end [Hash[nonns_attrs], Hash[ns_bindings]] end |
.split_qname(qname) ⇒ Object
split a qname String into a [local_part, prefix] pair
85 86 87 88 89 90 91 92 93 |
# File 'lib/rsxml/namespace.rb', line 85 def split_qname(qname) return qname if qname.is_a?(Array) if qname =~ /^[^:]+:[^:]+$/ [*qname.split(':')].reverse else qname end end |
.undeclared_namespace_bindings(ns_stack, ns_explicit) ⇒ Object
figure out which explicit namespaces need declaring
ns_stack
is the stack of namespace bindings ns_explicit
is the explicit refs for a element
140 141 142 143 144 |
# File 'lib/rsxml/namespace.rb', line 140 def undeclared_namespace_bindings(ns_stack, ns_explicit) Hash[ns_explicit.map do |prefix,uri| [prefix, uri] if !find_namespace_uri(ns_stack, prefix, uri) end.compact] end |