lib/moxml/element.rb in moxml-0.1.0 vs lib/moxml/element.rb in moxml-0.1.1

- old
+ new

@@ -1,145 +1,107 @@ +# frozen_string_literal: true + +require_relative "attribute" +require_relative "namespace" + module Moxml class Element < Node - def initialize(name_or_native = nil) - case name_or_native - when String - super(adapter.create_element(nil, name_or_native)) - else - super(name_or_native) - end - end - def name - adapter.node_name(native) + adapter.node_name(@native) end - def attributes - adapter.attributes(native).transform_values { |attr| Attribute.new(attr) } + def name=(value) + adapter.set_node_name(@native, value) end def []=(name, value) - adapter.set_attribute(native, name, value) + adapter.set_attribute(@native, name, normalize_xml_value(value)) end def [](name) - attr = adapter.get_attribute(native, name) - attr.nil? ? nil : Attribute.new(attr) + adapter.get_attribute_value(@native, name) end - def add_child(node) - adapter.add_child(native, node.native) - self + def attribute(name) + native_attr = adapter.get_attribute(@native, name) + native_attr && Attribute.new(native_attr, context) end - def namespace - ns = adapter.namespace(native) - ns.nil? ? nil : Namespace.new(ns) + def attributes + adapter.attributes(@native).map do |attr| + Attribute.new(attr, context) + end end - def namespace=(ns) - adapter.set_namespace(native, ns&.native) + def remove_attribute(name) + adapter.remove_attribute(@native, name) self end - def namespaces - adapter.namespaces(native).transform_values { |ns| Namespace.new(ns) } + def add_namespace(prefix, uri) + validate_uri(uri) + adapter.create_native_namespace(@native, prefix, uri) + self + rescue ValidationError => e + raise Moxml::NamespaceError, e.message end + alias add_namespace_definition add_namespace - def css(selector) - NodeSet.new(adapter.css(native, selector)) + # it's NOT the same as namespaces.first + def namespace + ns = adapter.namespace(@native) + ns && Namespace.new(ns, context) end - def xpath(expression, namespaces = {}) - NodeSet.new(adapter.xpath(native, expression, namespaces)) + # it does NOT change the list of namespace definitions + def namespace=(ns_or_hash) + if ns_or_hash.is_a?(Hash) + adapter.set_namespace( + @native, + adapter.create_namespace(@native, *ns_or_hash.to_a.first) + ) + else + adapter.set_namespace(@native, ns_or_hash&.native) + end end - def at_css(selector) - node = adapter.at_css(native, selector) - node.nil? ? nil : wrap_node(node) + def namespaces + adapter.namespace_definitions(@native).map do |ns| + Namespace.new(ns, context) + end end + alias namespace_definitions namespaces - def at_xpath(expression, namespaces = {}) - node = adapter.at_xpath(native, expression, namespaces) - node.nil? ? nil : wrap_node(node) + def text + adapter.text_content(@native) end - def blank? - text.strip.empty? && children.empty? + def text=(content) + adapter.set_text_content(@native, normalize_xml_value(content)) end - def value - text.strip + def inner_html + adapter.inner_html(@native) end - def value=(val) - self.text = val.to_s + def inner_html=(html) + doc = context.parse("<root>#{html}</root>") + adapter.replace_children(@native, doc.root.children.map(&:native)) end - def matches?(selector) - adapter.matches?(native, selector) - end - - def ancestors - NodeSet.new(adapter.ancestors(native)) - end - - def descendants - NodeSet.new(adapter.descendants(native)) - end - - def previous_elements - NodeSet.new(adapter.previous_elements(native)) - end - - def next_elements - NodeSet.new(adapter.next_elements(native)) - end - - def inner_text - adapter.inner_text(native) - end - - def inner_text=(text) - adapter.set_inner_text(native, text) + # Fluent interface methods + def with_attribute(name, value) + self[name] = value self end - def key?(name) - adapter.has_attribute?(native, name) - end - - alias has_attribute? key? - - def classes - (self["class"] || "").split(/\s+/) - end - - def add_class(*names) - self["class"] = (classes + names).uniq.join(" ") + def with_namespace(prefix, uri) + add_namespace(prefix, uri) self end - def remove_class(*names) - self["class"] = (classes - names).join(" ") + def with_text(content) + self.text = content self - end - - def toggle_class(name) - if classes.include?(name) - remove_class(name) - else - add_class(name) - end - end - - def has_class?(name) - classes.include?(name) - end - - private - - def create_native_node - adapter.create_element(nil, "") end end end