PageRenderTime 190ms CodeModel.GetById 143ms app.highlight 31ms RepoModel.GetById 13ms app.codeStats 1ms

/tools/Ruby/lib/ruby/1.8/rexml/attribute.rb

http://github.com/agross/netopenspace
Ruby | 185 lines | 101 code | 19 blank | 65 comment | 14 complexity | 083c8b3fb7543dde5d558f71d1d542c6 MD5 | raw file
  1require "rexml/namespace"
  2require 'rexml/text'
  3
  4module REXML
  5	# Defines an Element Attribute; IE, a attribute=value pair, as in:
  6	# <element attribute="value"/>.  Attributes can be in their own
  7	# namespaces.  General users of REXML will not interact with the
  8	# Attribute class much.
  9	class Attribute
 10		include Node
 11		include Namespace
 12
 13		# The element to which this attribute belongs
 14		attr_reader :element
 15		# The normalized value of this attribute.  That is, the attribute with
 16		# entities intact.
 17		attr_writer :normalized	
 18		PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
 19
 20		# Constructor.
 21    # FIXME: The parser doesn't catch illegal characters in attributes
 22    #
 23    # first:: 
 24    #   Either: an Attribute, which this new attribute will become a
 25    #   clone of; or a String, which is the name of this attribute
 26    # second::
 27    #   If +first+ is an Attribute, then this may be an Element, or nil.
 28    #   If nil, then the Element parent of this attribute is the parent
 29    #   of the +first+ Attribute.  If the first argument is a String, 
 30    #   then this must also be a String, and is the content of the attribute.  
 31    #   If this is the content, it must be fully normalized (contain no
 32    #   illegal characters).
 33    # parent::
 34    #   Ignored unless +first+ is a String; otherwise, may be the Element 
 35    #   parent of this attribute, or nil.
 36    #
 37		#
 38		#  Attribute.new( attribute_to_clone )
 39		#  Attribute.new( attribute_to_clone, parent_element )
 40		#  Attribute.new( "attr", "attr_value" )
 41		#  Attribute.new( "attr", "attr_value", parent_element )
 42		def initialize( first, second=nil, parent=nil )
 43			@normalized = @unnormalized = @element = nil
 44			if first.kind_of? Attribute
 45				self.name = first.expanded_name
 46				@unnormalized = first.value
 47				if second.kind_of? Element
 48					@element = second
 49				else
 50					@element = first.element
 51				end
 52			elsif first.kind_of? String
 53				@element = parent
 54				self.name = first
 55				@normalized = second.to_s
 56			else
 57				raise "illegal argument #{first.class.name} to Attribute constructor"
 58			end
 59		end
 60
 61		# Returns the namespace of the attribute.
 62		# 
 63		#  e = Element.new( "elns:myelement" )
 64		#  e.add_attribute( "nsa:a", "aval" )
 65		#  e.add_attribute( "b", "bval" )
 66		#  e.attributes.get_attribute( "a" ).prefix   # -> "nsa"
 67		#  e.attributes.get_attribute( "b" ).prefix   # -> "elns"
 68		#  a = Attribute.new( "x", "y" )
 69		#  a.prefix                                   # -> ""
 70		def prefix
 71			pf = super
 72			if pf == ""
 73				pf = @element.prefix if @element
 74			end
 75			pf
 76		end
 77
 78		# Returns the namespace URL, if defined, or nil otherwise
 79		# 
 80		#  e = Element.new("el")
 81		#  e.add_attributes({"xmlns:ns", "http://url"})
 82		#  e.namespace( "ns" )              # -> "http://url"
 83		def namespace arg=nil
 84			arg = prefix if arg.nil?
 85			@element.namespace arg
 86		end
 87
 88		# Returns true if other is an Attribute and has the same name and value,
 89		# false otherwise.
 90		def ==( other )
 91			other.kind_of?(Attribute) and other.name==name and other.value==value
 92		end
 93
 94		# Creates (and returns) a hash from both the name and value
 95		def hash
 96			name.hash + value.hash
 97		end
 98
 99		# Returns this attribute out as XML source, expanding the name
100		#
101		#  a = Attribute.new( "x", "y" )
102		#  a.to_string     # -> "x='y'"
103		#  b = Attribute.new( "ns:x", "y" )
104		#  b.to_string     # -> "ns:x='y'"
105		def to_string
106			if @element and @element.context and @element.context[:attribute_quote] == :quote
107				%Q^#@expanded_name="#{to_s().gsub(/"/, '&quote;')}"^
108			else
109				"#@expanded_name='#{to_s().gsub(/'/, '&apos;')}'"
110			end
111		end
112
113		# Returns the attribute value, with entities replaced
114		def to_s
115			return @normalized if @normalized
116
117			doctype = nil
118			if @element
119				doc = @element.document
120				doctype = doc.doctype if doc
121			end
122
123			@normalized = Text::normalize( @unnormalized, doctype )
124			@unnormalized = nil
125      @normalized
126		end
127
128		# Returns the UNNORMALIZED value of this attribute.  That is, entities
129		# have been expanded to their values
130		def value
131			return @unnormalized if @unnormalized
132			doctype = nil
133			if @element
134				doc = @element.document
135				doctype = doc.doctype if doc
136			end
137			@unnormalized = Text::unnormalize( @normalized, doctype )
138			@normalized = nil
139      @unnormalized
140		end
141
142		# Returns a copy of this attribute
143		def clone
144			Attribute.new self
145		end
146
147		# Sets the element of which this object is an attribute.  Normally, this
148		# is not directly called.
149		#
150		# Returns this attribute
151		def element=( element )
152			@element = element
153			self
154		end
155
156		# Removes this Attribute from the tree, and returns true if successfull
157		# 
158		# This method is usually not called directly.
159		def remove
160			@element.attributes.delete self.name unless @element.nil?
161		end
162
163		# Writes this attribute (EG, puts 'key="value"' to the output)
164		def write( output, indent=-1 )
165			output << to_string
166		end
167
168    def node_type
169      :attribute
170    end
171
172    def inspect
173      rv = ""
174      write( rv )
175      rv
176    end
177
178    def xpath
179      path = @element.xpath
180      path += "/@#{self.expanded_name}"
181      return path
182    end
183	end
184end
185#vim:ts=2 sw=2 noexpandtab: