internalize rexml
[booh] / lib / booh / rexml / attribute.rb.orig
1 require "rexml/namespace"
2 require 'rexml/text'
3
4 module 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                 #
22                 #  Attribute.new( attribute_to_clone )
23                 #  Attribute.new( source )
24                 #  Attribute.new( "attr", "attr_value" )
25                 #  Attribute.new( "attr", "attr_value", parent_element )
26                 def initialize( first, second=nil, parent=nil )
27                         @normalized = @unnormalized = @element = nil
28                         if first.kind_of? Attribute
29                                 self.name = first.expanded_name
30                                 @value = first.value
31                                 if second.kind_of? Element
32                                         @element = second
33                                 else
34                                         @element = first.element
35                                 end
36                         elsif first.kind_of? String
37                                 @element = parent if parent.kind_of? Element
38                                 self.name = first
39                                 @value = second.to_s
40                         else
41                                 raise "illegal argument #{first.class.name} to Attribute constructor"
42                         end
43                 end
44
45                 # Returns the namespace of the attribute.
46                 # 
47                 #  e = Element.new( "elns:myelement" )
48                 #  e.add_attribute( "nsa:a", "aval" )
49                 #  e.add_attribute( "b", "bval" )
50                 #  e.attributes.get_attribute( "a" ).prefix   # -> "nsa"
51                 #  e.attributes.get_attribute( "b" ).prefix   # -> "elns"
52                 #  a = Attribute.new( "x", "y" )
53                 #  a.prefix                                   # -> ""
54                 def prefix
55                         pf = super
56                         if pf == ""
57                                 pf = @element.prefix if @element
58                         end
59                         pf
60                 end
61
62                 # Returns the namespace URL, if defined, or nil otherwise
63                 # 
64                 #  e = Element.new("el")
65                 #  e.add_attributes({"xmlns:ns", "http://url"})
66                 #  e.namespace( "ns" )              # -> "http://url"
67                 def namespace arg=nil
68                         arg = prefix if arg.nil?
69                         @element.namespace arg
70                 end
71
72                 # Returns true if other is an Attribute and has the same name and value,
73                 # false otherwise.
74                 def ==( other )
75                         other.kind_of?(Attribute) and other.name==name and other.value==@value
76                 end
77
78                 # Creates (and returns) a hash from both the name and value
79                 def hash
80                         name.hash + value.hash
81                 end
82
83                 # Returns this attribute out as XML source, expanding the name
84                 #
85                 #  a = Attribute.new( "x", "y" )
86                 #  a.to_string     # -> "x='y'"
87                 #  b = Attribute.new( "ns:x", "y" )
88                 #  b.to_string     # -> "ns:x='y'"
89                 def to_string
90                         "#@expanded_name='#{to_s().gsub(/'/, '&apos;')}'"
91                 end
92
93                 # Returns the attribute value, with entities replaced
94                 def to_s
95                         return @normalized if @normalized
96
97                         doctype = nil
98                         if @element
99                                 doc = @element.document
100                                 doctype = doc.doctype if doc
101                         end
102
103                         @unnormalized = nil
104                         @normalized = Text::normalize( @value, doctype )
105                 end
106
107                 # Returns the UNNORMALIZED value of this attribute.  That is, entities
108                 # have been expanded to their values
109                 def value
110                         return @unnormalized if @unnormalized
111                         doctype = nil
112                         if @element
113                                 doc = @element.document
114                                 doctype = doc.doctype if doc
115                         end
116                         @normalized = nil
117                         @unnormalized = Text::unnormalize( @value, doctype )
118                 end
119
120                 # Returns a copy of this attribute
121                 def clone
122                         Attribute.new self
123                 end
124
125                 # Sets the element of which this object is an attribute.  Normally, this
126                 # is not directly called.
127                 #
128                 # Returns this attribute
129                 def element=( element )
130                         @element = element
131                         self
132                 end
133
134                 # Removes this Attribute from the tree, and returns true if successfull
135                 # 
136                 # This method is usually not called directly.
137                 def remove
138                         @element.attributes.delete self.name unless @element.nil?
139                 end
140
141                 # Writes this attribute (EG, puts 'key="value"' to the output)
142                 def write( output, indent=-1 )
143                         output << to_string
144                 end
145
146     def node_type
147       :attribute
148     end
149
150     def inspect
151       rv = ""
152       write( rv )
153       rv
154     end
155
156     def xpath
157       path = @element.xpath
158       path += "/@#{self.expanded_name}"
159       return path
160     end
161         end
162 end
163 #vim:ts=2 sw=2 noexpandtab: