Class: REXML::Attribute

Inherits:
Object
  • Object
show all
Includes:
Namespace, Node
Defined in:
lib/rexml/attribute.rb

Overview

Defines an Element Attribute; IE, a attribute=value pair, as in: <element attribute=“value”/>. Attributes can be in their own namespaces. General users of REXML will not interact with the Attribute class much.

Constant Summary collapse

PATTERN =
/\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
NEEDS_A_SECOND_CHECK =
/(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um

Constants included from Namespace

Namespace::NAMESPLIT, Namespace::NAME_WITHOUT_NAMESPACE

Constants included from XMLTokens

XMLTokens::NAME, XMLTokens::NAMECHAR, XMLTokens::NAME_CHAR, XMLTokens::NAME_START_CHAR, XMLTokens::NAME_STR, XMLTokens::NCNAME_STR, XMLTokens::NMTOKEN, XMLTokens::NMTOKENS, XMLTokens::REFERENCE

Instance Attribute Summary collapse

Attributes included from Namespace

#expanded_name, #name

Instance Method Summary collapse

Methods included from Namespace

#fully_expanded_name, #has_name?

Methods included from Node

#each_recursive, #find_first_recursive, #indent, #index_in_parent, #next_sibling_node, #parent?, #previous_sibling_node

Constructor Details

#initialize(first, second = nil, parent = nil) ⇒ Attribute

Constructor. FIXME: The parser doesn’t catch illegal characters in attributes

first

Either: an Attribute, which this new attribute will become a clone of; or a String, which is the name of this attribute

second

If first is an Attribute, then this may be an Element, or nil. If nil, then the Element parent of this attribute is the parent of the first Attribute. If the first argument is a String, then this must also be a String, and is the content of the attribute. If this is the content, it must be fully normalized (contain no illegal characters).

parent

Ignored unless first is a String; otherwise, may be the Element parent of this attribute, or nil.

Attribute.new( attribute_to_clone )
Attribute.new( attribute_to_clone, parent_element )
Attribute.new( "attr", "attr_value" )
Attribute.new( "attr", "attr_value", parent_element )


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rexml/attribute.rb', line 42

def initialize( first, second=nil, parent=nil )
  @normalized = @unnormalized = @element = nil
  if first.kind_of? Attribute
    self.name = first.expanded_name
    @unnormalized = first.value
    if second.kind_of? Element
      @element = second
    else
      @element = first.element
    end
  elsif first.kind_of? String
    @element = parent
    self.name = first
    @normalized = second.to_s
  else
    raise "illegal argument #{first.class.name} to Attribute constructor"
  end
end

Instance Attribute Details

#elementObject

The element to which this attribute belongs



15
16
17
# File 'lib/rexml/attribute.rb', line 15

def element
  @element
end

Instance Method Details

#==(other) ⇒ Object

Returns true if other is an Attribute and has the same name and value, false otherwise.



106
107
108
# File 'lib/rexml/attribute.rb', line 106

def ==( other )
  other.kind_of?(Attribute) and other.name==name and other.value==value
end

#cloneObject

Returns a copy of this attribute



161
162
163
# File 'lib/rexml/attribute.rb', line 161

def clone
  Attribute.new self
end

#doctypeObject



132
133
134
# File 'lib/rexml/attribute.rb', line 132

def doctype
  @element&.document&.doctype
end

#documentObject



205
206
207
# File 'lib/rexml/attribute.rb', line 205

def document
  @element&.document
end

#hashObject

Creates (and returns) a hash from both the name and value



111
112
113
# File 'lib/rexml/attribute.rb', line 111

def hash
  name.hash + value.hash
end

#inspectObject



195
196
197
198
199
# File 'lib/rexml/attribute.rb', line 195

def inspect
  rv = +""
  write( rv )
  rv
end

#namespace(arg = nil) ⇒ Object

Returns the namespace URL, if defined, or nil otherwise

e = Element.new("el")
e.add_namespace("ns", "http://url")
e.add_attribute("ns:a", "b")
e.add_attribute("nsx:a", "c")
e.attribute("ns:a").namespace # => "http://url"
e.attribute("nsx:a").namespace # => nil

This method always returns “” for no namespace attribute. Because the default namespace doesn’t apply to attribute names.

From www.w3.org/TR/xml-names/#uniqAttrs

> the default namespace does not apply to attribute names

e = REXML::Element.new("el")
e.add_namespace("", "http://example.com/")
e.namespace # => "http://example.com/"
e.add_attribute("a", "b")
e.attribute("a").namespace # => ""


95
96
97
98
99
100
101
102
# File 'lib/rexml/attribute.rb', line 95

def namespace arg=nil
  arg = prefix if arg.nil?
  if arg == ""
    ""
  else
    @element.namespace(arg)
  end
end

#node_typeObject



191
192
193
# File 'lib/rexml/attribute.rb', line 191

def node_type
  :attribute
end

#normalized=(new_normalized) ⇒ Object

The normalized value of this attribute. That is, the attribute with entities intact.



155
156
157
158
# File 'lib/rexml/attribute.rb', line 155

def normalized=(new_normalized)
  @normalized = new_normalized
  @unnormalized = nil
end

#prefixObject

Returns the namespace of the attribute.

e = Element.new( "elns:myelement" )
e.add_attribute( "nsa:a", "aval" )
e.add_attribute( "b", "bval" )
e.attributes.get_attribute( "a" ).prefix   # -> "nsa"
e.attributes.get_attribute( "b" ).prefix   # -> ""
a = Attribute.new( "x", "y" )
a.prefix                                   # -> ""


70
71
72
# File 'lib/rexml/attribute.rb', line 70

def prefix
  super
end

#removeObject

Removes this Attribute from the tree, and returns true if successful

This method is usually not called directly.



182
183
184
# File 'lib/rexml/attribute.rb', line 182

def remove
  @element.attributes.delete self.name unless @element.nil?
end

#to_sObject

Returns the attribute value, with entities replaced



137
138
139
140
141
142
# File 'lib/rexml/attribute.rb', line 137

def to_s
  return @normalized if @normalized

  @normalized = Text::normalize( @unnormalized, doctype )
  @normalized
end

#to_stringObject

Returns this attribute out as XML source, expanding the name

a = Attribute.new( "x", "y" )
a.to_string     # -> "x='y'"
b = Attribute.new( "ns:x", "y" )
b.to_string     # -> "ns:x='y'"


121
122
123
124
125
126
127
128
129
130
# File 'lib/rexml/attribute.rb', line 121

def to_string
  value = to_s
  if @element and @element.context and @element.context[:attribute_quote] == :quote
    value = value.gsub('"', '&quot;') if value.include?('"')
    %Q^#@expanded_name="#{value}"^
  else
    value = value.gsub("'", '&apos;') if value.include?("'")
    "#@expanded_name='#{value}'"
  end
end

#valueObject

Returns the UNNORMALIZED value of this attribute. That is, entities have been expanded to their values



146
147
148
149
150
151
# File 'lib/rexml/attribute.rb', line 146

def value
  return @unnormalized if @unnormalized

  @unnormalized = Text::unnormalize(@normalized, doctype,
                                    entity_expansion_text_limit: @element&.document&.entity_expansion_text_limit)
end

#write(output, indent = -1 )) ⇒ Object

Writes this attribute (EG, puts ‘key=“value”’ to the output)



187
188
189
# File 'lib/rexml/attribute.rb', line 187

def write( output, indent=-1 )
  output << to_string
end

#xpathObject



201
202
203
# File 'lib/rexml/attribute.rb', line 201

def xpath
  @element.xpath + "/@#{self.expanded_name}"
end