Class: Moxml::C14n::DataModel
- Inherits:
-
Object
- Object
- Moxml::C14n::DataModel
- Defined in:
- lib/moxml/c14n/data_model.rb
Overview
Builds a C14N data model from a Moxml::Node tree (or XML string).
The data model exists because canonicalization needs:
- sorted namespace and attribute axes (spec §2.3, §2.4)
- in_node_set flags for subset canonicalization (spec §3)
- xml:* inheritable attribute resolution
Ported from canon (lutaml/canon) — adapted to build directly from Moxml::Node rather than via a separate Nokogiri pass. Matches canon's document-level node iteration (PIs and comments outside the document root element).
Constant Summary collapse
- BUILDABLE_TYPES =
[::Moxml::Element, ::Moxml::Text, ::Moxml::Cdata, ::Moxml::Comment, ::Moxml::ProcessingInstruction].freeze
Class Attribute Summary collapse
-
.source_map ⇒ Object
readonly
Returns the value of attribute source_map.
Class Method Summary collapse
- .buildable?(node) ⇒ Boolean
- .from_node(moxml_node) ⇒ Object
- .from_xml(xml_string) ⇒ Object
-
.mark_subset_paths(root_node, paths) ⇒ Object
Mark an XPath-selected subset: reset the whole model, then flag each matched node by position path.
- .node_path(node, source) ⇒ Object
-
.path_key_for(wrapper, source, adapter) ⇒ Object
Path key of a matched wrapper relative to the source the data model was built from; nil when the wrapper is outside it.
Class Attribute Details
.source_map ⇒ Object (readonly)
Returns the value of attribute source_map.
38 39 40 |
# File 'lib/moxml/c14n/data_model.rb', line 38 def source_map @source_map end |
Class Method Details
.buildable?(node) ⇒ Boolean
45 46 47 |
# File 'lib/moxml/c14n/data_model.rb', line 45 def self.buildable?(node) BUILDABLE_TYPES.any? { |type| node.is_a?(type) } end |
.from_node(moxml_node) ⇒ Object
21 22 23 24 25 26 27 28 29 |
# File 'lib/moxml/c14n/data_model.rb', line 21 def self.from_node(moxml_node) @source_map = {} return build_from_document(moxml_node) if moxml_node.is_a?(::Moxml::Document) root = Nodes::RootNode.new built = build_node(moxml_node, [0]) root.add_child(built) if built root end |
.from_xml(xml_string) ⇒ Object
17 18 19 |
# File 'lib/moxml/c14n/data_model.rb', line 17 def self.from_xml(xml_string) from_node(::Moxml.parse(xml_string)) end |
.mark_subset_paths(root_node, paths) ⇒ Object
Mark an XPath-selected subset: reset the whole model, then flag each matched node by position path. Node-set semantics follow the enveloped-signature interop (libxml2/xmlsec): an included element renders with its namespaces, attributes and DIRECT character data, but child ELEMENTS render only if matched too — an unmatched Signature subtree stays out even though its ancestors are matched.
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/moxml/c14n/data_model.rb', line 241 def self.mark_subset_paths(root_node, paths) mark_all(root_node, false) paths.each do |path| node = lookup_path(root_node, path) next unless node if node.is_a?(Nodes::ElementNode) node.in_node_set = true node.namespace_nodes.each { |ns| ns.in_node_set = true } node.attribute_nodes.each { |attr| attr.in_node_set = true } node.children.each do |child| child.in_node_set = true unless child.is_a?(Nodes::ElementNode) end else node.in_node_set = true end end end |
.node_path(node, source) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/moxml/c14n/data_model.rb', line 79 def self.node_path(node, source) parts = [] cur = node loop do if !source.is_a?(::Moxml::Document) && cur.equal?(source) parts.unshift(0) return parts end parent = cur.parent return nil unless parent idx = parent.children.select { |c| buildable?(c) }.index { |c| c == cur } return nil unless idx parts.unshift(idx) return parts if source.is_a?(::Moxml::Document) && parent.is_a?(::Moxml::Document) cur = parent end end |
.path_key_for(wrapper, source, adapter) ⇒ Object
Path key of a matched wrapper relative to the source the data model was built from; nil when the wrapper is outside it. Attributes extend their owner's path with [:attribute, index]. The adapter comes from the caller: the Attribute contract keeps its own adapter hop protected.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/moxml/c14n/data_model.rb', line 54 def self.path_key_for(wrapper, source, adapter) case wrapper when ::Moxml::Attribute owner = wrapper.parent unless owner.is_a?(::Moxml::Element) # XPath results are re-wrapped from natives: attribute # wrappers carry no minted parent. The adapter answers # the owner element instead. owner_native = adapter.attribute_element(wrapper.native) owner = owner_native && ::Moxml::Node.wrap(owner_native, wrapper.context) end return nil unless owner.is_a?(::Moxml::Element) owner_path = node_path(owner, source) return nil unless owner_path idx = owner.attributes.index { |a| a == wrapper } return nil unless idx owner_path + [:attribute, idx] when *BUILDABLE_TYPES node_path(wrapper, source) end end |