/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

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