summaryrefslogtreecommitdiff
path: root/ruby_1_8_6/lib/rexml/light/node.rb
blob: 943ec5f1a0d8a100c9ae431a486c7d7d616b47f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
require 'rexml/xmltokens'
require 'rexml/light/node'

# [ :element, parent, name, attributes, children* ]
	# a = Node.new
	# a << "B"		# => <a>B</a>
	# a.b			# => <a>B<b/></a>
	# a.b[1]			# => <a>B<b/><b/><a>
	# a.b[1]["x"] = "y"	# => <a>B<b/><b x="y"/></a>
	# a.b[0].c		# => <a>B<b><c/></b><b x="y"/></a>
	# a.b.c << "D"		# => <a>B<b><c>D</c></b><b x="y"/></a>
module REXML
	module Light
		# Represents a tagged XML element.  Elements are characterized by
		# having children, attributes, and names, and can themselves be
		# children.
		class Node
			NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u
			PARENTS = [ :element, :document, :doctype ]
			# Create a new element.
			def initialize node=nil
				@node = node
				if node.kind_of? String
					node = [ :text, node ]
				elsif node.nil?
					node = [ :document, nil, nil ]
				elsif node[0] == :start_element
					node[0] = :element
				elsif node[0] == :start_doctype
					node[0] = :doctype
				elsif node[0] == :start_document
					node[0] = :document
				end
			end

			def size
				if PARENTS.include? @node[0]
					@node[-1].size
				else
					0
				end
			end

			def each( &block )
				size.times { |x| yield( at(x+4) ) }
			end

			def name
				at(2)
			end

			def name=( name_str, ns=nil )
				pfx = ''
				pfx = "#{prefix(ns)}:" if ns
				_old_put(2, "#{pfx}#{name_str}")
			end

			def parent=( node )
				_old_put(1,node)
			end

			def local_name
				namesplit
				@name
			end

			def local_name=( name_str )
				_old_put( 1, "#@prefix:#{name_str}" )
			end

			def prefix( namespace=nil )
				prefix_of( self, namespace )
			end

			def namespace( prefix=prefix() )
				namespace_of( self, prefix )
			end

			def namespace=( namespace )
				@prefix = prefix( namespace )
				pfx = ''
				pfx = "#@prefix:" if @prefix.size > 0
				_old_put(1, "#{pfx}#@name")
			end

			def []( reference, ns=nil )
				if reference.kind_of? String
					pfx = ''
					pfx = "#{prefix(ns)}:" if ns
					at(3)["#{pfx}#{reference}"]
				elsif reference.kind_of? Range
					_old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) )
				else
					_old_get( 4+reference )
				end
			end

			def =~( path )
				XPath.match( self, path )
			end

			# Doesn't handle namespaces yet
			def []=( reference, ns, value=nil )
				if reference.kind_of? String
					value = ns unless value
					at( 3 )[reference] = value
				elsif reference.kind_of? Range
					_old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns )
				else
					if value
						_old_put( 4+reference, ns, value )
					else
						_old_put( 4+reference, ns )
					end
				end
			end

			# Append a child to this element, optionally under a provided namespace.
			# The namespace argument is ignored if the element argument is an Element
			# object.  Otherwise, the element argument is a string, the namespace (if
			# provided) is the namespace the element is created in.
			def << element
				if node_type() == :text
					at(-1) << element
				else
					newnode = Node.new( element )
					newnode.parent = self
					self.push( newnode )
				end
				at(-1)
			end

			def node_type
				_old_get(0)
			end

			def text=( foo )
				replace = at(4).kind_of?(String)? 1 : 0
				self._old_put(4,replace, normalizefoo)
			end

			def root
				context = self
				context = context.at(1) while context.at(1)
			end

			def has_name?( name, namespace = '' )
				at(3) == name and namespace() == namespace
			end

			def children
				self
			end

			def parent
				at(1)
			end

			def to_s

			end

			private

			def namesplit
				return if @name.defined?
				at(2) =~ NAMESPLIT
				@prefix = '' || $1
				@name = $2
			end

			def namespace_of( node, prefix=nil )
				if not prefix
					name = at(2)
					name =~ NAMESPLIT
					prefix = $1
				end
				to_find = 'xmlns'
				to_find = "xmlns:#{prefix}" if not prefix.nil?
				ns = at(3)[ to_find ]
				ns ? ns : namespace_of( @node[0], prefix )
			end

			def prefix_of( node, namespace=nil )
				if not namespace
					name = node.name
					name =~ NAMESPLIT
					$1
				else
					ns = at(3).find { |k,v| v == namespace }
					ns ? ns : prefix_of( node.parent, namespace )
				end
			end
		end
	end
end