rexml 3.2.3 → 3.3.8
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rexml might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/NEWS.md +502 -0
- data/README.md +11 -14
- data/doc/rexml/context.rdoc +143 -0
- data/doc/rexml/tasks/rdoc/child.rdoc +87 -0
- data/doc/rexml/tasks/rdoc/document.rdoc +276 -0
- data/doc/rexml/tasks/rdoc/element.rdoc +602 -0
- data/doc/rexml/tasks/rdoc/node.rdoc +97 -0
- data/doc/rexml/tasks/rdoc/parent.rdoc +267 -0
- data/doc/rexml/tasks/tocs/child_toc.rdoc +12 -0
- data/doc/rexml/tasks/tocs/document_toc.rdoc +30 -0
- data/doc/rexml/tasks/tocs/element_toc.rdoc +55 -0
- data/doc/rexml/tasks/tocs/master_toc.rdoc +135 -0
- data/doc/rexml/tasks/tocs/node_toc.rdoc +16 -0
- data/doc/rexml/tasks/tocs/parent_toc.rdoc +25 -0
- data/doc/rexml/tutorial.rdoc +1358 -0
- data/lib/rexml/attribute.rb +17 -11
- data/lib/rexml/doctype.rb +55 -31
- data/lib/rexml/document.rb +199 -35
- data/lib/rexml/element.rb +1802 -487
- data/lib/rexml/entity.rb +10 -39
- data/lib/rexml/formatters/pretty.rb +3 -3
- data/lib/rexml/functions.rb +1 -2
- data/lib/rexml/light/node.rb +0 -8
- data/lib/rexml/namespace.rb +8 -4
- data/lib/rexml/node.rb +8 -4
- data/lib/rexml/parseexception.rb +1 -0
- data/lib/rexml/parsers/baseparser.rb +513 -250
- data/lib/rexml/parsers/pullparser.rb +12 -0
- data/lib/rexml/parsers/sax2parser.rb +16 -19
- data/lib/rexml/parsers/streamparser.rb +16 -10
- data/lib/rexml/parsers/treeparser.rb +9 -21
- data/lib/rexml/parsers/xpathparser.rb +161 -97
- data/lib/rexml/rexml.rb +29 -22
- data/lib/rexml/source.rb +128 -98
- data/lib/rexml/text.rb +46 -22
- data/lib/rexml/xpath_parser.rb +43 -33
- data/lib/rexml.rb +3 -0
- metadata +42 -46
- data/.gitignore +0 -9
- data/.travis.yml +0 -24
- data/Gemfile +0 -6
- data/Rakefile +0 -8
- data/rexml.gemspec +0 -84
data/lib/rexml/element.rb
CHANGED
@@ -7,17 +7,267 @@ require_relative "xpath"
|
|
7
7
|
require_relative "parseexception"
|
8
8
|
|
9
9
|
module REXML
|
10
|
-
# An
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
10
|
+
# An \REXML::Element object represents an XML element.
|
11
|
+
#
|
12
|
+
# An element:
|
13
|
+
#
|
14
|
+
# - Has a name (string).
|
15
|
+
# - May have a parent (another element).
|
16
|
+
# - Has zero or more children
|
17
|
+
# (other elements, text, CDATA, processing instructions, and comments).
|
18
|
+
# - Has zero or more siblings
|
19
|
+
# (other elements, text, CDATA, processing instructions, and comments).
|
20
|
+
# - Has zero or more named attributes.
|
21
|
+
#
|
22
|
+
# == In a Hurry?
|
23
|
+
#
|
24
|
+
# If you're somewhat familiar with XML
|
25
|
+
# and have a particular task in mind,
|
26
|
+
# you may want to see the
|
27
|
+
# {tasks pages}[../doc/rexml/tasks/tocs/master_toc_rdoc.html],
|
28
|
+
# and in particular, the
|
29
|
+
# {tasks page for elements}[../doc/rexml/tasks/tocs/element_toc_rdoc.html].
|
30
|
+
#
|
31
|
+
# === Name
|
32
|
+
#
|
33
|
+
# An element has a name, which is initially set when the element is created:
|
34
|
+
#
|
35
|
+
# e = REXML::Element.new('foo')
|
36
|
+
# e.name # => "foo"
|
37
|
+
#
|
38
|
+
# The name may be changed:
|
39
|
+
#
|
40
|
+
# e.name = 'bar'
|
41
|
+
# e.name # => "bar"
|
42
|
+
#
|
43
|
+
#
|
44
|
+
# === \Parent
|
45
|
+
#
|
46
|
+
# An element may have a parent.
|
47
|
+
#
|
48
|
+
# Its parent may be assigned explicitly when the element is created:
|
49
|
+
#
|
50
|
+
# e0 = REXML::Element.new('foo')
|
51
|
+
# e1 = REXML::Element.new('bar', e0)
|
52
|
+
# e1.parent # => <foo> ... </>
|
53
|
+
#
|
54
|
+
# Note: the representation of an element always shows the element's name.
|
55
|
+
# If the element has children, the representation indicates that
|
56
|
+
# by including an ellipsis (<tt>...</tt>).
|
57
|
+
#
|
58
|
+
# The parent may be assigned explicitly at any time:
|
59
|
+
#
|
60
|
+
# e2 = REXML::Element.new('baz')
|
61
|
+
# e1.parent = e2
|
62
|
+
# e1.parent # => <baz/>
|
63
|
+
#
|
64
|
+
# When an element is added as a child, its parent is set automatically:
|
65
|
+
#
|
66
|
+
# e1.add_element(e0)
|
67
|
+
# e0.parent # => <bar> ... </>
|
68
|
+
#
|
69
|
+
# For an element that has no parent, method +parent+ returns +nil+.
|
70
|
+
#
|
71
|
+
# === Children
|
72
|
+
#
|
73
|
+
# An element has zero or more children.
|
74
|
+
# The children are an ordered collection
|
75
|
+
# of all objects whose parent is the element itself.
|
76
|
+
#
|
77
|
+
# The children may include any combination of elements, text, comments,
|
78
|
+
# processing instructions, and CDATA.
|
79
|
+
# (This example keeps things clean by controlling whitespace
|
80
|
+
# via a +context+ setting.)
|
81
|
+
#
|
82
|
+
# xml_string = <<-EOT
|
83
|
+
# <root>
|
84
|
+
# <ele_0/>
|
85
|
+
# text 0
|
86
|
+
# <!--comment 0-->
|
87
|
+
# <?target_0 pi_0?>
|
88
|
+
# <![CDATA[cdata 0]]>
|
89
|
+
# <ele_1/>
|
90
|
+
# text 1
|
91
|
+
# <!--comment 1-->
|
92
|
+
# <?target_0 pi_1?>
|
93
|
+
# <![CDATA[cdata 1]]>
|
94
|
+
# </root>
|
95
|
+
# EOT
|
96
|
+
# context = {ignore_whitespace_nodes: :all, compress_whitespace: :all}
|
97
|
+
# d = REXML::Document.new(xml_string, context)
|
98
|
+
# root = d.root
|
99
|
+
# root.children.size # => 10
|
100
|
+
# root.each {|child| p "#{child.class}: #{child}" }
|
101
|
+
#
|
102
|
+
# Output:
|
103
|
+
#
|
104
|
+
# "REXML::Element: <ele_0/>"
|
105
|
+
# "REXML::Text: \n text 0\n "
|
106
|
+
# "REXML::Comment: comment 0"
|
107
|
+
# "REXML::Instruction: <?target_0 pi_0?>"
|
108
|
+
# "REXML::CData: cdata 0"
|
109
|
+
# "REXML::Element: <ele_1/>"
|
110
|
+
# "REXML::Text: \n text 1\n "
|
111
|
+
# "REXML::Comment: comment 1"
|
112
|
+
# "REXML::Instruction: <?target_0 pi_1?>"
|
113
|
+
# "REXML::CData: cdata 1"
|
114
|
+
#
|
115
|
+
# A child may be added using inherited methods
|
116
|
+
# Parent#insert_before or Parent#insert_after:
|
117
|
+
#
|
118
|
+
# xml_string = '<root><a/><c/><d/></root>'
|
119
|
+
# d = REXML::Document.new(xml_string)
|
120
|
+
# root = d.root
|
121
|
+
# c = d.root[1] # => <c/>
|
122
|
+
# root.insert_before(c, REXML::Element.new('b'))
|
123
|
+
# root.to_a # => [<a/>, <b/>, <c/>, <d/>]
|
124
|
+
#
|
125
|
+
# A child may be replaced using Parent#replace_child:
|
126
|
+
#
|
127
|
+
# root.replace_child(c, REXML::Element.new('x'))
|
128
|
+
# root.to_a # => [<a/>, <b/>, <x/>, <d/>]
|
129
|
+
#
|
130
|
+
# A child may be removed using Parent#delete:
|
131
|
+
#
|
132
|
+
# x = root[2] # => <x/>
|
133
|
+
# root.delete(x)
|
134
|
+
# root.to_a # => [<a/>, <b/>, <d/>]
|
135
|
+
#
|
136
|
+
# === Siblings
|
137
|
+
#
|
138
|
+
# An element has zero or more siblings,
|
139
|
+
# which are the other children of the element's parent.
|
140
|
+
#
|
141
|
+
# In the example above, element +ele_1+ is between a CDATA sibling
|
142
|
+
# and a text sibling:
|
143
|
+
#
|
144
|
+
# ele_1 = root[5] # => <ele_1/>
|
145
|
+
# ele_1.previous_sibling # => "cdata 0"
|
146
|
+
# ele_1.next_sibling # => "\n text 1\n "
|
147
|
+
#
|
148
|
+
# === \Attributes
|
149
|
+
#
|
150
|
+
# An element has zero or more named attributes.
|
151
|
+
#
|
152
|
+
# A new element has no attributes:
|
153
|
+
#
|
154
|
+
# e = REXML::Element.new('foo')
|
155
|
+
# e.attributes # => {}
|
156
|
+
#
|
157
|
+
# Attributes may be added:
|
158
|
+
#
|
159
|
+
# e.add_attribute('bar', 'baz')
|
160
|
+
# e.add_attribute('bat', 'bam')
|
161
|
+
# e.attributes.size # => 2
|
162
|
+
# e['bar'] # => "baz"
|
163
|
+
# e['bat'] # => "bam"
|
164
|
+
#
|
165
|
+
# An existing attribute may be modified:
|
166
|
+
#
|
167
|
+
# e.add_attribute('bar', 'bad')
|
168
|
+
# e.attributes.size # => 2
|
169
|
+
# e['bar'] # => "bad"
|
170
|
+
#
|
171
|
+
# An existing attribute may be deleted:
|
172
|
+
#
|
173
|
+
# e.delete_attribute('bar')
|
174
|
+
# e.attributes.size # => 1
|
175
|
+
# e['bar'] # => nil
|
176
|
+
#
|
177
|
+
# == What's Here
|
178
|
+
#
|
179
|
+
# To begin with, what's elsewhere?
|
180
|
+
#
|
181
|
+
# \Class \REXML::Element inherits from its ancestor classes:
|
182
|
+
#
|
183
|
+
# - REXML::Child
|
184
|
+
# - REXML::Parent
|
185
|
+
#
|
186
|
+
# \REXML::Element itself and its ancestors also include modules:
|
187
|
+
#
|
188
|
+
# - {Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html]
|
189
|
+
# - REXML::Namespace
|
190
|
+
# - REXML::Node
|
191
|
+
# - REXML::XMLTokens
|
192
|
+
#
|
193
|
+
# === Methods for Creating an \Element
|
194
|
+
#
|
195
|
+
# ::new:: Returns a new empty element.
|
196
|
+
# #clone:: Returns a clone of another element.
|
197
|
+
#
|
198
|
+
# === Methods for Attributes
|
199
|
+
#
|
200
|
+
# {[attribute_name]}[#method-i-5B-5D]:: Returns an attribute value.
|
201
|
+
# #add_attribute:: Adds a new attribute.
|
202
|
+
# #add_attributes:: Adds multiple new attributes.
|
203
|
+
# #attribute:: Returns the attribute value for a given name and optional namespace.
|
204
|
+
# #delete_attribute:: Removes an attribute.
|
205
|
+
#
|
206
|
+
# === Methods for Children
|
207
|
+
#
|
208
|
+
# {[index]}[#method-i-5B-5D]:: Returns the child at the given offset.
|
209
|
+
# #add_element:: Adds an element as the last child.
|
210
|
+
# #delete_element:: Deletes a child element.
|
211
|
+
# #each_element:: Calls the given block with each child element.
|
212
|
+
# #each_element_with_attribute:: Calls the given block with each child element
|
213
|
+
# that meets given criteria,
|
214
|
+
# which can include the attribute name.
|
215
|
+
# #each_element_with_text:: Calls the given block with each child element
|
216
|
+
# that meets given criteria,
|
217
|
+
# which can include text.
|
218
|
+
# #get_elements:: Returns an array of element children that match a given xpath.
|
219
|
+
#
|
220
|
+
# === Methods for \Text Children
|
221
|
+
#
|
222
|
+
# #add_text:: Adds a text node to the element.
|
223
|
+
# #get_text:: Returns a text node that meets specified criteria.
|
224
|
+
# #text:: Returns the text string from the first node that meets specified criteria.
|
225
|
+
# #texts:: Returns an array of the text children of the element.
|
226
|
+
# #text=:: Adds, removes, or replaces the first text child of the element
|
227
|
+
#
|
228
|
+
# === Methods for Other Children
|
229
|
+
#
|
230
|
+
# #cdatas:: Returns an array of the cdata children of the element.
|
231
|
+
# #comments:: Returns an array of the comment children of the element.
|
232
|
+
# #instructions:: Returns an array of the instruction children of the element.
|
233
|
+
#
|
234
|
+
# === Methods for Namespaces
|
235
|
+
#
|
236
|
+
# #add_namespace:: Adds a namespace to the element.
|
237
|
+
# #delete_namespace:: Removes a namespace from the element.
|
238
|
+
# #namespace:: Returns the string namespace URI for the element.
|
239
|
+
# #namespaces:: Returns a hash of all defined namespaces in the element.
|
240
|
+
# #prefixes:: Returns an array of the string prefixes (names)
|
241
|
+
# of all defined namespaces in the element
|
242
|
+
#
|
243
|
+
# === Methods for Querying
|
244
|
+
#
|
245
|
+
# #document:: Returns the document, if any, that the element belongs to.
|
246
|
+
# #root:: Returns the most distant element (not document) ancestor of the element.
|
247
|
+
# #root_node:: Returns the most distant ancestor of the element.
|
248
|
+
# #xpath:: Returns the string xpath to the element
|
249
|
+
# relative to the most distant parent
|
250
|
+
# #has_attributes?:: Returns whether the element has attributes.
|
251
|
+
# #has_elements?:: Returns whether the element has elements.
|
252
|
+
# #has_text?:: Returns whether the element has text.
|
253
|
+
# #next_element:: Returns the next sibling that is an element.
|
254
|
+
# #previous_element:: Returns the previous sibling that is an element.
|
255
|
+
# #raw:: Returns whether raw mode is set for the element.
|
256
|
+
# #whitespace:: Returns whether whitespace is respected for the element.
|
257
|
+
# #ignore_whitespace_nodes:: Returns whether whitespace nodes
|
258
|
+
# are to be ignored for the element.
|
259
|
+
# #node_type:: Returns symbol <tt>:element</tt>.
|
260
|
+
#
|
261
|
+
# === One More Method
|
262
|
+
#
|
263
|
+
# #inspect:: Returns a string representation of the element.
|
264
|
+
#
|
265
|
+
# === Accessors
|
266
|
+
#
|
267
|
+
# #elements:: Returns the REXML::Elements object for the element.
|
268
|
+
# #attributes:: Returns the REXML::Attributes object for the element.
|
269
|
+
# #context:: Returns or sets the context hash for the element.
|
270
|
+
#
|
21
271
|
class Element < Parent
|
22
272
|
include Namespace
|
23
273
|
|
@@ -30,32 +280,42 @@ module REXML
|
|
30
280
|
# whitespace handling.
|
31
281
|
attr_accessor :context
|
32
282
|
|
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
|
-
#
|
283
|
+
# :call-seq:
|
284
|
+
# Element.new(name = 'UNDEFINED', parent = nil, context = nil) -> new_element
|
285
|
+
# Element.new(element, parent = nil, context = nil) -> new_element
|
286
|
+
#
|
287
|
+
# Returns a new \REXML::Element object.
|
288
|
+
#
|
289
|
+
# When no arguments are given,
|
290
|
+
# returns an element with name <tt>'UNDEFINED'</tt>:
|
291
|
+
#
|
292
|
+
# e = REXML::Element.new # => <UNDEFINED/>
|
293
|
+
# e.class # => REXML::Element
|
294
|
+
# e.name # => "UNDEFINED"
|
295
|
+
#
|
296
|
+
# When only argument +name+ is given,
|
297
|
+
# returns an element of the given name:
|
298
|
+
#
|
299
|
+
# REXML::Element.new('foo') # => <foo/>
|
300
|
+
#
|
301
|
+
# When only argument +element+ is given, it must be an \REXML::Element object;
|
302
|
+
# returns a shallow copy of the given element:
|
303
|
+
#
|
304
|
+
# e0 = REXML::Element.new('foo')
|
305
|
+
# e1 = REXML::Element.new(e0) # => <foo/>
|
306
|
+
#
|
307
|
+
# When argument +parent+ is also given, it must be an REXML::Parent object:
|
308
|
+
#
|
309
|
+
# e = REXML::Element.new('foo', REXML::Parent.new)
|
310
|
+
# e.parent # => #<REXML::Parent @parent=nil, @children=[<foo/>]>
|
311
|
+
#
|
312
|
+
# When argument +context+ is also given, it must be a hash
|
313
|
+
# representing the context for the element;
|
314
|
+
# see {Element Context}[../doc/rexml/context_rdoc.html]:
|
315
|
+
#
|
316
|
+
# e = REXML::Element.new('foo', nil, {raw: :all})
|
317
|
+
# e.context # => {:raw=>:all}
|
318
|
+
#
|
59
319
|
def initialize( arg = UNDEFINED, parent=nil, context=nil )
|
60
320
|
super(parent)
|
61
321
|
|
@@ -74,6 +334,27 @@ module REXML
|
|
74
334
|
end
|
75
335
|
end
|
76
336
|
|
337
|
+
# :call-seq:
|
338
|
+
# inspect -> string
|
339
|
+
#
|
340
|
+
# Returns a string representation of the element.
|
341
|
+
#
|
342
|
+
# For an element with no attributes and no children, shows the element name:
|
343
|
+
#
|
344
|
+
# REXML::Element.new.inspect # => "<UNDEFINED/>"
|
345
|
+
#
|
346
|
+
# Shows attributes, if any:
|
347
|
+
#
|
348
|
+
# e = REXML::Element.new('foo')
|
349
|
+
# e.add_attributes({'bar' => 0, 'baz' => 1})
|
350
|
+
# e.inspect # => "<foo bar='0' baz='1'/>"
|
351
|
+
#
|
352
|
+
# Shows an ellipsis (<tt>...</tt>), if there are child elements:
|
353
|
+
#
|
354
|
+
# e.add_element(REXML::Element.new('bar'))
|
355
|
+
# e.add_element(REXML::Element.new('baz'))
|
356
|
+
# e.inspect # => "<foo bar='0' baz='1'> ... </>"
|
357
|
+
#
|
77
358
|
def inspect
|
78
359
|
rv = "<#@expanded_name"
|
79
360
|
|
@@ -89,60 +370,123 @@ module REXML
|
|
89
370
|
end
|
90
371
|
end
|
91
372
|
|
92
|
-
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
373
|
+
# :call-seq:
|
374
|
+
# clone -> new_element
|
375
|
+
#
|
376
|
+
# Returns a shallow copy of the element, containing the name and attributes,
|
377
|
+
# but not the parent or children:
|
378
|
+
#
|
379
|
+
# e = REXML::Element.new('foo')
|
380
|
+
# e.add_attributes({'bar' => 0, 'baz' => 1})
|
381
|
+
# e.clone # => <foo bar='0' baz='1'/>
|
382
|
+
#
|
97
383
|
def clone
|
98
384
|
self.class.new self
|
99
385
|
end
|
100
386
|
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
387
|
+
# :call-seq:
|
388
|
+
# root_node -> document or element
|
389
|
+
#
|
390
|
+
# Returns the most distant ancestor of +self+.
|
391
|
+
#
|
392
|
+
# When the element is part of a document,
|
393
|
+
# returns the root node of the document.
|
394
|
+
# Note that the root node is different from the document element;
|
395
|
+
# in this example +a+ is document element and the root node is its parent:
|
396
|
+
#
|
397
|
+
# d = REXML::Document.new('<a><b><c/></b></a>')
|
398
|
+
# top_element = d.first # => <a> ... </>
|
399
|
+
# child = top_element.first # => <b> ... </>
|
400
|
+
# d.root_node == d # => true
|
401
|
+
# top_element.root_node == d # => true
|
402
|
+
# child.root_node == d # => true
|
403
|
+
#
|
404
|
+
# When the element is not part of a document, but does have ancestor elements,
|
405
|
+
# returns the most distant ancestor element:
|
406
|
+
#
|
407
|
+
# e0 = REXML::Element.new('foo')
|
408
|
+
# e1 = REXML::Element.new('bar')
|
409
|
+
# e1.parent = e0
|
410
|
+
# e2 = REXML::Element.new('baz')
|
411
|
+
# e2.parent = e1
|
412
|
+
# e2.root_node == e0 # => true
|
413
|
+
#
|
414
|
+
# When the element has no ancestor elements,
|
415
|
+
# returns +self+:
|
416
|
+
#
|
417
|
+
# e = REXML::Element.new('foo')
|
418
|
+
# e.root_node == e # => true
|
419
|
+
#
|
420
|
+
# Related: #root, #document.
|
421
|
+
#
|
120
422
|
def root_node
|
121
423
|
parent.nil? ? self : parent.root_node
|
122
424
|
end
|
123
425
|
|
426
|
+
# :call-seq:
|
427
|
+
# root -> element
|
428
|
+
#
|
429
|
+
# Returns the most distant _element_ (not document) ancestor of the element:
|
430
|
+
#
|
431
|
+
# d = REXML::Document.new('<a><b><c/></b></a>')
|
432
|
+
# top_element = d.first
|
433
|
+
# child = top_element.first
|
434
|
+
# top_element.root == top_element # => true
|
435
|
+
# child.root == top_element # => true
|
436
|
+
#
|
437
|
+
# For a document, returns the topmost element:
|
438
|
+
#
|
439
|
+
# d.root == top_element # => true
|
440
|
+
#
|
441
|
+
# Related: #root_node, #document.
|
442
|
+
#
|
124
443
|
def root
|
125
|
-
|
126
|
-
|
127
|
-
|
444
|
+
target = self
|
445
|
+
while target
|
446
|
+
return target.elements[1] if target.kind_of? Document
|
447
|
+
parent = target.parent
|
448
|
+
return target if parent.kind_of? Document or parent.nil?
|
449
|
+
target = parent
|
450
|
+
end
|
451
|
+
nil
|
128
452
|
end
|
129
453
|
|
130
|
-
#
|
131
|
-
#
|
454
|
+
# :call-seq:
|
455
|
+
# document -> document or nil
|
456
|
+
#
|
457
|
+
# If the element is part of a document, returns that document:
|
458
|
+
#
|
459
|
+
# d = REXML::Document.new('<a><b><c/></b></a>')
|
460
|
+
# top_element = d.first
|
461
|
+
# child = top_element.first
|
462
|
+
# top_element.document == d # => true
|
463
|
+
# child.document == d # => true
|
464
|
+
#
|
465
|
+
# If the element is not part of a document, returns +nil+:
|
466
|
+
#
|
467
|
+
# REXML::Element.new.document # => nil
|
468
|
+
#
|
469
|
+
# For a document, returns +self+:
|
470
|
+
#
|
471
|
+
# d.document == d # => true
|
472
|
+
#
|
473
|
+
# Related: #root, #root_node.
|
474
|
+
#
|
132
475
|
def document
|
133
476
|
rt = root
|
134
477
|
rt.parent if rt
|
135
478
|
end
|
136
479
|
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
480
|
+
# :call-seq:
|
481
|
+
# whitespace
|
482
|
+
#
|
483
|
+
# Returns +true+ if whitespace is respected for this element,
|
484
|
+
# +false+ otherwise.
|
485
|
+
#
|
486
|
+
# See {Element Context}[../doc/rexml/context_rdoc.html].
|
487
|
+
#
|
488
|
+
# The evaluation is tested against the element's +expanded_name+,
|
489
|
+
# and so is namespace-sensitive.
|
146
490
|
def whitespace
|
147
491
|
@whitespace = nil
|
148
492
|
if @context
|
@@ -159,6 +503,13 @@ module REXML
|
|
159
503
|
@whitespace
|
160
504
|
end
|
161
505
|
|
506
|
+
# :call-seq:
|
507
|
+
# ignore_whitespace_nodes
|
508
|
+
#
|
509
|
+
# Returns +true+ if whitespace nodes are ignored for the element.
|
510
|
+
#
|
511
|
+
# See {Element Context}[../doc/rexml/context_rdoc.html].
|
512
|
+
#
|
162
513
|
def ignore_whitespace_nodes
|
163
514
|
@ignore_whitespace_nodes = false
|
164
515
|
if @context
|
@@ -170,9 +521,12 @@ module REXML
|
|
170
521
|
end
|
171
522
|
end
|
172
523
|
|
173
|
-
#
|
174
|
-
#
|
175
|
-
#
|
524
|
+
# :call-seq:
|
525
|
+
# raw
|
526
|
+
#
|
527
|
+
# Returns +true+ if raw mode is set for the element.
|
528
|
+
#
|
529
|
+
# See {Element Context}[../doc/rexml/context_rdoc.html].
|
176
530
|
#
|
177
531
|
# The evaluation is tested against +expanded_name+, and so is namespace
|
178
532
|
# sensitive.
|
@@ -180,7 +534,7 @@ module REXML
|
|
180
534
|
@raw = (@context and @context[:raw] and
|
181
535
|
(@context[:raw] == :all or
|
182
536
|
@context[:raw].include? expanded_name))
|
183
|
-
|
537
|
+
@raw
|
184
538
|
end
|
185
539
|
|
186
540
|
#once :whitespace, :raw, :ignore_whitespace_nodes
|
@@ -189,10 +543,25 @@ module REXML
|
|
189
543
|
# Namespaces #
|
190
544
|
#################################################
|
191
545
|
|
192
|
-
#
|
193
|
-
#
|
194
|
-
#
|
195
|
-
#
|
546
|
+
# :call-seq:
|
547
|
+
# prefixes -> array_of_namespace_prefixes
|
548
|
+
#
|
549
|
+
# Returns an array of the string prefixes (names) of all defined namespaces
|
550
|
+
# in the element and its ancestors:
|
551
|
+
#
|
552
|
+
# xml_string = <<-EOT
|
553
|
+
# <root>
|
554
|
+
# <a xmlns:x='1' xmlns:y='2'>
|
555
|
+
# <b/>
|
556
|
+
# <c xmlns:z='3'/>
|
557
|
+
# </a>
|
558
|
+
# </root>
|
559
|
+
# EOT
|
560
|
+
# d = REXML::Document.new(xml_string, {compress_whitespace: :all})
|
561
|
+
# d.elements['//a'].prefixes # => ["x", "y"]
|
562
|
+
# d.elements['//b'].prefixes # => ["x", "y"]
|
563
|
+
# d.elements['//c'].prefixes # => ["x", "y", "z"]
|
564
|
+
#
|
196
565
|
def prefixes
|
197
566
|
prefixes = []
|
198
567
|
prefixes = parent.prefixes if parent
|
@@ -200,6 +569,25 @@ module REXML
|
|
200
569
|
return prefixes
|
201
570
|
end
|
202
571
|
|
572
|
+
# :call-seq:
|
573
|
+
# namespaces -> array_of_namespace_names
|
574
|
+
#
|
575
|
+
# Returns a hash of all defined namespaces
|
576
|
+
# in the element and its ancestors:
|
577
|
+
#
|
578
|
+
# xml_string = <<-EOT
|
579
|
+
# <root>
|
580
|
+
# <a xmlns:x='1' xmlns:y='2'>
|
581
|
+
# <b/>
|
582
|
+
# <c xmlns:z='3'/>
|
583
|
+
# </a>
|
584
|
+
# </root>
|
585
|
+
# EOT
|
586
|
+
# d = REXML::Document.new(xml_string)
|
587
|
+
# d.elements['//a'].namespaces # => {"x"=>"1", "y"=>"2"}
|
588
|
+
# d.elements['//b'].namespaces # => {"x"=>"1", "y"=>"2"}
|
589
|
+
# d.elements['//c'].namespaces # => {"x"=>"1", "y"=>"2", "z"=>"3"}
|
590
|
+
#
|
203
591
|
def namespaces
|
204
592
|
namespaces = {}
|
205
593
|
namespaces = parent.namespaces if parent
|
@@ -207,19 +595,26 @@ module REXML
|
|
207
595
|
return namespaces
|
208
596
|
end
|
209
597
|
|
210
|
-
#
|
211
|
-
#
|
212
|
-
#
|
213
|
-
#
|
214
|
-
#
|
215
|
-
#
|
216
|
-
#
|
217
|
-
#
|
218
|
-
#
|
219
|
-
#
|
220
|
-
#
|
221
|
-
#
|
222
|
-
#
|
598
|
+
# :call-seq:
|
599
|
+
# namespace(prefix = nil) -> string_uri or nil
|
600
|
+
#
|
601
|
+
# Returns the string namespace URI for the element,
|
602
|
+
# possibly deriving from one of its ancestors.
|
603
|
+
#
|
604
|
+
# xml_string = <<-EOT
|
605
|
+
# <root>
|
606
|
+
# <a xmlns='1' xmlns:y='2'>
|
607
|
+
# <b/>
|
608
|
+
# <c xmlns:z='3'/>
|
609
|
+
# </a>
|
610
|
+
# </root>
|
611
|
+
# EOT
|
612
|
+
# d = REXML::Document.new(xml_string)
|
613
|
+
# b = d.elements['//b']
|
614
|
+
# b.namespace # => "1"
|
615
|
+
# b.namespace('y') # => "2"
|
616
|
+
# b.namespace('nosuch') # => nil
|
617
|
+
#
|
223
618
|
def namespace(prefix=nil)
|
224
619
|
if prefix.nil?
|
225
620
|
prefix = prefix()
|
@@ -229,25 +624,34 @@ module REXML
|
|
229
624
|
else
|
230
625
|
prefix = "xmlns:#{prefix}" unless prefix[0,5] == 'xmlns'
|
231
626
|
end
|
232
|
-
ns =
|
233
|
-
|
627
|
+
ns = nil
|
628
|
+
target = self
|
629
|
+
while ns.nil? and target
|
630
|
+
ns = target.attributes[prefix]
|
631
|
+
target = target.parent
|
632
|
+
end
|
234
633
|
ns = '' if ns.nil? and prefix == 'xmlns'
|
235
634
|
return ns
|
236
635
|
end
|
237
636
|
|
238
|
-
#
|
239
|
-
#
|
240
|
-
#
|
241
|
-
#
|
242
|
-
#
|
243
|
-
#
|
244
|
-
#
|
245
|
-
#
|
246
|
-
#
|
247
|
-
#
|
248
|
-
#
|
249
|
-
#
|
250
|
-
#
|
637
|
+
# :call-seq:
|
638
|
+
# add_namespace(prefix, uri = nil) -> self
|
639
|
+
#
|
640
|
+
# Adds a namespace to the element; returns +self+.
|
641
|
+
#
|
642
|
+
# With the single argument +prefix+,
|
643
|
+
# adds a namespace using the given +prefix+ and the namespace URI:
|
644
|
+
#
|
645
|
+
# e = REXML::Element.new('foo')
|
646
|
+
# e.add_namespace('bar')
|
647
|
+
# e.namespaces # => {"xmlns"=>"bar"}
|
648
|
+
#
|
649
|
+
# With both arguments +prefix+ and +uri+ given,
|
650
|
+
# adds a namespace using both arguments:
|
651
|
+
#
|
652
|
+
# e.add_namespace('baz', 'bat')
|
653
|
+
# e.namespaces # => {"xmlns"=>"bar", "baz"=>"bat"}
|
654
|
+
#
|
251
655
|
def add_namespace( prefix, uri=nil )
|
252
656
|
unless uri
|
253
657
|
@attributes["xmlns"] = prefix
|
@@ -258,16 +662,28 @@ module REXML
|
|
258
662
|
self
|
259
663
|
end
|
260
664
|
|
261
|
-
#
|
262
|
-
#
|
263
|
-
#
|
665
|
+
# :call-seq:
|
666
|
+
# delete_namespace(namespace = 'xmlns') -> self
|
667
|
+
#
|
668
|
+
# Removes a namespace from the element.
|
669
|
+
#
|
670
|
+
# With no argument, removes the default namespace:
|
671
|
+
#
|
672
|
+
# d = REXML::Document.new "<a xmlns:foo='bar' xmlns='twiddle'/>"
|
673
|
+
# d.to_s # => "<a xmlns:foo='bar' xmlns='twiddle'/>"
|
674
|
+
# d.root.delete_namespace # => <a xmlns:foo='bar'/>
|
675
|
+
# d.to_s # => "<a xmlns:foo='bar'/>"
|
676
|
+
#
|
677
|
+
# With argument +namespace+, removes the specified namespace:
|
678
|
+
#
|
679
|
+
# d.root.delete_namespace('foo')
|
680
|
+
# d.to_s # => "<a/>"
|
681
|
+
#
|
682
|
+
# Does nothing if no such namespace is found:
|
683
|
+
#
|
684
|
+
# d.root.delete_namespace('nosuch')
|
685
|
+
# d.to_s # => "<a/>"
|
264
686
|
#
|
265
|
-
# Evaluates to: this element
|
266
|
-
# doc = Document.new "<a xmlns:foo='bar' xmlns='twiddle'/>"
|
267
|
-
# doc.root.delete_namespace
|
268
|
-
# puts doc # -> <a xmlns:foo='bar'/>
|
269
|
-
# doc.root.delete_namespace 'foo'
|
270
|
-
# puts doc # -> <a/>
|
271
687
|
def delete_namespace namespace="xmlns"
|
272
688
|
namespace = "xmlns:#{namespace}" unless namespace == 'xmlns'
|
273
689
|
attribute = attributes.get_attribute(namespace)
|
@@ -279,20 +695,40 @@ module REXML
|
|
279
695
|
# Elements #
|
280
696
|
#################################################
|
281
697
|
|
282
|
-
#
|
283
|
-
#
|
284
|
-
# element
|
285
|
-
#
|
286
|
-
#
|
287
|
-
#
|
288
|
-
#
|
289
|
-
#
|
290
|
-
#
|
291
|
-
#
|
292
|
-
#
|
293
|
-
#
|
294
|
-
#
|
295
|
-
#
|
698
|
+
# :call-seq:
|
699
|
+
# add_element(name, attributes = nil) -> new_element
|
700
|
+
# add_element(element, attributes = nil) -> element
|
701
|
+
#
|
702
|
+
# Adds a child element, optionally setting attributes
|
703
|
+
# on the added element; returns the added element.
|
704
|
+
#
|
705
|
+
# With string argument +name+, creates a new element with that name
|
706
|
+
# and adds the new element as a child:
|
707
|
+
#
|
708
|
+
# e0 = REXML::Element.new('foo')
|
709
|
+
# e0.add_element('bar')
|
710
|
+
# e0[0] # => <bar/>
|
711
|
+
#
|
712
|
+
#
|
713
|
+
# With argument +name+ and hash argument +attributes+,
|
714
|
+
# sets attributes on the new element:
|
715
|
+
#
|
716
|
+
# e0.add_element('baz', {'bat' => '0', 'bam' => '1'})
|
717
|
+
# e0[1] # => <baz bat='0' bam='1'/>
|
718
|
+
#
|
719
|
+
# With element argument +element+, adds that element as a child:
|
720
|
+
#
|
721
|
+
# e0 = REXML::Element.new('foo')
|
722
|
+
# e1 = REXML::Element.new('bar')
|
723
|
+
# e0.add_element(e1)
|
724
|
+
# e0[0] # => <bar/>
|
725
|
+
#
|
726
|
+
# With argument +element+ and hash argument +attributes+,
|
727
|
+
# sets attributes on the added element:
|
728
|
+
#
|
729
|
+
# e0.add_element(e1, {'bat' => '0', 'bam' => '1'})
|
730
|
+
# e0[1] # => <bar bat='0' bam='1'/>
|
731
|
+
#
|
296
732
|
def add_element element, attrs=nil
|
297
733
|
raise "First argument must be either an element name, or an Element object" if element.nil?
|
298
734
|
el = @elements.add(element)
|
@@ -302,52 +738,112 @@ module REXML
|
|
302
738
|
el
|
303
739
|
end
|
304
740
|
|
741
|
+
# :call-seq:
|
742
|
+
# delete_element(index) -> removed_element or nil
|
743
|
+
# delete_element(element) -> removed_element or nil
|
744
|
+
# delete_element(xpath) -> removed_element or nil
|
745
|
+
#
|
305
746
|
# Deletes a child element.
|
306
|
-
#
|
307
|
-
#
|
308
|
-
#
|
309
|
-
#
|
310
|
-
#
|
311
|
-
#
|
312
|
-
#
|
313
|
-
#
|
314
|
-
#
|
315
|
-
#
|
747
|
+
#
|
748
|
+
# When 1-based integer argument +index+ is given,
|
749
|
+
# removes and returns the child element at that offset if it exists;
|
750
|
+
# indexing does not include text nodes;
|
751
|
+
# returns +nil+ if the element does not exist:
|
752
|
+
#
|
753
|
+
# d = REXML::Document.new '<a><b/>text<c/></a>'
|
754
|
+
# a = d.root # => <a> ... </>
|
755
|
+
# a.delete_element(1) # => <b/>
|
756
|
+
# a.delete_element(1) # => <c/>
|
757
|
+
# a.delete_element(1) # => nil
|
758
|
+
#
|
759
|
+
# When element argument +element+ is given,
|
760
|
+
# removes and returns that child element if it exists,
|
761
|
+
# otherwise returns +nil+:
|
762
|
+
#
|
763
|
+
# d = REXML::Document.new '<a><b/>text<c/></a>'
|
764
|
+
# a = d.root # => <a> ... </>
|
765
|
+
# c = a[2] # => <c/>
|
766
|
+
# a.delete_element(c) # => <c/>
|
767
|
+
# a.delete_element(c) # => nil
|
768
|
+
#
|
769
|
+
# When xpath argument +xpath+ is given,
|
770
|
+
# removes and returns the element at xpath if it exists,
|
771
|
+
# otherwise returns +nil+:
|
772
|
+
#
|
773
|
+
# d = REXML::Document.new '<a><b/>text<c/></a>'
|
774
|
+
# a = d.root # => <a> ... </>
|
775
|
+
# a.delete_element('//c') # => <c/>
|
776
|
+
# a.delete_element('//c') # => nil
|
777
|
+
#
|
316
778
|
def delete_element element
|
317
779
|
@elements.delete element
|
318
780
|
end
|
319
781
|
|
320
|
-
#
|
321
|
-
#
|
322
|
-
#
|
323
|
-
#
|
324
|
-
#
|
782
|
+
# :call-seq:
|
783
|
+
# has_elements?
|
784
|
+
#
|
785
|
+
# Returns +true+ if the element has one or more element children,
|
786
|
+
# +false+ otherwise:
|
787
|
+
#
|
788
|
+
# d = REXML::Document.new '<a><b/>text<c/></a>'
|
789
|
+
# a = d.root # => <a> ... </>
|
790
|
+
# a.has_elements? # => true
|
791
|
+
# b = a[0] # => <b/>
|
792
|
+
# b.has_elements? # => false
|
793
|
+
#
|
325
794
|
def has_elements?
|
326
795
|
!@elements.empty?
|
327
796
|
end
|
328
797
|
|
329
|
-
#
|
330
|
-
#
|
331
|
-
#
|
332
|
-
#
|
333
|
-
#
|
334
|
-
#
|
335
|
-
#
|
336
|
-
#
|
337
|
-
#
|
338
|
-
#
|
339
|
-
# (
|
340
|
-
#
|
341
|
-
#
|
342
|
-
#
|
343
|
-
#
|
344
|
-
#
|
345
|
-
#
|
346
|
-
#
|
347
|
-
#
|
348
|
-
#
|
349
|
-
#
|
350
|
-
#
|
798
|
+
# :call-seq:
|
799
|
+
# each_element_with_attribute(attr_name, value = nil, max = 0, xpath = nil) {|e| ... }
|
800
|
+
#
|
801
|
+
# Calls the given block with each child element that meets given criteria.
|
802
|
+
#
|
803
|
+
# When only string argument +attr_name+ is given,
|
804
|
+
# calls the block with each child element that has that attribute:
|
805
|
+
#
|
806
|
+
# d = REXML::Document.new '<a><b id="1"/><c id="2"/><d id="1"/><e/></a>'
|
807
|
+
# a = d.root
|
808
|
+
# a.each_element_with_attribute('id') {|e| p e }
|
809
|
+
#
|
810
|
+
# Output:
|
811
|
+
#
|
812
|
+
# <b id='1'/>
|
813
|
+
# <c id='2'/>
|
814
|
+
# <d id='1'/>
|
815
|
+
#
|
816
|
+
# With argument +attr_name+ and string argument +value+ given,
|
817
|
+
# calls the block with each child element that has that attribute
|
818
|
+
# with that value:
|
819
|
+
#
|
820
|
+
# a.each_element_with_attribute('id', '1') {|e| p e }
|
821
|
+
#
|
822
|
+
# Output:
|
823
|
+
#
|
824
|
+
# <b id='1'/>
|
825
|
+
# <d id='1'/>
|
826
|
+
#
|
827
|
+
# With arguments +attr_name+, +value+, and integer argument +max+ given,
|
828
|
+
# calls the block with at most +max+ child elements:
|
829
|
+
#
|
830
|
+
# a.each_element_with_attribute('id', '1', 1) {|e| p e }
|
831
|
+
#
|
832
|
+
# Output:
|
833
|
+
#
|
834
|
+
# <b id='1'/>
|
835
|
+
#
|
836
|
+
# With all arguments given, including +xpath+,
|
837
|
+
# calls the block with only those child elements
|
838
|
+
# that meet the first three criteria,
|
839
|
+
# and also match the given +xpath+:
|
840
|
+
#
|
841
|
+
# a.each_element_with_attribute('id', '1', 2, '//d') {|e| p e }
|
842
|
+
#
|
843
|
+
# Output:
|
844
|
+
#
|
845
|
+
# <d id='1'/>
|
846
|
+
#
|
351
847
|
def each_element_with_attribute( key, value=nil, max=0, name=nil, &block ) # :yields: Element
|
352
848
|
each_with_something( proc {|child|
|
353
849
|
if value.nil?
|
@@ -358,27 +854,53 @@ module REXML
|
|
358
854
|
}, max, name, &block )
|
359
855
|
end
|
360
856
|
|
361
|
-
#
|
362
|
-
#
|
363
|
-
#
|
364
|
-
#
|
365
|
-
#
|
366
|
-
#
|
367
|
-
#
|
368
|
-
#
|
369
|
-
#
|
370
|
-
#
|
371
|
-
#
|
372
|
-
#
|
373
|
-
#
|
374
|
-
#
|
375
|
-
#
|
376
|
-
#
|
377
|
-
#
|
378
|
-
#
|
379
|
-
#
|
380
|
-
#
|
381
|
-
#
|
857
|
+
# :call-seq:
|
858
|
+
# each_element_with_text(text = nil, max = 0, xpath = nil) {|e| ... }
|
859
|
+
#
|
860
|
+
# Calls the given block with each child element that meets given criteria.
|
861
|
+
#
|
862
|
+
# With no arguments, calls the block with each child element that has text:
|
863
|
+
#
|
864
|
+
# d = REXML::Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
|
865
|
+
# a = d.root
|
866
|
+
# a.each_element_with_text {|e| p e }
|
867
|
+
#
|
868
|
+
# Output:
|
869
|
+
#
|
870
|
+
# <b> ... </>
|
871
|
+
# <c> ... </>
|
872
|
+
# <d> ... </>
|
873
|
+
#
|
874
|
+
# With the single string argument +text+,
|
875
|
+
# calls the block with each element that has exactly that text:
|
876
|
+
#
|
877
|
+
# a.each_element_with_text('b') {|e| p e }
|
878
|
+
#
|
879
|
+
# Output:
|
880
|
+
#
|
881
|
+
# <b> ... </>
|
882
|
+
# <c> ... </>
|
883
|
+
#
|
884
|
+
# With argument +text+ and integer argument +max+,
|
885
|
+
# calls the block with at most +max+ elements:
|
886
|
+
#
|
887
|
+
# a.each_element_with_text('b', 1) {|e| p e }
|
888
|
+
#
|
889
|
+
# Output:
|
890
|
+
#
|
891
|
+
# <b> ... </>
|
892
|
+
#
|
893
|
+
# With all arguments given, including +xpath+,
|
894
|
+
# calls the block with only those child elements
|
895
|
+
# that meet the first two criteria,
|
896
|
+
# and also match the given +xpath+:
|
897
|
+
#
|
898
|
+
# a.each_element_with_text('b', 2, '//c') {|e| p e }
|
899
|
+
#
|
900
|
+
# Output:
|
901
|
+
#
|
902
|
+
# <c> ... </>
|
903
|
+
#
|
382
904
|
def each_element_with_text( text=nil, max=0, name=nil, &block ) # :yields: Element
|
383
905
|
each_with_something( proc {|child|
|
384
906
|
if text.nil?
|
@@ -389,35 +911,71 @@ module REXML
|
|
389
911
|
}, max, name, &block )
|
390
912
|
end
|
391
913
|
|
392
|
-
#
|
914
|
+
# :call-seq:
|
915
|
+
# each_element {|e| ... }
|
916
|
+
#
|
917
|
+
# Calls the given block with each child element:
|
918
|
+
#
|
919
|
+
# d = REXML::Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
|
920
|
+
# a = d.root
|
921
|
+
# a.each_element {|e| p e }
|
922
|
+
#
|
923
|
+
# Output:
|
924
|
+
#
|
925
|
+
# <b> ... </>
|
926
|
+
# <c> ... </>
|
927
|
+
# <d> ... </>
|
928
|
+
# <e/>
|
929
|
+
#
|
393
930
|
def each_element( xpath=nil, &block ) # :yields: Element
|
394
931
|
@elements.each( xpath, &block )
|
395
932
|
end
|
396
933
|
|
397
|
-
#
|
398
|
-
#
|
399
|
-
#
|
400
|
-
# Returns
|
934
|
+
# :call-seq:
|
935
|
+
# get_elements(xpath)
|
936
|
+
#
|
937
|
+
# Returns an array of the elements that match the given +xpath+:
|
938
|
+
#
|
939
|
+
# xml_string = <<-EOT
|
940
|
+
# <root>
|
941
|
+
# <a level='1'>
|
942
|
+
# <a level='2'/>
|
943
|
+
# </a>
|
944
|
+
# </root>
|
945
|
+
# EOT
|
946
|
+
# d = REXML::Document.new(xml_string)
|
947
|
+
# d.root.get_elements('//a') # => [<a level='1'> ... </>, <a level='2'/>]
|
948
|
+
#
|
401
949
|
def get_elements( xpath )
|
402
950
|
@elements.to_a( xpath )
|
403
951
|
end
|
404
952
|
|
405
|
-
#
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
409
|
-
#
|
953
|
+
# :call-seq:
|
954
|
+
# next_element
|
955
|
+
#
|
956
|
+
# Returns the next sibling that is an element if it exists,
|
957
|
+
# +niL+ otherwise:
|
958
|
+
#
|
959
|
+
# d = REXML::Document.new '<a><b/>text<c/></a>'
|
960
|
+
# d.root.elements['b'].next_element #-> <c/>
|
961
|
+
# d.root.elements['c'].next_element #-> nil
|
962
|
+
#
|
410
963
|
def next_element
|
411
964
|
element = next_sibling
|
412
965
|
element = element.next_sibling until element.nil? or element.kind_of? Element
|
413
966
|
return element
|
414
967
|
end
|
415
968
|
|
416
|
-
#
|
417
|
-
#
|
418
|
-
#
|
419
|
-
#
|
420
|
-
#
|
969
|
+
# :call-seq:
|
970
|
+
# previous_element
|
971
|
+
#
|
972
|
+
# Returns the previous sibling that is an element if it exists,
|
973
|
+
# +niL+ otherwise:
|
974
|
+
#
|
975
|
+
# d = REXML::Document.new '<a><b/>text<c/></a>'
|
976
|
+
# d.root.elements['c'].previous_element #-> <b/>
|
977
|
+
# d.root.elements['b'].previous_element #-> nil
|
978
|
+
#
|
421
979
|
def previous_element
|
422
980
|
element = previous_sibling
|
423
981
|
element = element.previous_sibling until element.nil? or element.kind_of? Element
|
@@ -429,36 +987,69 @@ module REXML
|
|
429
987
|
# Text #
|
430
988
|
#################################################
|
431
989
|
|
432
|
-
#
|
990
|
+
# :call-seq:
|
991
|
+
# has_text? -> true or false
|
992
|
+
#
|
993
|
+
# Returns +true+ if the element has one or more text noded,
|
994
|
+
# +false+ otherwise:
|
995
|
+
#
|
996
|
+
# d = REXML::Document.new '<a><b/>text<c/></a>'
|
997
|
+
# a = d.root
|
998
|
+
# a.has_text? # => true
|
999
|
+
# b = a[0]
|
1000
|
+
# b.has_text? # => false
|
1001
|
+
#
|
433
1002
|
def has_text?
|
434
1003
|
not text().nil?
|
435
1004
|
end
|
436
1005
|
|
437
|
-
#
|
438
|
-
#
|
1006
|
+
# :call-seq:
|
1007
|
+
# text(xpath = nil) -> text_string or nil
|
439
1008
|
#
|
440
|
-
#
|
441
|
-
#
|
442
|
-
# the first Text node.
|
1009
|
+
# Returns the text string from the first text node child
|
1010
|
+
# in a specified element, if it exists, +nil+ otherwise.
|
443
1011
|
#
|
444
|
-
#
|
445
|
-
#
|
446
|
-
#
|
1012
|
+
# With no argument, returns the text from the first text node in +self+:
|
1013
|
+
#
|
1014
|
+
# d = REXML::Document.new "<p>some text <b>this is bold!</b> more text</p>"
|
1015
|
+
# d.root.text.class # => String
|
1016
|
+
# d.root.text # => "some text "
|
1017
|
+
#
|
1018
|
+
# With argument +xpath+, returns text from the first text node
|
1019
|
+
# in the element that matches +xpath+:
|
1020
|
+
#
|
1021
|
+
# d.root.text(1) # => "this is bold!"
|
1022
|
+
#
|
1023
|
+
# Note that an element may have multiple text nodes,
|
1024
|
+
# possibly separated by other non-text children, as above.
|
1025
|
+
# Even so, the returned value is the string text from the first such node.
|
1026
|
+
#
|
1027
|
+
# Note also that the text note is retrieved by method get_text,
|
1028
|
+
# and so is always normalized text.
|
447
1029
|
#
|
448
|
-
# doc = Document.new "<p>some text <b>this is bold!</b> more text</p>"
|
449
|
-
# # The element 'p' has two text elements, "some text " and " more text".
|
450
|
-
# doc.root.text #-> "some text "
|
451
1030
|
def text( path = nil )
|
452
1031
|
rv = get_text(path)
|
453
1032
|
return rv.value unless rv.nil?
|
454
1033
|
nil
|
455
1034
|
end
|
456
1035
|
|
457
|
-
#
|
458
|
-
#
|
459
|
-
#
|
460
|
-
#
|
461
|
-
#
|
1036
|
+
# :call-seq:
|
1037
|
+
# get_text(xpath = nil) -> text_node or nil
|
1038
|
+
#
|
1039
|
+
# Returns the first text node child in a specified element, if it exists,
|
1040
|
+
# +nil+ otherwise.
|
1041
|
+
#
|
1042
|
+
# With no argument, returns the first text node from +self+:
|
1043
|
+
#
|
1044
|
+
# d = REXML::Document.new "<p>some text <b>this is bold!</b> more text</p>"
|
1045
|
+
# d.root.get_text.class # => REXML::Text
|
1046
|
+
# d.root.get_text # => "some text "
|
1047
|
+
#
|
1048
|
+
# With argument +xpath+, returns the first text node from the element
|
1049
|
+
# that matches +xpath+:
|
1050
|
+
#
|
1051
|
+
# d.root.get_text(1) # => "this is bold!"
|
1052
|
+
#
|
462
1053
|
def get_text path = nil
|
463
1054
|
rv = nil
|
464
1055
|
if path
|
@@ -470,26 +1061,31 @@ module REXML
|
|
470
1061
|
return rv
|
471
1062
|
end
|
472
1063
|
|
473
|
-
#
|
474
|
-
#
|
475
|
-
#
|
476
|
-
#
|
477
|
-
#
|
478
|
-
#
|
479
|
-
#
|
480
|
-
#
|
481
|
-
#
|
482
|
-
#
|
483
|
-
#
|
484
|
-
#
|
485
|
-
#
|
486
|
-
#
|
487
|
-
#
|
488
|
-
#
|
489
|
-
#
|
490
|
-
#
|
491
|
-
#
|
492
|
-
#
|
1064
|
+
# :call-seq:
|
1065
|
+
# text = string -> string
|
1066
|
+
# text = nil -> nil
|
1067
|
+
#
|
1068
|
+
# Adds, replaces, or removes the first text node child in the element.
|
1069
|
+
#
|
1070
|
+
# With string argument +string+,
|
1071
|
+
# creates a new \REXML::Text node containing that string,
|
1072
|
+
# honoring the current settings for whitespace and row,
|
1073
|
+
# then places the node as the first text child in the element;
|
1074
|
+
# returns +string+.
|
1075
|
+
#
|
1076
|
+
# If the element has no text child, the text node is added:
|
1077
|
+
#
|
1078
|
+
# d = REXML::Document.new '<a><b/></a>'
|
1079
|
+
# d.root.text = 'foo' #-> '<a><b/>foo</a>'
|
1080
|
+
#
|
1081
|
+
# If the element has a text child, it is replaced:
|
1082
|
+
#
|
1083
|
+
# d.root.text = 'bar' #-> '<a><b/>bar</a>'
|
1084
|
+
#
|
1085
|
+
# With argument +nil+, removes the first text child:
|
1086
|
+
#
|
1087
|
+
# d.root.text = nil #-> '<a><b/><c/></a>'
|
1088
|
+
#
|
493
1089
|
def text=( text )
|
494
1090
|
if text.kind_of? String
|
495
1091
|
text = Text.new( text, whitespace(), nil, raw() )
|
@@ -509,17 +1105,45 @@ module REXML
|
|
509
1105
|
return self
|
510
1106
|
end
|
511
1107
|
|
512
|
-
#
|
513
|
-
#
|
514
|
-
#
|
515
|
-
#
|
516
|
-
#
|
517
|
-
#
|
518
|
-
#
|
519
|
-
#
|
520
|
-
#
|
521
|
-
#
|
522
|
-
#
|
1108
|
+
# :call-seq:
|
1109
|
+
# add_text(string) -> nil
|
1110
|
+
# add_text(text_node) -> self
|
1111
|
+
#
|
1112
|
+
# Adds text to the element.
|
1113
|
+
#
|
1114
|
+
# When string argument +string+ is given, returns +nil+.
|
1115
|
+
#
|
1116
|
+
# If the element has no child text node,
|
1117
|
+
# creates a \REXML::Text object using the string,
|
1118
|
+
# honoring the current settings for whitespace and raw,
|
1119
|
+
# then adds that node to the element:
|
1120
|
+
#
|
1121
|
+
# d = REXML::Document.new('<a><b/></a>')
|
1122
|
+
# a = d.root
|
1123
|
+
# a.add_text('foo')
|
1124
|
+
# a.to_a # => [<b/>, "foo"]
|
1125
|
+
#
|
1126
|
+
# If the element has child text nodes,
|
1127
|
+
# appends the string to the _last_ text node:
|
1128
|
+
#
|
1129
|
+
# d = REXML::Document.new('<a>foo<b/>bar</a>')
|
1130
|
+
# a = d.root
|
1131
|
+
# a.add_text('baz')
|
1132
|
+
# a.to_a # => ["foo", <b/>, "barbaz"]
|
1133
|
+
# a.add_text('baz')
|
1134
|
+
# a.to_a # => ["foo", <b/>, "barbazbaz"]
|
1135
|
+
#
|
1136
|
+
# When text node argument +text_node+ is given,
|
1137
|
+
# appends the node as the last text node in the element;
|
1138
|
+
# returns +self+:
|
1139
|
+
#
|
1140
|
+
# d = REXML::Document.new('<a>foo<b/>bar</a>')
|
1141
|
+
# a = d.root
|
1142
|
+
# a.add_text(REXML::Text.new('baz'))
|
1143
|
+
# a.to_a # => ["foo", <b/>, "bar", "baz"]
|
1144
|
+
# a.add_text(REXML::Text.new('baz'))
|
1145
|
+
# a.to_a # => ["foo", <b/>, "bar", "baz", "baz"]
|
1146
|
+
#
|
523
1147
|
def add_text( text )
|
524
1148
|
if text.kind_of? String
|
525
1149
|
if @children[-1].kind_of? Text
|
@@ -532,10 +1156,39 @@ module REXML
|
|
532
1156
|
return self
|
533
1157
|
end
|
534
1158
|
|
1159
|
+
# :call-seq:
|
1160
|
+
# node_type -> :element
|
1161
|
+
#
|
1162
|
+
# Returns symbol <tt>:element</tt>:
|
1163
|
+
#
|
1164
|
+
# d = REXML::Document.new('<a/>')
|
1165
|
+
# a = d.root # => <a/>
|
1166
|
+
# a.node_type # => :element
|
1167
|
+
#
|
535
1168
|
def node_type
|
536
1169
|
:element
|
537
1170
|
end
|
538
1171
|
|
1172
|
+
# :call-seq:
|
1173
|
+
# xpath -> string_xpath
|
1174
|
+
#
|
1175
|
+
# Returns the string xpath to the element
|
1176
|
+
# relative to the most distant parent:
|
1177
|
+
#
|
1178
|
+
# d = REXML::Document.new('<a><b><c/></b></a>')
|
1179
|
+
# a = d.root # => <a> ... </>
|
1180
|
+
# b = a[0] # => <b> ... </>
|
1181
|
+
# c = b[0] # => <c/>
|
1182
|
+
# d.xpath # => ""
|
1183
|
+
# a.xpath # => "/a"
|
1184
|
+
# b.xpath # => "/a/b"
|
1185
|
+
# c.xpath # => "/a/b/c"
|
1186
|
+
#
|
1187
|
+
# If there is no parent, returns the expanded name of the element:
|
1188
|
+
#
|
1189
|
+
# e = REXML::Element.new('foo')
|
1190
|
+
# e.xpath # => "foo"
|
1191
|
+
#
|
539
1192
|
def xpath
|
540
1193
|
path_elements = []
|
541
1194
|
cur = self
|
@@ -551,19 +1204,45 @@ module REXML
|
|
551
1204
|
# Attributes #
|
552
1205
|
#################################################
|
553
1206
|
|
554
|
-
#
|
1207
|
+
# :call-seq:
|
1208
|
+
# [index] -> object
|
1209
|
+
# [attr_name] -> attr_value
|
1210
|
+
# [attr_sym] -> attr_value
|
1211
|
+
#
|
1212
|
+
# With integer argument +index+ given,
|
1213
|
+
# returns the child at offset +index+, or +nil+ if none:
|
1214
|
+
#
|
1215
|
+
# d = REXML::Document.new '><root><a/>text<b/>more<c/></root>'
|
1216
|
+
# root = d.root
|
1217
|
+
# (0..root.size).each do |index|
|
1218
|
+
# node = root[index]
|
1219
|
+
# p "#{index}: #{node} (#{node.class})"
|
1220
|
+
# end
|
1221
|
+
#
|
1222
|
+
# Output:
|
1223
|
+
#
|
1224
|
+
# "0: <a/> (REXML::Element)"
|
1225
|
+
# "1: text (REXML::Text)"
|
1226
|
+
# "2: <b/> (REXML::Element)"
|
1227
|
+
# "3: more (REXML::Text)"
|
1228
|
+
# "4: <c/> (REXML::Element)"
|
1229
|
+
# "5: (NilClass)"
|
1230
|
+
#
|
1231
|
+
# With string argument +attr_name+ given,
|
1232
|
+
# returns the string value for the given attribute name if it exists,
|
1233
|
+
# otherwise +nil+:
|
555
1234
|
#
|
556
|
-
#
|
557
|
-
#
|
558
|
-
#
|
1235
|
+
# d = REXML::Document.new('<root attr="value"></root>')
|
1236
|
+
# root = d.root
|
1237
|
+
# root['attr'] # => "value"
|
1238
|
+
# root['nosuch'] # => nil
|
559
1239
|
#
|
560
|
-
#
|
561
|
-
#
|
1240
|
+
# With symbol argument +attr_sym+ given,
|
1241
|
+
# returns <tt>[attr_sym.to_s]</tt>:
|
1242
|
+
#
|
1243
|
+
# root[:attr] # => "value"
|
1244
|
+
# root[:nosuch] # => nil
|
562
1245
|
#
|
563
|
-
# doc = REXML::Document.new("<a attr='1'><b/><c/></a>")
|
564
|
-
# doc.root["attr"] # => "1"
|
565
|
-
# doc.root.attributes["attr"] # => "1"
|
566
|
-
# doc.root[1] # => <c/>
|
567
1246
|
def [](name_or_index)
|
568
1247
|
case name_or_index
|
569
1248
|
when String
|
@@ -575,17 +1254,42 @@ module REXML
|
|
575
1254
|
end
|
576
1255
|
end
|
577
1256
|
|
1257
|
+
|
1258
|
+
# :call-seq:
|
1259
|
+
# attribute(name, namespace = nil)
|
1260
|
+
#
|
1261
|
+
# Returns the string value for the given attribute name.
|
1262
|
+
#
|
1263
|
+
# With only argument +name+ given,
|
1264
|
+
# returns the value of the named attribute if it exists, otherwise +nil+:
|
1265
|
+
#
|
1266
|
+
# xml_string = <<-EOT
|
1267
|
+
# <root xmlns="ns0">
|
1268
|
+
# <a xmlns="ns1" attr="value"></a>
|
1269
|
+
# <b xmlns="ns2" attr="value"></b>
|
1270
|
+
# <c attr="value"/>
|
1271
|
+
# </root>
|
1272
|
+
# EOT
|
1273
|
+
# d = REXML::Document.new(xml_string)
|
1274
|
+
# root = d.root
|
1275
|
+
# a = root[1] # => <a xmlns='ns1' attr='value'/>
|
1276
|
+
# a.attribute('attr') # => attr='value'
|
1277
|
+
# a.attribute('nope') # => nil
|
1278
|
+
#
|
1279
|
+
# With arguments +name+ and +namespace+ given,
|
1280
|
+
# returns the value of the named attribute if it exists, otherwise +nil+:
|
1281
|
+
#
|
1282
|
+
# xml_string = "<root xmlns:a='a' a:x='a:x' x='x'/>"
|
1283
|
+
# document = REXML::Document.new(xml_string)
|
1284
|
+
# document.root.attribute("x") # => x='x'
|
1285
|
+
# document.root.attribute("x", "a") # => a:x='a:x'
|
1286
|
+
#
|
578
1287
|
def attribute( name, namespace=nil )
|
579
|
-
prefix =
|
580
|
-
if namespaces.respond_to? :key
|
581
|
-
prefix = namespaces.key(namespace) if namespace
|
582
|
-
else
|
583
|
-
prefix = namespaces.index(namespace) if namespace
|
584
|
-
end
|
1288
|
+
prefix = namespaces.key(namespace) if namespace
|
585
1289
|
prefix = nil if prefix == 'xmlns'
|
586
1290
|
|
587
1291
|
ret_val =
|
588
|
-
attributes.get_attribute(
|
1292
|
+
attributes.get_attribute( prefix ? "#{prefix}:#{name}" : name )
|
589
1293
|
|
590
1294
|
return ret_val unless ret_val.nil?
|
591
1295
|
return nil if prefix.nil?
|
@@ -598,29 +1302,46 @@ module REXML
|
|
598
1302
|
|
599
1303
|
end
|
600
1304
|
|
601
|
-
#
|
602
|
-
#
|
1305
|
+
# :call-seq:
|
1306
|
+
# has_attributes? -> true or false
|
1307
|
+
#
|
1308
|
+
# Returns +true+ if the element has attributes, +false+ otherwise:
|
1309
|
+
#
|
1310
|
+
# d = REXML::Document.new('<root><a attr="val"/><b/></root>')
|
1311
|
+
# a, b = *d.root
|
1312
|
+
# a.has_attributes? # => true
|
1313
|
+
# b.has_attributes? # => false
|
1314
|
+
#
|
603
1315
|
def has_attributes?
|
604
1316
|
return !@attributes.empty?
|
605
1317
|
end
|
606
1318
|
|
1319
|
+
# :call-seq:
|
1320
|
+
# add_attribute(name, value) -> value
|
1321
|
+
# add_attribute(attribute) -> attribute
|
1322
|
+
#
|
607
1323
|
# Adds an attribute to this element, overwriting any existing attribute
|
608
1324
|
# by the same name.
|
609
|
-
#
|
610
|
-
#
|
611
|
-
#
|
612
|
-
#
|
613
|
-
#
|
614
|
-
# value
|
615
|
-
#
|
616
|
-
#
|
617
|
-
#
|
618
|
-
#
|
619
|
-
#
|
620
|
-
#
|
621
|
-
#
|
622
|
-
#
|
623
|
-
#
|
1325
|
+
#
|
1326
|
+
# With string argument +name+ and object +value+ are given,
|
1327
|
+
# adds the attribute created with that name and value:
|
1328
|
+
#
|
1329
|
+
# e = REXML::Element.new
|
1330
|
+
# e.add_attribute('attr', 'value') # => "value"
|
1331
|
+
# e['attr'] # => "value"
|
1332
|
+
# e.add_attribute('attr', 'VALUE') # => "VALUE"
|
1333
|
+
# e['attr'] # => "VALUE"
|
1334
|
+
#
|
1335
|
+
# With only attribute object +attribute+ given,
|
1336
|
+
# adds the given attribute:
|
1337
|
+
#
|
1338
|
+
# a = REXML::Attribute.new('attr', 'value')
|
1339
|
+
# e.add_attribute(a) # => attr='value'
|
1340
|
+
# e['attr'] # => "value"
|
1341
|
+
# a = REXML::Attribute.new('attr', 'VALUE')
|
1342
|
+
# e.add_attribute(a) # => attr='VALUE'
|
1343
|
+
# e['attr'] # => "VALUE"
|
1344
|
+
#
|
624
1345
|
def add_attribute( key, value=nil )
|
625
1346
|
if key.kind_of? Attribute
|
626
1347
|
@attributes << key
|
@@ -629,10 +1350,29 @@ module REXML
|
|
629
1350
|
end
|
630
1351
|
end
|
631
1352
|
|
632
|
-
#
|
633
|
-
#
|
634
|
-
#
|
635
|
-
#
|
1353
|
+
# :call-seq:
|
1354
|
+
# add_attributes(hash) -> hash
|
1355
|
+
# add_attributes(array)
|
1356
|
+
#
|
1357
|
+
# Adds zero or more attributes to the element;
|
1358
|
+
# returns the argument.
|
1359
|
+
#
|
1360
|
+
# If hash argument +hash+ is given,
|
1361
|
+
# each key must be a string;
|
1362
|
+
# adds each attribute created with the key/value pair:
|
1363
|
+
#
|
1364
|
+
# e = REXML::Element.new
|
1365
|
+
# h = {'foo' => 'bar', 'baz' => 'bat'}
|
1366
|
+
# e.add_attributes(h)
|
1367
|
+
#
|
1368
|
+
# If argument +array+ is given,
|
1369
|
+
# each array member must be a 2-element array <tt>[name, value];
|
1370
|
+
# each name must be a string:
|
1371
|
+
#
|
1372
|
+
# e = REXML::Element.new
|
1373
|
+
# a = [['foo' => 'bar'], ['baz' => 'bat']]
|
1374
|
+
# e.add_attributes(a)
|
1375
|
+
#
|
636
1376
|
def add_attributes hash
|
637
1377
|
if hash.kind_of? Hash
|
638
1378
|
hash.each_pair {|key, value| @attributes[key] = value }
|
@@ -641,19 +1381,17 @@ module REXML
|
|
641
1381
|
end
|
642
1382
|
end
|
643
1383
|
|
644
|
-
#
|
645
|
-
#
|
646
|
-
#
|
647
|
-
#
|
648
|
-
#
|
649
|
-
#
|
650
|
-
#
|
651
|
-
#
|
652
|
-
#
|
653
|
-
#
|
654
|
-
#
|
655
|
-
# e.delete_attribute( 'name' ) #-> <E sur:name='Russell'/>
|
656
|
-
# e.delete_attribute( r ) #-> <E/>
|
1384
|
+
# :call-seq:
|
1385
|
+
# delete_attribute(name) -> removed_attribute or nil
|
1386
|
+
#
|
1387
|
+
# Removes a named attribute if it exists;
|
1388
|
+
# returns the removed attribute if found, otherwise +nil+:
|
1389
|
+
#
|
1390
|
+
# e = REXML::Element.new('foo')
|
1391
|
+
# e.add_attribute('bar', 'baz')
|
1392
|
+
# e.delete_attribute('bar') # => <bar/>
|
1393
|
+
# e.delete_attribute('bar') # => nil
|
1394
|
+
#
|
657
1395
|
def delete_attribute(key)
|
658
1396
|
attr = @attributes.get_attribute(key)
|
659
1397
|
attr.remove unless attr.nil?
|
@@ -663,26 +1401,80 @@ module REXML
|
|
663
1401
|
# Other Utilities #
|
664
1402
|
#################################################
|
665
1403
|
|
666
|
-
#
|
667
|
-
#
|
1404
|
+
# :call-seq:
|
1405
|
+
# cdatas -> array_of_cdata_children
|
1406
|
+
#
|
1407
|
+
# Returns a frozen array of the REXML::CData children of the element:
|
1408
|
+
#
|
1409
|
+
# xml_string = <<-EOT
|
1410
|
+
# <root>
|
1411
|
+
# <![CDATA[foo]]>
|
1412
|
+
# <![CDATA[bar]]>
|
1413
|
+
# </root>
|
1414
|
+
# EOT
|
1415
|
+
# d = REXML::Document.new(xml_string)
|
1416
|
+
# cds = d.root.cdatas # => ["foo", "bar"]
|
1417
|
+
# cds.frozen? # => true
|
1418
|
+
# cds.map {|cd| cd.class } # => [REXML::CData, REXML::CData]
|
1419
|
+
#
|
668
1420
|
def cdatas
|
669
1421
|
find_all { |child| child.kind_of? CData }.freeze
|
670
1422
|
end
|
671
1423
|
|
672
|
-
#
|
673
|
-
#
|
1424
|
+
# :call-seq:
|
1425
|
+
# comments -> array_of_comment_children
|
1426
|
+
#
|
1427
|
+
# Returns a frozen array of the REXML::Comment children of the element:
|
1428
|
+
#
|
1429
|
+
# xml_string = <<-EOT
|
1430
|
+
# <root>
|
1431
|
+
# <!--foo-->
|
1432
|
+
# <!--bar-->
|
1433
|
+
# </root>
|
1434
|
+
# EOT
|
1435
|
+
# d = REXML::Document.new(xml_string)
|
1436
|
+
# cs = d.root.comments
|
1437
|
+
# cs.frozen? # => true
|
1438
|
+
# cs.map {|c| c.class } # => [REXML::Comment, REXML::Comment]
|
1439
|
+
# cs.map {|c| c.to_s } # => ["foo", "bar"]
|
1440
|
+
#
|
674
1441
|
def comments
|
675
1442
|
find_all { |child| child.kind_of? Comment }.freeze
|
676
1443
|
end
|
677
1444
|
|
678
|
-
#
|
679
|
-
#
|
1445
|
+
# :call-seq:
|
1446
|
+
# instructions -> array_of_instruction_children
|
1447
|
+
#
|
1448
|
+
# Returns a frozen array of the REXML::Instruction children of the element:
|
1449
|
+
#
|
1450
|
+
# xml_string = <<-EOT
|
1451
|
+
# <root>
|
1452
|
+
# <?target0 foo?>
|
1453
|
+
# <?target1 bar?>
|
1454
|
+
# </root>
|
1455
|
+
# EOT
|
1456
|
+
# d = REXML::Document.new(xml_string)
|
1457
|
+
# is = d.root.instructions
|
1458
|
+
# is.frozen? # => true
|
1459
|
+
# is.map {|i| i.class } # => [REXML::Instruction, REXML::Instruction]
|
1460
|
+
# is.map {|i| i.to_s } # => ["<?target0 foo?>", "<?target1 bar?>"]
|
1461
|
+
#
|
680
1462
|
def instructions
|
681
1463
|
find_all { |child| child.kind_of? Instruction }.freeze
|
682
1464
|
end
|
683
1465
|
|
684
|
-
#
|
685
|
-
#
|
1466
|
+
# :call-seq:
|
1467
|
+
# texts -> array_of_text_children
|
1468
|
+
#
|
1469
|
+
# Returns a frozen array of the REXML::Text children of the element:
|
1470
|
+
#
|
1471
|
+
# xml_string = '<root><a/>text<b/>more<c/></root>'
|
1472
|
+
# d = REXML::Document.new(xml_string)
|
1473
|
+
# ts = d.root.texts
|
1474
|
+
# ts.frozen? # => true
|
1475
|
+
# ts.map {|t| t.class } # => [REXML::Text, REXML::Text]
|
1476
|
+
# ts.map {|t| t.to_s } # => ["text", "more"]
|
1477
|
+
#
|
686
1478
|
def texts
|
687
1479
|
find_all { |child| child.kind_of? Text }.freeze
|
688
1480
|
end
|
@@ -758,35 +1550,129 @@ module REXML
|
|
758
1550
|
# XPath search support. You are expected to only encounter this class as
|
759
1551
|
# the <tt>element.elements</tt> object. Therefore, you are
|
760
1552
|
# _not_ expected to instantiate this yourself.
|
1553
|
+
#
|
1554
|
+
# xml_string = <<-EOT
|
1555
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
1556
|
+
# <bookstore>
|
1557
|
+
# <book category="cooking">
|
1558
|
+
# <title lang="en">Everyday Italian</title>
|
1559
|
+
# <author>Giada De Laurentiis</author>
|
1560
|
+
# <year>2005</year>
|
1561
|
+
# <price>30.00</price>
|
1562
|
+
# </book>
|
1563
|
+
# <book category="children">
|
1564
|
+
# <title lang="en">Harry Potter</title>
|
1565
|
+
# <author>J K. Rowling</author>
|
1566
|
+
# <year>2005</year>
|
1567
|
+
# <price>29.99</price>
|
1568
|
+
# </book>
|
1569
|
+
# <book category="web">
|
1570
|
+
# <title lang="en">XQuery Kick Start</title>
|
1571
|
+
# <author>James McGovern</author>
|
1572
|
+
# <author>Per Bothner</author>
|
1573
|
+
# <author>Kurt Cagle</author>
|
1574
|
+
# <author>James Linn</author>
|
1575
|
+
# <author>Vaidyanathan Nagarajan</author>
|
1576
|
+
# <year>2003</year>
|
1577
|
+
# <price>49.99</price>
|
1578
|
+
# </book>
|
1579
|
+
# <book category="web" cover="paperback">
|
1580
|
+
# <title lang="en">Learning XML</title>
|
1581
|
+
# <author>Erik T. Ray</author>
|
1582
|
+
# <year>2003</year>
|
1583
|
+
# <price>39.95</price>
|
1584
|
+
# </book>
|
1585
|
+
# </bookstore>
|
1586
|
+
# EOT
|
1587
|
+
# d = REXML::Document.new(xml_string)
|
1588
|
+
# elements = d.root.elements
|
1589
|
+
# elements # => #<REXML::Elements @element=<bookstore> ... </>>
|
1590
|
+
#
|
761
1591
|
class Elements
|
762
1592
|
include Enumerable
|
763
|
-
#
|
764
|
-
#
|
1593
|
+
# :call-seq:
|
1594
|
+
# new(parent) -> new_elements_object
|
1595
|
+
#
|
1596
|
+
# Returns a new \Elements object with the given +parent+.
|
1597
|
+
# Does _not_ assign <tt>parent.elements = self</tt>:
|
1598
|
+
#
|
1599
|
+
# d = REXML::Document.new(xml_string)
|
1600
|
+
# eles = REXML::Elements.new(d.root)
|
1601
|
+
# eles # => #<REXML::Elements @element=<bookstore> ... </>>
|
1602
|
+
# eles == d.root.elements # => false
|
1603
|
+
#
|
765
1604
|
def initialize parent
|
766
1605
|
@element = parent
|
767
1606
|
end
|
768
1607
|
|
769
|
-
#
|
770
|
-
#
|
771
|
-
#
|
772
|
-
#
|
773
|
-
#
|
774
|
-
#
|
775
|
-
#
|
776
|
-
#
|
777
|
-
#
|
778
|
-
#
|
779
|
-
#
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
#
|
785
|
-
#
|
786
|
-
#
|
787
|
-
#
|
788
|
-
#
|
789
|
-
#
|
1608
|
+
# :call-seq:
|
1609
|
+
# parent
|
1610
|
+
#
|
1611
|
+
# Returns the parent element cited in creating the \Elements object.
|
1612
|
+
# This element is also the default starting point for searching
|
1613
|
+
# in the \Elements object.
|
1614
|
+
#
|
1615
|
+
# d = REXML::Document.new(xml_string)
|
1616
|
+
# elements = REXML::Elements.new(d.root)
|
1617
|
+
# elements.parent == d.root # => true
|
1618
|
+
#
|
1619
|
+
def parent
|
1620
|
+
@element
|
1621
|
+
end
|
1622
|
+
|
1623
|
+
# :call-seq:
|
1624
|
+
# elements[index] -> element or nil
|
1625
|
+
# elements[xpath] -> element or nil
|
1626
|
+
# elements[n, name] -> element or nil
|
1627
|
+
#
|
1628
|
+
# Returns the first \Element object selected by the arguments,
|
1629
|
+
# if any found, or +nil+ if none found.
|
1630
|
+
#
|
1631
|
+
# Notes:
|
1632
|
+
# - The +index+ is 1-based, not 0-based, so that:
|
1633
|
+
# - The first element has index <tt>1</tt>
|
1634
|
+
# - The _nth_ element has index +n+.
|
1635
|
+
# - The selection ignores non-\Element nodes.
|
1636
|
+
#
|
1637
|
+
# When the single argument +index+ is given,
|
1638
|
+
# returns the element given by the index, if any; otherwise, +nil+:
|
1639
|
+
#
|
1640
|
+
# d = REXML::Document.new(xml_string)
|
1641
|
+
# eles = d.root.elements
|
1642
|
+
# eles # => #<REXML::Elements @element=<bookstore> ... </>>
|
1643
|
+
# eles[1] # => <book category='cooking'> ... </>
|
1644
|
+
# eles.size # => 4
|
1645
|
+
# eles[4] # => <book category='web' cover='paperback'> ... </>
|
1646
|
+
# eles[5] # => nil
|
1647
|
+
#
|
1648
|
+
# The node at this index is not an \Element, and so is not returned:
|
1649
|
+
#
|
1650
|
+
# eles = d.root.first.first # => <title lang='en'> ... </>
|
1651
|
+
# eles.to_a # => ["Everyday Italian"]
|
1652
|
+
# eles[1] # => nil
|
1653
|
+
#
|
1654
|
+
# When the single argument +xpath+ is given,
|
1655
|
+
# returns the first element found via that +xpath+, if any; otherwise, +nil+:
|
1656
|
+
#
|
1657
|
+
# eles = d.root.elements # => #<REXML::Elements @element=<bookstore> ... </>>
|
1658
|
+
# eles['/bookstore'] # => <bookstore> ... </>
|
1659
|
+
# eles['//book'] # => <book category='cooking'> ... </>
|
1660
|
+
# eles['//book [@category="children"]'] # => <book category='children'> ... </>
|
1661
|
+
# eles['/nosuch'] # => nil
|
1662
|
+
# eles['//nosuch'] # => nil
|
1663
|
+
# eles['//book [@category="nosuch"]'] # => nil
|
1664
|
+
# eles['.'] # => <bookstore> ... </>
|
1665
|
+
# eles['..'].class # => REXML::Document
|
1666
|
+
#
|
1667
|
+
# With arguments +n+ and +name+ given,
|
1668
|
+
# returns the _nth_ found element that has the given +name+,
|
1669
|
+
# or +nil+ if there is no such _nth_ element:
|
1670
|
+
#
|
1671
|
+
# eles = d.root.elements # => #<REXML::Elements @element=<bookstore> ... </>>
|
1672
|
+
# eles[1, 'book'] # => <book category='cooking'> ... </>
|
1673
|
+
# eles[4, 'book'] # => <book category='web' cover='paperback'> ... </>
|
1674
|
+
# eles[5, 'book'] # => nil
|
1675
|
+
#
|
790
1676
|
def []( index, name=nil)
|
791
1677
|
if index.kind_of? Integer
|
792
1678
|
raise "index (#{index}) must be >= 1" if index < 1
|
@@ -806,19 +1692,42 @@ module REXML
|
|
806
1692
|
end
|
807
1693
|
end
|
808
1694
|
|
809
|
-
#
|
810
|
-
#
|
811
|
-
#
|
812
|
-
# element
|
813
|
-
#
|
814
|
-
#
|
815
|
-
#
|
1695
|
+
# :call-seq:
|
1696
|
+
# elements[] = index, replacement_element -> replacement_element or nil
|
1697
|
+
#
|
1698
|
+
# Replaces or adds an element.
|
1699
|
+
#
|
1700
|
+
# When <tt>eles[index]</tt> exists, replaces it with +replacement_element+
|
1701
|
+
# and returns +replacement_element+:
|
1702
|
+
#
|
1703
|
+
# d = REXML::Document.new(xml_string)
|
1704
|
+
# eles = d.root.elements # => #<REXML::Elements @element=<bookstore> ... </>>
|
1705
|
+
# eles[1] # => <book category='cooking'> ... </>
|
1706
|
+
# eles[1] = REXML::Element.new('foo')
|
1707
|
+
# eles[1] # => <foo/>
|
1708
|
+
#
|
1709
|
+
# Does nothing (or raises an exception)
|
1710
|
+
# if +replacement_element+ is not an \Element:
|
1711
|
+
# eles[2] # => <book category='web' cover='paperback'> ... </>
|
1712
|
+
# eles[2] = REXML::Text.new('bar')
|
1713
|
+
# eles[2] # => <book category='web' cover='paperback'> ... </>
|
1714
|
+
#
|
1715
|
+
# When <tt>eles[index]</tt> does not exist,
|
1716
|
+
# adds +replacement_element+ to the element and returns
|
1717
|
+
#
|
1718
|
+
# d = REXML::Document.new(xml_string)
|
1719
|
+
# eles = d.root.elements # => #<REXML::Elements @element=<bookstore> ... </>>
|
1720
|
+
# eles.size # => 4
|
1721
|
+
# eles[50] = REXML::Element.new('foo') # => <foo/>
|
1722
|
+
# eles.size # => 5
|
1723
|
+
# eles[5] # => <foo/>
|
1724
|
+
#
|
1725
|
+
# Does nothing (or raises an exception)
|
1726
|
+
# if +replacement_element+ is not an \Element:
|
1727
|
+
#
|
1728
|
+
# eles[50] = REXML::Text.new('bar') # => "bar"
|
1729
|
+
# eles.size # => 5
|
816
1730
|
#
|
817
|
-
# doc = Document.new '<a/>'
|
818
|
-
# doc.root.elements[10] = Element.new('b') #-> <a><b/></a>
|
819
|
-
# doc.root.elements[1] #-> <b/>
|
820
|
-
# doc.root.elements[1] = Element.new('c') #-> <a><c/></a>
|
821
|
-
# doc.root.elements['c'] = Element.new('d') #-> <a><d/></a>
|
822
1731
|
def []=( index, element )
|
823
1732
|
previous = self[index]
|
824
1733
|
if previous.nil?
|
@@ -829,14 +1738,34 @@ module REXML
|
|
829
1738
|
return previous
|
830
1739
|
end
|
831
1740
|
|
832
|
-
#
|
1741
|
+
# :call-seq:
|
1742
|
+
# empty? -> true or false
|
1743
|
+
#
|
1744
|
+
# Returns +true+ if there are no children, +false+ otherwise.
|
1745
|
+
#
|
1746
|
+
# d = REXML::Document.new('')
|
1747
|
+
# d.elements.empty? # => true
|
1748
|
+
# d = REXML::Document.new(xml_string)
|
1749
|
+
# d.elements.empty? # => false
|
1750
|
+
#
|
833
1751
|
def empty?
|
834
1752
|
@element.find{ |child| child.kind_of? Element}.nil?
|
835
1753
|
end
|
836
1754
|
|
837
|
-
#
|
838
|
-
#
|
839
|
-
#
|
1755
|
+
# :call-seq:
|
1756
|
+
# index(element)
|
1757
|
+
#
|
1758
|
+
# Returns the 1-based index of the given +element+, if found;
|
1759
|
+
# otherwise, returns -1:
|
1760
|
+
#
|
1761
|
+
# d = REXML::Document.new(xml_string)
|
1762
|
+
# elements = d.root.elements
|
1763
|
+
# ele_1, ele_2, ele_3, ele_4 = *elements
|
1764
|
+
# elements.index(ele_4) # => 4
|
1765
|
+
# elements.delete(ele_3)
|
1766
|
+
# elements.index(ele_4) # => 3
|
1767
|
+
# elements.index(ele_3) # => -1
|
1768
|
+
#
|
840
1769
|
def index element
|
841
1770
|
rv = 0
|
842
1771
|
found = @element.find do |child|
|
@@ -848,17 +1777,47 @@ module REXML
|
|
848
1777
|
return -1
|
849
1778
|
end
|
850
1779
|
|
851
|
-
#
|
852
|
-
#
|
853
|
-
#
|
854
|
-
# xpath
|
855
|
-
#
|
856
|
-
#
|
857
|
-
#
|
858
|
-
#
|
859
|
-
#
|
860
|
-
#
|
861
|
-
#
|
1780
|
+
# :call-seq:
|
1781
|
+
# delete(index) -> removed_element or nil
|
1782
|
+
# delete(element) -> removed_element or nil
|
1783
|
+
# delete(xpath) -> removed_element or nil
|
1784
|
+
#
|
1785
|
+
# Removes an element; returns the removed element, or +nil+ if none removed.
|
1786
|
+
#
|
1787
|
+
# With integer argument +index+ given,
|
1788
|
+
# removes the child element at that offset:
|
1789
|
+
#
|
1790
|
+
# d = REXML::Document.new(xml_string)
|
1791
|
+
# elements = d.root.elements
|
1792
|
+
# elements.size # => 4
|
1793
|
+
# elements[2] # => <book category='children'> ... </>
|
1794
|
+
# elements.delete(2) # => <book category='children'> ... </>
|
1795
|
+
# elements.size # => 3
|
1796
|
+
# elements[2] # => <book category='web'> ... </>
|
1797
|
+
# elements.delete(50) # => nil
|
1798
|
+
#
|
1799
|
+
# With element argument +element+ given,
|
1800
|
+
# removes that child element:
|
1801
|
+
#
|
1802
|
+
# d = REXML::Document.new(xml_string)
|
1803
|
+
# elements = d.root.elements
|
1804
|
+
# ele_1, ele_2, ele_3, ele_4 = *elements
|
1805
|
+
# elements.size # => 4
|
1806
|
+
# elements[2] # => <book category='children'> ... </>
|
1807
|
+
# elements.delete(ele_2) # => <book category='children'> ... </>
|
1808
|
+
# elements.size # => 3
|
1809
|
+
# elements[2] # => <book category='web'> ... </>
|
1810
|
+
# elements.delete(ele_2) # => nil
|
1811
|
+
#
|
1812
|
+
# With string argument +xpath+ given,
|
1813
|
+
# removes the first element found via that xpath:
|
1814
|
+
#
|
1815
|
+
# d = REXML::Document.new(xml_string)
|
1816
|
+
# elements = d.root.elements
|
1817
|
+
# elements.delete('//book') # => <book category='cooking'> ... </>
|
1818
|
+
# elements.delete('//book [@category="children"]') # => <book category='children'> ... </>
|
1819
|
+
# elements.delete('//nosuch') # => nil
|
1820
|
+
#
|
862
1821
|
def delete element
|
863
1822
|
if element.kind_of? Element
|
864
1823
|
@element.delete element
|
@@ -868,12 +1827,23 @@ module REXML
|
|
868
1827
|
end
|
869
1828
|
end
|
870
1829
|
|
871
|
-
#
|
872
|
-
#
|
873
|
-
#
|
874
|
-
#
|
875
|
-
#
|
876
|
-
#
|
1830
|
+
# :call-seq:
|
1831
|
+
# delete_all(xpath)
|
1832
|
+
#
|
1833
|
+
# Removes all elements found via the given +xpath+;
|
1834
|
+
# returns the array of removed elements, if any, else +nil+.
|
1835
|
+
#
|
1836
|
+
# d = REXML::Document.new(xml_string)
|
1837
|
+
# elements = d.root.elements
|
1838
|
+
# elements.size # => 4
|
1839
|
+
# deleted_elements = elements.delete_all('//book [@category="web"]')
|
1840
|
+
# deleted_elements.size # => 2
|
1841
|
+
# elements.size # => 2
|
1842
|
+
# deleted_elements = elements.delete_all('//book')
|
1843
|
+
# deleted_elements.size # => 2
|
1844
|
+
# elements.size # => 0
|
1845
|
+
# elements.delete_all('//book') # => []
|
1846
|
+
#
|
877
1847
|
def delete_all( xpath )
|
878
1848
|
rv = []
|
879
1849
|
XPath::each( @element, xpath) {|element|
|
@@ -886,15 +1856,68 @@ module REXML
|
|
886
1856
|
return rv
|
887
1857
|
end
|
888
1858
|
|
889
|
-
#
|
890
|
-
#
|
891
|
-
#
|
892
|
-
#
|
893
|
-
#
|
894
|
-
#
|
895
|
-
#
|
896
|
-
#
|
897
|
-
#
|
1859
|
+
# :call-seq:
|
1860
|
+
# add -> new_element
|
1861
|
+
# add(name) -> new_element
|
1862
|
+
# add(element) -> element
|
1863
|
+
#
|
1864
|
+
# Adds an element; returns the element added.
|
1865
|
+
#
|
1866
|
+
# With no argument, creates and adds a new element.
|
1867
|
+
# The new element has:
|
1868
|
+
#
|
1869
|
+
# - No name.
|
1870
|
+
# - \Parent from the \Elements object.
|
1871
|
+
# - Context from the that parent.
|
1872
|
+
#
|
1873
|
+
# Example:
|
1874
|
+
#
|
1875
|
+
# d = REXML::Document.new(xml_string)
|
1876
|
+
# elements = d.root.elements
|
1877
|
+
# parent = elements.parent # => <bookstore> ... </>
|
1878
|
+
# parent.context = {raw: :all}
|
1879
|
+
# elements.size # => 4
|
1880
|
+
# new_element = elements.add # => </>
|
1881
|
+
# elements.size # => 5
|
1882
|
+
# new_element.name # => nil
|
1883
|
+
# new_element.parent # => <bookstore> ... </>
|
1884
|
+
# new_element.context # => {:raw=>:all}
|
1885
|
+
#
|
1886
|
+
# With string argument +name+, creates and adds a new element.
|
1887
|
+
# The new element has:
|
1888
|
+
#
|
1889
|
+
# - Name +name+.
|
1890
|
+
# - \Parent from the \Elements object.
|
1891
|
+
# - Context from the that parent.
|
1892
|
+
#
|
1893
|
+
# Example:
|
1894
|
+
#
|
1895
|
+
# d = REXML::Document.new(xml_string)
|
1896
|
+
# elements = d.root.elements
|
1897
|
+
# parent = elements.parent # => <bookstore> ... </>
|
1898
|
+
# parent.context = {raw: :all}
|
1899
|
+
# elements.size # => 4
|
1900
|
+
# new_element = elements.add('foo') # => <foo/>
|
1901
|
+
# elements.size # => 5
|
1902
|
+
# new_element.name # => "foo"
|
1903
|
+
# new_element.parent # => <bookstore> ... </>
|
1904
|
+
# new_element.context # => {:raw=>:all}
|
1905
|
+
#
|
1906
|
+
# With argument +element+,
|
1907
|
+
# creates and adds a clone of the given +element+.
|
1908
|
+
# The new element has name, parent, and context from the given +element+.
|
1909
|
+
#
|
1910
|
+
# d = REXML::Document.new(xml_string)
|
1911
|
+
# elements = d.root.elements
|
1912
|
+
# elements.size # => 4
|
1913
|
+
# e0 = REXML::Element.new('foo')
|
1914
|
+
# e1 = REXML::Element.new('bar', e0, {raw: :all})
|
1915
|
+
# element = elements.add(e1) # => <bar/>
|
1916
|
+
# elements.size # => 5
|
1917
|
+
# element.name # => "bar"
|
1918
|
+
# element.parent # => <bookstore> ... </>
|
1919
|
+
# element.context # => {:raw=>:all}
|
1920
|
+
#
|
898
1921
|
def add element=nil
|
899
1922
|
if element.nil?
|
900
1923
|
Element.new("", self, @element.context)
|
@@ -909,24 +1932,55 @@ module REXML
|
|
909
1932
|
|
910
1933
|
alias :<< :add
|
911
1934
|
|
912
|
-
#
|
913
|
-
#
|
914
|
-
#
|
915
|
-
#
|
916
|
-
#
|
917
|
-
#
|
918
|
-
#
|
919
|
-
#
|
920
|
-
#
|
921
|
-
#
|
922
|
-
#
|
923
|
-
#
|
924
|
-
#
|
925
|
-
#
|
1935
|
+
# :call-seq:
|
1936
|
+
# each(xpath = nil) {|element| ... } -> self
|
1937
|
+
#
|
1938
|
+
# Iterates over the elements.
|
1939
|
+
#
|
1940
|
+
# With no argument, calls the block with each element:
|
1941
|
+
#
|
1942
|
+
# d = REXML::Document.new(xml_string)
|
1943
|
+
# elements = d.root.elements
|
1944
|
+
# elements.each {|element| p element }
|
1945
|
+
#
|
1946
|
+
# Output:
|
1947
|
+
#
|
1948
|
+
# <book category='cooking'> ... </>
|
1949
|
+
# <book category='children'> ... </>
|
1950
|
+
# <book category='web'> ... </>
|
1951
|
+
# <book category='web' cover='paperback'> ... </>
|
1952
|
+
#
|
1953
|
+
# With argument +xpath+, calls the block with each element
|
1954
|
+
# that matches the given +xpath+:
|
1955
|
+
#
|
1956
|
+
# elements.each('//book [@category="web"]') {|element| p element }
|
1957
|
+
#
|
1958
|
+
# Output:
|
1959
|
+
#
|
1960
|
+
# <book category='web'> ... </>
|
1961
|
+
# <book category='web' cover='paperback'> ... </>
|
1962
|
+
#
|
926
1963
|
def each( xpath=nil )
|
927
1964
|
XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element }
|
928
1965
|
end
|
929
1966
|
|
1967
|
+
# :call-seq:
|
1968
|
+
# collect(xpath = nil) {|element| ... } -> array
|
1969
|
+
#
|
1970
|
+
# Iterates over the elements; returns the array of block return values.
|
1971
|
+
#
|
1972
|
+
# With no argument, iterates over all elements:
|
1973
|
+
#
|
1974
|
+
# d = REXML::Document.new(xml_string)
|
1975
|
+
# elements = d.root.elements
|
1976
|
+
# elements.collect {|element| element.size } # => [9, 9, 17, 9]
|
1977
|
+
#
|
1978
|
+
# With argument +xpath+, iterates over elements that match
|
1979
|
+
# the given +xpath+:
|
1980
|
+
#
|
1981
|
+
# xpath = '//book [@category="web"]'
|
1982
|
+
# elements.collect(xpath) {|element| element.size } # => [17, 9]
|
1983
|
+
#
|
930
1984
|
def collect( xpath=nil )
|
931
1985
|
collection = []
|
932
1986
|
XPath::each( @element, xpath ) {|e|
|
@@ -935,6 +1989,83 @@ module REXML
|
|
935
1989
|
collection
|
936
1990
|
end
|
937
1991
|
|
1992
|
+
# :call-seq:
|
1993
|
+
# inject(xpath = nil, initial = nil) -> object
|
1994
|
+
#
|
1995
|
+
# Calls the block with elements; returns the last block return value.
|
1996
|
+
#
|
1997
|
+
# With no argument, iterates over the elements, calling the block
|
1998
|
+
# <tt>elements.size - 1</tt> times.
|
1999
|
+
#
|
2000
|
+
# - The first call passes the first and second elements.
|
2001
|
+
# - The second call passes the first block return value and the third element.
|
2002
|
+
# - The third call passes the second block return value and the fourth element.
|
2003
|
+
# - And so on.
|
2004
|
+
#
|
2005
|
+
# In this example, the block returns the passed element,
|
2006
|
+
# which is then the object argument to the next call:
|
2007
|
+
#
|
2008
|
+
# d = REXML::Document.new(xml_string)
|
2009
|
+
# elements = d.root.elements
|
2010
|
+
# elements.inject do |object, element|
|
2011
|
+
# p [elements.index(object), elements.index(element)]
|
2012
|
+
# element
|
2013
|
+
# end
|
2014
|
+
#
|
2015
|
+
# Output:
|
2016
|
+
#
|
2017
|
+
# [1, 2]
|
2018
|
+
# [2, 3]
|
2019
|
+
# [3, 4]
|
2020
|
+
#
|
2021
|
+
# With the single argument +xpath+, calls the block only with
|
2022
|
+
# elements matching that xpath:
|
2023
|
+
#
|
2024
|
+
# elements.inject('//book [@category="web"]') do |object, element|
|
2025
|
+
# p [elements.index(object), elements.index(element)]
|
2026
|
+
# element
|
2027
|
+
# end
|
2028
|
+
#
|
2029
|
+
# Output:
|
2030
|
+
#
|
2031
|
+
# [3, 4]
|
2032
|
+
#
|
2033
|
+
# With argument +xpath+ given as +nil+
|
2034
|
+
# and argument +initial+ also given,
|
2035
|
+
# calls the block once for each element.
|
2036
|
+
#
|
2037
|
+
# - The first call passes the +initial+ and the first element.
|
2038
|
+
# - The second call passes the first block return value and the second element.
|
2039
|
+
# - The third call passes the second block return value and the third element.
|
2040
|
+
# - And so on.
|
2041
|
+
#
|
2042
|
+
# In this example, the first object index is <tt>-1</tt>
|
2043
|
+
#
|
2044
|
+
# elements.inject(nil, 'Initial') do |object, element|
|
2045
|
+
# p [elements.index(object), elements.index(element)]
|
2046
|
+
# element
|
2047
|
+
# end
|
2048
|
+
#
|
2049
|
+
# Output:
|
2050
|
+
#
|
2051
|
+
# [-1, 1]
|
2052
|
+
# [1, 2]
|
2053
|
+
# [2, 3]
|
2054
|
+
# [3, 4]
|
2055
|
+
#
|
2056
|
+
# In this form the passed object can be used as an accumulator:
|
2057
|
+
#
|
2058
|
+
# elements.inject(nil, 0) do |total, element|
|
2059
|
+
# total += element.size
|
2060
|
+
# end # => 44
|
2061
|
+
#
|
2062
|
+
# With both arguments +xpath+ and +initial+ are given,
|
2063
|
+
# calls the block only with elements matching that xpath:
|
2064
|
+
#
|
2065
|
+
# elements.inject('//book [@category="web"]', 0) do |total, element|
|
2066
|
+
# total += element.size
|
2067
|
+
# end # => 26
|
2068
|
+
#
|
938
2069
|
def inject( xpath=nil, initial=nil )
|
939
2070
|
first = true
|
940
2071
|
XPath::each( @element, xpath ) {|e|
|
@@ -950,23 +2081,39 @@ module REXML
|
|
950
2081
|
initial
|
951
2082
|
end
|
952
2083
|
|
953
|
-
#
|
954
|
-
#
|
955
|
-
#
|
956
|
-
#
|
2084
|
+
# :call-seq:
|
2085
|
+
# size -> integer
|
2086
|
+
#
|
2087
|
+
# Returns the count of \Element children:
|
2088
|
+
#
|
2089
|
+
# d = REXML::Document.new '<a>sean<b/>elliott<b/>russell<b/></a>'
|
2090
|
+
# d.root.elements.size # => 3 # Three elements.
|
2091
|
+
# d.root.size # => 6 # Three elements plus three text nodes..
|
2092
|
+
#
|
957
2093
|
def size
|
958
2094
|
count = 0
|
959
2095
|
@element.each {|child| count+=1 if child.kind_of? Element }
|
960
2096
|
count
|
961
2097
|
end
|
962
2098
|
|
963
|
-
#
|
964
|
-
#
|
965
|
-
#
|
966
|
-
#
|
967
|
-
#
|
968
|
-
#
|
969
|
-
#
|
2099
|
+
# :call-seq:
|
2100
|
+
# to_a(xpath = nil) -> array_of_elements
|
2101
|
+
#
|
2102
|
+
# Returns an array of element children (not including non-element children).
|
2103
|
+
#
|
2104
|
+
# With no argument, returns an array of all element children:
|
2105
|
+
#
|
2106
|
+
# d = REXML::Document.new '<a>sean<b/>elliott<c/></a>'
|
2107
|
+
# elements = d.root.elements
|
2108
|
+
# elements.to_a # => [<b/>, <c/>] # Omits non-element children.
|
2109
|
+
# children = d.root.children
|
2110
|
+
# children # => ["sean", <b/>, "elliott", <c/>] # Includes non-element children.
|
2111
|
+
#
|
2112
|
+
# With argument +xpath+, returns an array of element children
|
2113
|
+
# that match the xpath:
|
2114
|
+
#
|
2115
|
+
# elements.to_a('//c') # => [<c/>]
|
2116
|
+
#
|
970
2117
|
def to_a( xpath=nil )
|
971
2118
|
rv = XPath.match( @element, xpath )
|
972
2119
|
return rv.find_all{|e| e.kind_of? Element} if xpath
|
@@ -988,36 +2135,89 @@ module REXML
|
|
988
2135
|
# A class that defines the set of Attributes of an Element and provides
|
989
2136
|
# operations for accessing elements in that set.
|
990
2137
|
class Attributes < Hash
|
991
|
-
|
992
|
-
#
|
2138
|
+
|
2139
|
+
# :call-seq:
|
2140
|
+
# new(element)
|
2141
|
+
#
|
2142
|
+
# Creates and returns a new \REXML::Attributes object.
|
2143
|
+
# The element given by argument +element+ is stored,
|
2144
|
+
# but its own attributes are not modified:
|
2145
|
+
#
|
2146
|
+
# ele = REXML::Element.new('foo')
|
2147
|
+
# attrs = REXML::Attributes.new(ele)
|
2148
|
+
# attrs.object_id == ele.attributes.object_id # => false
|
2149
|
+
#
|
2150
|
+
# Other instance methods in class \REXML::Attributes may refer to:
|
2151
|
+
#
|
2152
|
+
# - +element.document+.
|
2153
|
+
# - +element.prefix+.
|
2154
|
+
# - +element.expanded_name+.
|
2155
|
+
#
|
993
2156
|
def initialize element
|
994
2157
|
@element = element
|
995
2158
|
end
|
996
2159
|
|
997
|
-
#
|
998
|
-
#
|
999
|
-
#
|
1000
|
-
# Returns
|
1001
|
-
#
|
1002
|
-
#
|
1003
|
-
#
|
2160
|
+
# :call-seq:
|
2161
|
+
# [name] -> attribute_value or nil
|
2162
|
+
#
|
2163
|
+
# Returns the value for the attribute given by +name+,
|
2164
|
+
# if it exists; otherwise +nil+.
|
2165
|
+
# The value returned is the unnormalized attribute value,
|
2166
|
+
# with entities expanded:
|
2167
|
+
#
|
2168
|
+
# xml_string = <<-EOT
|
2169
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2170
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2171
|
+
# </root>
|
2172
|
+
# EOT
|
2173
|
+
# d = REXML::Document.new(xml_string)
|
2174
|
+
# ele = d.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2175
|
+
# ele.attributes['att'] # => "<"
|
2176
|
+
# ele.attributes['bar:att'] # => "2"
|
2177
|
+
# ele.attributes['nosuch'] # => nil
|
2178
|
+
#
|
2179
|
+
# Related: get_attribute (returns an \Attribute object).
|
1004
2180
|
#
|
1005
|
-
# doc = Document.new "<a foo:att='1' bar:att='2' att='<'/>"
|
1006
|
-
# doc.root.attributes['att'] #-> '<'
|
1007
|
-
# doc.root.attributes['bar:att'] #-> '2'
|
1008
2181
|
def [](name)
|
1009
2182
|
attr = get_attribute(name)
|
1010
2183
|
return attr.value unless attr.nil?
|
1011
2184
|
return nil
|
1012
2185
|
end
|
1013
2186
|
|
2187
|
+
# :call-seq:
|
2188
|
+
# to_a -> array_of_attribute_objects
|
2189
|
+
#
|
2190
|
+
# Returns an array of \REXML::Attribute objects representing
|
2191
|
+
# the attributes:
|
2192
|
+
#
|
2193
|
+
# xml_string = <<-EOT
|
2194
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2195
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2196
|
+
# </root>
|
2197
|
+
# EOT
|
2198
|
+
# d = REXML::Document.new(xml_string)
|
2199
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2200
|
+
# attrs = ele.attributes.to_a # => [foo:att='1', bar:att='2', att='<']
|
2201
|
+
# attrs.first.class # => REXML::Attribute
|
2202
|
+
#
|
1014
2203
|
def to_a
|
1015
2204
|
enum_for(:each_attribute).to_a
|
1016
2205
|
end
|
1017
2206
|
|
1018
|
-
#
|
1019
|
-
#
|
1020
|
-
#
|
2207
|
+
# :call-seq:
|
2208
|
+
# length
|
2209
|
+
#
|
2210
|
+
# Returns the count of attributes:
|
2211
|
+
#
|
2212
|
+
# xml_string = <<-EOT
|
2213
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2214
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2215
|
+
# </root>
|
2216
|
+
# EOT
|
2217
|
+
# d = REXML::Document.new(xml_string)
|
2218
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2219
|
+
# ele.attributes.length # => 3
|
2220
|
+
#
|
1021
2221
|
def length
|
1022
2222
|
c = 0
|
1023
2223
|
each_attribute { c+=1 }
|
@@ -1025,13 +2225,28 @@ module REXML
|
|
1025
2225
|
end
|
1026
2226
|
alias :size :length
|
1027
2227
|
|
1028
|
-
#
|
1029
|
-
#
|
2228
|
+
# :call-seq:
|
2229
|
+
# each_attribute {|attr| ... }
|
2230
|
+
#
|
2231
|
+
# Calls the given block with each \REXML::Attribute object:
|
2232
|
+
#
|
2233
|
+
# xml_string = <<-EOT
|
2234
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2235
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2236
|
+
# </root>
|
2237
|
+
# EOT
|
2238
|
+
# d = REXML::Document.new(xml_string)
|
2239
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2240
|
+
# ele.attributes.each_attribute do |attr|
|
2241
|
+
# p [attr.class, attr]
|
2242
|
+
# end
|
2243
|
+
#
|
2244
|
+
# Output:
|
2245
|
+
#
|
2246
|
+
# [REXML::Attribute, foo:att='1']
|
2247
|
+
# [REXML::Attribute, bar:att='2']
|
2248
|
+
# [REXML::Attribute, att='<']
|
1030
2249
|
#
|
1031
|
-
# doc = Document.new '<a x="1" y="2"/>'
|
1032
|
-
# doc.root.attributes.each_attribute {|attr|
|
1033
|
-
# p attr.expanded_name+" => "+attr.value
|
1034
|
-
# }
|
1035
2250
|
def each_attribute # :yields: attribute
|
1036
2251
|
return to_enum(__method__) unless block_given?
|
1037
2252
|
each_value do |val|
|
@@ -1043,11 +2258,28 @@ module REXML
|
|
1043
2258
|
end
|
1044
2259
|
end
|
1045
2260
|
|
1046
|
-
#
|
1047
|
-
#
|
2261
|
+
# :call-seq:
|
2262
|
+
# each {|expanded_name, value| ... }
|
2263
|
+
#
|
2264
|
+
# Calls the given block with each expanded-name/value pair:
|
2265
|
+
#
|
2266
|
+
# xml_string = <<-EOT
|
2267
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2268
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2269
|
+
# </root>
|
2270
|
+
# EOT
|
2271
|
+
# d = REXML::Document.new(xml_string)
|
2272
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2273
|
+
# ele.attributes.each do |expanded_name, value|
|
2274
|
+
# p [expanded_name, value]
|
2275
|
+
# end
|
2276
|
+
#
|
2277
|
+
# Output:
|
2278
|
+
#
|
2279
|
+
# ["foo:att", "1"]
|
2280
|
+
# ["bar:att", "2"]
|
2281
|
+
# ["att", "<"]
|
1048
2282
|
#
|
1049
|
-
# doc = Document.new '<a x="1" y="2"/>'
|
1050
|
-
# doc.root.attributes.each {|name, value| p name+" => "+value }
|
1051
2283
|
def each
|
1052
2284
|
return to_enum(__method__) unless block_given?
|
1053
2285
|
each_attribute do |attr|
|
@@ -1055,15 +2287,25 @@ module REXML
|
|
1055
2287
|
end
|
1056
2288
|
end
|
1057
2289
|
|
1058
|
-
#
|
1059
|
-
#
|
1060
|
-
#
|
1061
|
-
#
|
1062
|
-
#
|
1063
|
-
#
|
1064
|
-
#
|
1065
|
-
#
|
1066
|
-
#
|
2290
|
+
# :call-seq:
|
2291
|
+
# get_attribute(name) -> attribute_object or nil
|
2292
|
+
#
|
2293
|
+
# Returns the \REXML::Attribute object for the given +name+:
|
2294
|
+
#
|
2295
|
+
# xml_string = <<-EOT
|
2296
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2297
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2298
|
+
# </root>
|
2299
|
+
# EOT
|
2300
|
+
# d = REXML::Document.new(xml_string)
|
2301
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2302
|
+
# attrs = ele.attributes
|
2303
|
+
# attrs.get_attribute('foo:att') # => foo:att='1'
|
2304
|
+
# attrs.get_attribute('foo:att').class # => REXML::Attribute
|
2305
|
+
# attrs.get_attribute('bar:att') # => bar:att='2'
|
2306
|
+
# attrs.get_attribute('att') # => att='<'
|
2307
|
+
# attrs.get_attribute('nosuch') # => nil
|
2308
|
+
#
|
1067
2309
|
def get_attribute( name )
|
1068
2310
|
attr = fetch( name, nil )
|
1069
2311
|
if attr.nil?
|
@@ -1097,18 +2339,29 @@ module REXML
|
|
1097
2339
|
return attr
|
1098
2340
|
end
|
1099
2341
|
|
1100
|
-
#
|
1101
|
-
#
|
1102
|
-
#
|
1103
|
-
# value
|
1104
|
-
#
|
1105
|
-
#
|
1106
|
-
#
|
1107
|
-
#
|
1108
|
-
#
|
1109
|
-
#
|
1110
|
-
#
|
1111
|
-
#
|
2342
|
+
# :call-seq:
|
2343
|
+
# [name] = value -> value
|
2344
|
+
#
|
2345
|
+
# When +value+ is non-+nil+,
|
2346
|
+
# assigns that to the attribute for the given +name+,
|
2347
|
+
# overwriting the previous value if it exists:
|
2348
|
+
#
|
2349
|
+
# xml_string = <<-EOT
|
2350
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2351
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2352
|
+
# </root>
|
2353
|
+
# EOT
|
2354
|
+
# d = REXML::Document.new(xml_string)
|
2355
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2356
|
+
# attrs = ele.attributes
|
2357
|
+
# attrs['foo:att'] = '2' # => "2"
|
2358
|
+
# attrs['baz:att'] = '3' # => "3"
|
2359
|
+
#
|
2360
|
+
# When +value+ is +nil+, deletes the attribute if it exists:
|
2361
|
+
#
|
2362
|
+
# attrs['baz:att'] = nil
|
2363
|
+
# attrs.include?('baz:att') # => false
|
2364
|
+
#
|
1112
2365
|
def []=( name, value )
|
1113
2366
|
if value.nil? # Delete the named attribute
|
1114
2367
|
attr = get_attribute(name)
|
@@ -1131,17 +2384,6 @@ module REXML
|
|
1131
2384
|
elsif old_attr.kind_of? Hash
|
1132
2385
|
old_attr[value.prefix] = value
|
1133
2386
|
elsif old_attr.prefix != value.prefix
|
1134
|
-
# Check for conflicting namespaces
|
1135
|
-
if value.prefix != "xmlns" and old_attr.prefix != "xmlns"
|
1136
|
-
old_namespace = old_attr.namespace
|
1137
|
-
new_namespace = value.namespace
|
1138
|
-
if old_namespace == new_namespace
|
1139
|
-
raise ParseException.new(
|
1140
|
-
"Namespace conflict in adding attribute \"#{value.name}\": "+
|
1141
|
-
"Prefix \"#{old_attr.prefix}\" = \"#{old_namespace}\" and "+
|
1142
|
-
"prefix \"#{value.prefix}\" = \"#{new_namespace}\"")
|
1143
|
-
end
|
1144
|
-
end
|
1145
2387
|
store value.name, {old_attr.prefix => old_attr,
|
1146
2388
|
value.prefix => value}
|
1147
2389
|
else
|
@@ -1150,12 +2392,17 @@ module REXML
|
|
1150
2392
|
return @element
|
1151
2393
|
end
|
1152
2394
|
|
1153
|
-
#
|
1154
|
-
#
|
2395
|
+
# :call-seq:
|
2396
|
+
# prefixes -> array_of_prefix_strings
|
2397
|
+
#
|
2398
|
+
# Returns an array of prefix strings in the attributes.
|
2399
|
+
# The array does not include the default
|
1155
2400
|
# namespace declaration, if one exists.
|
1156
|
-
#
|
1157
|
-
#
|
1158
|
-
#
|
2401
|
+
#
|
2402
|
+
# xml_string = '<a xmlns="foo" xmlns:x="bar" xmlns:y="twee" z="glorp"/>'
|
2403
|
+
# d = REXML::Document.new(xml_string)
|
2404
|
+
# d.root.attributes.prefixes # => ["x", "y"]
|
2405
|
+
#
|
1159
2406
|
def prefixes
|
1160
2407
|
ns = []
|
1161
2408
|
each_attribute do |attribute|
|
@@ -1172,6 +2419,15 @@ module REXML
|
|
1172
2419
|
ns
|
1173
2420
|
end
|
1174
2421
|
|
2422
|
+
# :call-seq:
|
2423
|
+
# namespaces
|
2424
|
+
#
|
2425
|
+
# Returns a hash of name/value pairs for the namespaces:
|
2426
|
+
#
|
2427
|
+
# xml_string = '<a xmlns="foo" xmlns:x="bar" xmlns:y="twee" z="glorp"/>'
|
2428
|
+
# d = REXML::Document.new(xml_string)
|
2429
|
+
# d.root.attributes.namespaces # => {"xmlns"=>"foo", "x"=>"bar", "y"=>"twee"}
|
2430
|
+
#
|
1175
2431
|
def namespaces
|
1176
2432
|
namespaces = {}
|
1177
2433
|
each_attribute do |attribute|
|
@@ -1188,16 +2444,34 @@ module REXML
|
|
1188
2444
|
namespaces
|
1189
2445
|
end
|
1190
2446
|
|
1191
|
-
#
|
1192
|
-
#
|
1193
|
-
#
|
1194
|
-
#
|
1195
|
-
#
|
1196
|
-
#
|
1197
|
-
#
|
1198
|
-
#
|
1199
|
-
#
|
1200
|
-
#
|
2447
|
+
# :call-seq:
|
2448
|
+
# delete(name) -> element
|
2449
|
+
# delete(attribute) -> element
|
2450
|
+
#
|
2451
|
+
# Removes a specified attribute if it exists;
|
2452
|
+
# returns the attributes' element.
|
2453
|
+
#
|
2454
|
+
# When string argument +name+ is given,
|
2455
|
+
# removes the attribute of that name if it exists:
|
2456
|
+
#
|
2457
|
+
# xml_string = <<-EOT
|
2458
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2459
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2460
|
+
# </root>
|
2461
|
+
# EOT
|
2462
|
+
# d = REXML::Document.new(xml_string)
|
2463
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2464
|
+
# attrs = ele.attributes
|
2465
|
+
# attrs.delete('foo:att') # => <ele bar:att='2' att='<'/>
|
2466
|
+
# attrs.delete('foo:att') # => <ele bar:att='2' att='<'/>
|
2467
|
+
#
|
2468
|
+
# When attribute argument +attribute+ is given,
|
2469
|
+
# removes that attribute if it exists:
|
2470
|
+
#
|
2471
|
+
# attr = REXML::Attribute.new('bar:att', '2')
|
2472
|
+
# attrs.delete(attr) # => <ele att='<'/> # => <ele att='<'/>
|
2473
|
+
# attrs.delete(attr) # => <ele att='<'/> # => <ele/>
|
2474
|
+
#
|
1201
2475
|
def delete( attribute )
|
1202
2476
|
name = nil
|
1203
2477
|
prefix = nil
|
@@ -1225,19 +2499,48 @@ module REXML
|
|
1225
2499
|
@element
|
1226
2500
|
end
|
1227
2501
|
|
1228
|
-
#
|
1229
|
-
#
|
1230
|
-
#
|
2502
|
+
# :call-seq:
|
2503
|
+
# add(attribute) -> attribute
|
2504
|
+
#
|
2505
|
+
# Adds attribute +attribute+, replacing the previous
|
2506
|
+
# attribute of the same name if it exists;
|
2507
|
+
# returns +attribute+:
|
2508
|
+
#
|
2509
|
+
# xml_string = <<-EOT
|
2510
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2511
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2512
|
+
# </root>
|
2513
|
+
# EOT
|
2514
|
+
# d = REXML::Document.new(xml_string)
|
2515
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2516
|
+
# attrs = ele.attributes
|
2517
|
+
# attrs # => {"att"=>{"foo"=>foo:att='1', "bar"=>bar:att='2', ""=>att='<'}}
|
2518
|
+
# attrs.add(REXML::Attribute.new('foo:att', '2')) # => foo:att='2'
|
2519
|
+
# attrs.add(REXML::Attribute.new('baz', '3')) # => baz='3'
|
2520
|
+
# attrs.include?('baz') # => true
|
2521
|
+
#
|
1231
2522
|
def add( attribute )
|
1232
2523
|
self[attribute.name] = attribute
|
1233
2524
|
end
|
1234
2525
|
|
1235
2526
|
alias :<< :add
|
1236
2527
|
|
1237
|
-
#
|
1238
|
-
#
|
1239
|
-
#
|
1240
|
-
#
|
2528
|
+
# :call-seq:
|
2529
|
+
# delete_all(name) -> array_of_removed_attributes
|
2530
|
+
#
|
2531
|
+
# Removes all attributes matching the given +name+;
|
2532
|
+
# returns an array of the removed attributes:
|
2533
|
+
#
|
2534
|
+
# xml_string = <<-EOT
|
2535
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2536
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2537
|
+
# </root>
|
2538
|
+
# EOT
|
2539
|
+
# d = REXML::Document.new(xml_string)
|
2540
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2541
|
+
# attrs = ele.attributes
|
2542
|
+
# attrs.delete_all('att') # => [att='<']
|
2543
|
+
#
|
1241
2544
|
def delete_all( name )
|
1242
2545
|
rv = []
|
1243
2546
|
each_attribute { |attribute|
|
@@ -1247,11 +2550,23 @@ module REXML
|
|
1247
2550
|
return rv
|
1248
2551
|
end
|
1249
2552
|
|
1250
|
-
#
|
1251
|
-
#
|
1252
|
-
#
|
2553
|
+
# :call-seq:
|
2554
|
+
# get_attribute_ns(namespace, name)
|
2555
|
+
#
|
2556
|
+
# Returns the \REXML::Attribute object among the attributes
|
2557
|
+
# that matches the given +namespace+ and +name+:
|
2558
|
+
#
|
2559
|
+
# xml_string = <<-EOT
|
2560
|
+
# <root xmlns:foo="http://foo" xmlns:bar="http://bar">
|
2561
|
+
# <ele foo:att='1' bar:att='2' att='<'/>
|
2562
|
+
# </root>
|
2563
|
+
# EOT
|
2564
|
+
# d = REXML::Document.new(xml_string)
|
2565
|
+
# ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='<'/>
|
2566
|
+
# attrs = ele.attributes
|
2567
|
+
# attrs.get_attribute_ns('http://foo', 'att') # => foo:att='1'
|
2568
|
+
# attrs.get_attribute_ns('http://foo', 'nosuch') # => nil
|
1253
2569
|
#
|
1254
|
-
# Method contributed by Henrik Martensson
|
1255
2570
|
def get_attribute_ns(namespace, name)
|
1256
2571
|
result = nil
|
1257
2572
|
each_attribute() { |attribute|
|