struct Lexbor::Node
delegate :[], to: attributes
delegate :[]?, to: attributes
delegate :fetch, to: attributes
delegate :has_key?, to: attributes
def attribute_add(key : String, value : String, encoding = nil)
if Lib.element_set_attribute(@element, key.to_unsafe, key.bytesize, value.to_unsafe, value.bytesize).null?
raise LibError.new("unable to add attribute to #{self.inspect}")
end
if attrs = @attributes
attrs[key] = value
end
value
end
def attribute_remove(key : String)
Lib.attribute_remove(@element, key, key.bytesize)
if attrs = @attributes
attrs.delete(key)
end
key
end
def []=(key : String, value : String?)
if value
attribute_add(key, value)
else
attribute_remove(key)
end
end
def attribute_by(key : String) : String?
if attrs = @attributes
attrs[key]?
else
slice = key.to_slice
each_raw_attribute do |attr|
if attribute_name(attr) == slice
v = attribute_value(attr)
return v ? String.new(v) : ""
end
end
nil
end
end
def attributes
@attributes ||= begin
res = {} of String => String
each_attribute do |k, v|
res[String.new(k)] = v ? String.new(v) : ""
end
res
end
end
def each_attribute(&block)
each_raw_attribute do |attr|
yield attribute_name(attr), attribute_value(attr)
end
end
protected def each_raw_attribute(&block)
case tag_id
when Lib::TagIdT::LXB_TAG__EM_DOCTYPE, Lib::TagIdT::LXB_TAG__TEXT, Lib::TagIdT::LXB_TAG__EM_COMMENT
return nil
end
attr = Lib.element_first_attribute(@element)
while !attr.null?
yield attr
attr = Lib.element_next_attribute(attr)
end
nil
end
@[AlwaysInline]
private def any_attribute?
!Lib.element_first_attribute(@element).null?
end
@[AlwaysInline]
private def attribute_name(attr)
name = Lib.attribute_local_name(attr, out name_length)
Slice(UInt8).new(name, name_length)
end
@[AlwaysInline]
private def attribute_value(attr)
value = Lib.attribute_value(attr, out value_length)
value.null? ? nil : Slice(UInt8).new(value, value_length)
end
def attribute_by(slice : Slice(UInt8))
each_raw_attribute do |attr|
if attribute_name(attr) == slice
return attribute_value(attr)
end
end
end
end