rubysl-rexml 1.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/lib/rexml/attlistdecl.rb +56 -56
- data/lib/rexml/attribute.rb +155 -149
- data/lib/rexml/cdata.rb +48 -48
- data/lib/rexml/child.rb +82 -82
- data/lib/rexml/comment.rb +59 -59
- data/lib/rexml/doctype.rb +22 -24
- data/lib/rexml/document.rb +185 -129
- data/lib/rexml/dtd/attlistdecl.rb +7 -7
- data/lib/rexml/dtd/dtd.rb +41 -41
- data/lib/rexml/dtd/elementdecl.rb +13 -13
- data/lib/rexml/dtd/entitydecl.rb +49 -49
- data/lib/rexml/dtd/notationdecl.rb +32 -32
- data/lib/rexml/element.rb +122 -107
- data/lib/rexml/encoding.rb +37 -58
- data/lib/rexml/entity.rb +144 -144
- data/lib/rexml/formatters/default.rb +6 -4
- data/lib/rexml/formatters/pretty.rb +11 -8
- data/lib/rexml/formatters/transitive.rb +4 -3
- data/lib/rexml/functions.rb +33 -21
- data/lib/rexml/instruction.rb +49 -49
- data/lib/rexml/light/node.rb +190 -191
- data/lib/rexml/namespace.rb +39 -39
- data/lib/rexml/node.rb +38 -38
- data/lib/rexml/output.rb +17 -12
- data/lib/rexml/parent.rb +26 -25
- data/lib/rexml/parseexception.rb +4 -4
- data/lib/rexml/parsers/baseparser.rb +90 -61
- data/lib/rexml/parsers/lightparser.rb +41 -43
- data/lib/rexml/parsers/pullparser.rb +1 -1
- data/lib/rexml/parsers/sax2parser.rb +233 -198
- data/lib/rexml/parsers/streamparser.rb +6 -2
- data/lib/rexml/parsers/treeparser.rb +9 -6
- data/lib/rexml/parsers/ultralightparser.rb +40 -40
- data/lib/rexml/parsers/xpathparser.rb +51 -52
- data/lib/rexml/quickpath.rb +247 -248
- data/lib/rexml/rexml.rb +9 -10
- data/lib/rexml/sax2listener.rb +92 -92
- data/lib/rexml/security.rb +27 -0
- data/lib/rexml/source.rb +95 -50
- data/lib/rexml/streamlistener.rb +90 -90
- data/lib/rexml/syncenumerator.rb +3 -4
- data/lib/rexml/text.rb +157 -76
- data/lib/rexml/validation/relaxng.rb +18 -18
- data/lib/rexml/validation/validation.rb +5 -5
- data/lib/rexml/xmldecl.rb +59 -63
- data/lib/rexml/xmltokens.rb +14 -14
- data/lib/rexml/xpath.rb +67 -53
- data/lib/rexml/xpath_parser.rb +49 -38
- data/lib/rubysl/rexml.rb +1 -0
- data/lib/rubysl/rexml/version.rb +1 -1
- data/rubysl-rexml.gemspec +3 -1
- metadata +19 -28
- data/lib/rexml/encodings/CP-1252.rb +0 -103
- data/lib/rexml/encodings/EUC-JP.rb +0 -35
- data/lib/rexml/encodings/ICONV.rb +0 -22
- data/lib/rexml/encodings/ISO-8859-1.rb +0 -7
- data/lib/rexml/encodings/ISO-8859-15.rb +0 -72
- data/lib/rexml/encodings/SHIFT-JIS.rb +0 -37
- data/lib/rexml/encodings/SHIFT_JIS.rb +0 -1
- data/lib/rexml/encodings/UNILE.rb +0 -34
- data/lib/rexml/encodings/US-ASCII.rb +0 -30
- data/lib/rexml/encodings/UTF-16.rb +0 -35
- data/lib/rexml/encodings/UTF-8.rb +0 -18
@@ -1,17 +1,17 @@
|
|
1
1
|
require "rexml/child"
|
2
2
|
module REXML
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
module DTD
|
4
|
+
class ElementDecl < Child
|
5
|
+
START = "<!ELEMENT"
|
6
|
+
START_RE = /^\s*#{START}/um
|
7
|
+
PATTERN_RE = /^\s*(#{START}.*?)>/um
|
8
|
+
PATTERN_RE = /^\s*#{START}\s+((?:[:\w_][-\.\w_]*:)?[-!\*\.\w_]*)(.*?)>/
|
9
|
+
#\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true)
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
def initialize match
|
12
|
+
@name = match[1]
|
13
|
+
@rest = match[2]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
17
|
end
|
data/lib/rexml/dtd/entitydecl.rb
CHANGED
@@ -1,56 +1,56 @@
|
|
1
1
|
require "rexml/child"
|
2
2
|
module REXML
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
3
|
+
module DTD
|
4
|
+
class EntityDecl < Child
|
5
|
+
START = "<!ENTITY"
|
6
|
+
START_RE = /^\s*#{START}/um
|
7
|
+
PUBLIC = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+PUBLIC\s+((["']).*?\3)\s+((["']).*?\5)\s*>/um
|
8
|
+
SYSTEM = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+SYSTEM\s+((["']).*?\3)(?:\s+NDATA\s+\w+)?\s*>/um
|
9
|
+
PLAIN = /^\s*#{START}\s+(\w+)\s+((["']).*?\3)\s*>/um
|
10
|
+
PERCENT = /^\s*#{START}\s+%\s+(\w+)\s+((["']).*?\3)\s*>/um
|
11
|
+
# <!ENTITY name SYSTEM "...">
|
12
|
+
# <!ENTITY name "...">
|
13
|
+
def initialize src
|
14
|
+
super()
|
15
|
+
md = nil
|
16
|
+
if src.match( PUBLIC )
|
17
|
+
md = src.match( PUBLIC, true )
|
18
|
+
@middle = "PUBLIC"
|
19
|
+
@content = "#{md[2]} #{md[4]}"
|
20
|
+
elsif src.match( SYSTEM )
|
21
|
+
md = src.match( SYSTEM, true )
|
22
|
+
@middle = "SYSTEM"
|
23
|
+
@content = md[2]
|
24
|
+
elsif src.match( PLAIN )
|
25
|
+
md = src.match( PLAIN, true )
|
26
|
+
@middle = ""
|
27
|
+
@content = md[2]
|
28
|
+
elsif src.match( PERCENT )
|
29
|
+
md = src.match( PERCENT, true )
|
30
|
+
@middle = ""
|
31
|
+
@content = md[2]
|
32
|
+
end
|
33
|
+
raise ParseException.new("failed Entity match", src) if md.nil?
|
34
|
+
@name = md[1]
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
def to_s
|
38
|
+
rv = "<!ENTITY #@name "
|
39
|
+
rv << "#@middle " if @middle.size > 0
|
40
|
+
rv << @content
|
41
|
+
rv
|
42
|
+
end
|
43
43
|
|
44
|
-
|
44
|
+
def write( output, indent )
|
45
45
|
indent( output, indent )
|
46
|
-
|
47
|
-
|
46
|
+
output << to_s
|
47
|
+
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
def EntityDecl.parse_source source, listener
|
50
|
+
md = source.match( PATTERN_RE, true )
|
51
|
+
thing = md[0].squeeze(" \t\n\r")
|
52
|
+
listener.send inspect.downcase, thing
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
56
|
end
|
@@ -1,39 +1,39 @@
|
|
1
1
|
require "rexml/child"
|
2
2
|
module REXML
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
3
|
+
module DTD
|
4
|
+
class NotationDecl < Child
|
5
|
+
START = "<!NOTATION"
|
6
|
+
START_RE = /^\s*#{START}/um
|
7
|
+
PUBLIC = /^\s*#{START}\s+(\w[\w-]*)\s+(PUBLIC)\s+((["']).*?\4)\s*>/um
|
8
|
+
SYSTEM = /^\s*#{START}\s+(\w[\w-]*)\s+(SYSTEM)\s+((["']).*?\4)\s*>/um
|
9
|
+
def initialize src
|
10
|
+
super()
|
11
|
+
if src.match( PUBLIC )
|
12
|
+
md = src.match( PUBLIC, true )
|
13
|
+
elsif src.match( SYSTEM )
|
14
|
+
md = src.match( SYSTEM, true )
|
15
|
+
else
|
16
|
+
raise ParseException.new( "error parsing notation: no matching pattern", src )
|
17
|
+
end
|
18
|
+
@name = md[1]
|
19
|
+
@middle = md[2]
|
20
|
+
@rest = md[3]
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
def to_s
|
24
|
+
"<!NOTATION #@name #@middle #@rest>"
|
25
|
+
end
|
26
26
|
|
27
|
-
|
27
|
+
def write( output, indent )
|
28
28
|
indent( output, indent )
|
29
|
-
|
30
|
-
|
29
|
+
output << to_s
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
def NotationDecl.parse_source source, listener
|
33
|
+
md = source.match( PATTERN_RE, true )
|
34
|
+
thing = md[0].squeeze(" \t\n\r")
|
35
|
+
listener.send inspect.downcase, thing
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
39
|
end
|
data/lib/rexml/element.rb
CHANGED
@@ -20,7 +20,7 @@ module REXML
|
|
20
20
|
class Element < Parent
|
21
21
|
include Namespace
|
22
22
|
|
23
|
-
UNDEFINED = "UNDEFINED";
|
23
|
+
UNDEFINED = "UNDEFINED"; # The default name
|
24
24
|
|
25
25
|
# Mechanisms for accessing attributes and child elements of this
|
26
26
|
# element.
|
@@ -30,18 +30,18 @@ module REXML
|
|
30
30
|
attr_accessor :context
|
31
31
|
|
32
32
|
# Constructor
|
33
|
-
# arg::
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# parent::
|
40
|
-
#
|
41
|
-
#
|
33
|
+
# arg::
|
34
|
+
# if not supplied, will be set to the default value.
|
35
|
+
# If a String, the name of this object will be set to the argument.
|
36
|
+
# If an Element, the object will be shallowly cloned; name,
|
37
|
+
# attributes, and namespaces will be copied. Children will +not+ be
|
38
|
+
# copied.
|
39
|
+
# parent::
|
40
|
+
# if supplied, must be a Parent, and will be used as
|
41
|
+
# the parent of this object.
|
42
42
|
# context::
|
43
|
-
#
|
44
|
-
#
|
43
|
+
# If supplied, must be a hash containing context items. Context items
|
44
|
+
# include:
|
45
45
|
# * <tt>:respect_whitespace</tt> the value of this is :+all+ or an array of
|
46
46
|
# strings being the names of the elements to respect
|
47
47
|
# whitespace for. Defaults to :+all+.
|
@@ -97,7 +97,7 @@ module REXML
|
|
97
97
|
self.class.new self
|
98
98
|
end
|
99
99
|
|
100
|
-
# Evaluates to the root node of the document that this element
|
100
|
+
# Evaluates to the root node of the document that this element
|
101
101
|
# belongs to. If this element doesn't belong to a document, but does
|
102
102
|
# belong to another Element, the parent's root will be returned, until the
|
103
103
|
# earliest ancestor is found.
|
@@ -137,8 +137,8 @@ module REXML
|
|
137
137
|
# is the case if:
|
138
138
|
# 1. Neither :+respect_whitespace+ nor :+compress_whitespace+ has any value
|
139
139
|
# 2. The context has :+respect_whitespace+ set to :+all+ or
|
140
|
-
# an array containing the name of this element, and
|
141
|
-
# :+compress_whitespace+ isn't set to :+all+ or an array containing the
|
140
|
+
# an array containing the name of this element, and
|
141
|
+
# :+compress_whitespace+ isn't set to :+all+ or an array containing the
|
142
142
|
# name of this element.
|
143
143
|
# The evaluation is tested against +expanded_name+, and so is namespace
|
144
144
|
# sensitive.
|
@@ -162,7 +162,7 @@ module REXML
|
|
162
162
|
@ignore_whitespace_nodes = false
|
163
163
|
if @context
|
164
164
|
if @context[:ignore_whitespace_nodes]
|
165
|
-
@ignore_whitespace_nodes =
|
165
|
+
@ignore_whitespace_nodes =
|
166
166
|
(@context[:ignore_whitespace_nodes] == :all or
|
167
167
|
@context[:ignore_whitespace_nodes].include? expanded_name)
|
168
168
|
end
|
@@ -206,13 +206,13 @@ module REXML
|
|
206
206
|
return namespaces
|
207
207
|
end
|
208
208
|
|
209
|
-
# Evalutas to the URI for a prefix, or the empty string if no such
|
209
|
+
# Evalutas to the URI for a prefix, or the empty string if no such
|
210
210
|
# namespace is declared for this element. Evaluates recursively for
|
211
211
|
# ancestors. Returns the default namespace, if there is one.
|
212
|
-
# prefix::
|
212
|
+
# prefix::
|
213
213
|
# the prefix to search for. If not supplied, returns the default
|
214
214
|
# namespace if one exists
|
215
|
-
# Returns::
|
215
|
+
# Returns::
|
216
216
|
# the namespace URI as a String, or nil if no such namespace
|
217
217
|
# exists. If the namespace is undefined, returns an empty string
|
218
218
|
# doc = Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
|
@@ -235,10 +235,10 @@ module REXML
|
|
235
235
|
end
|
236
236
|
|
237
237
|
# Adds a namespace to this element.
|
238
|
-
# prefix::
|
238
|
+
# prefix::
|
239
239
|
# the prefix string, or the namespace URI if +uri+ is not
|
240
240
|
# supplied
|
241
|
-
# uri::
|
241
|
+
# uri::
|
242
242
|
# the namespace URI. May be nil, in which +prefix+ is used as
|
243
243
|
# the URI
|
244
244
|
# Evaluates to: this Element
|
@@ -280,12 +280,12 @@ module REXML
|
|
280
280
|
|
281
281
|
# Adds a child to this element, optionally setting attributes in
|
282
282
|
# the element.
|
283
|
-
# element::
|
283
|
+
# element::
|
284
284
|
# optional. If Element, the element is added.
|
285
285
|
# Otherwise, a new Element is constructed with the argument (see
|
286
286
|
# Element.initialize).
|
287
|
-
# attrs::
|
288
|
-
# If supplied, must be a Hash containing String name,value
|
287
|
+
# attrs::
|
288
|
+
# If supplied, must be a Hash containing String name,value
|
289
289
|
# pairs, which will be used to set the attributes of the new Element.
|
290
290
|
# Returns:: the Element that was added
|
291
291
|
# el = doc.add_element 'my-tag'
|
@@ -296,15 +296,15 @@ module REXML
|
|
296
296
|
raise "First argument must be either an element name, or an Element object" if element.nil?
|
297
297
|
el = @elements.add(element)
|
298
298
|
attrs.each do |key, value|
|
299
|
-
el.attributes[key]=
|
300
|
-
end
|
299
|
+
el.attributes[key]=value
|
300
|
+
end if attrs.kind_of? Hash
|
301
301
|
el
|
302
302
|
end
|
303
303
|
|
304
304
|
# Deletes a child element.
|
305
|
-
# element::
|
306
|
-
# Must be an +Element+, +String+, or +Integer+. If Element,
|
307
|
-
# the element is removed. If String, the element is found (via XPath)
|
305
|
+
# element::
|
306
|
+
# Must be an +Element+, +String+, or +Integer+. If Element,
|
307
|
+
# the element is removed. If String, the element is found (via XPath)
|
308
308
|
# and removed. <em>This means that any parent can remove any
|
309
309
|
# descendant.<em> If Integer, the Element indexed by that number will be
|
310
310
|
# removed.
|
@@ -327,14 +327,14 @@ module REXML
|
|
327
327
|
|
328
328
|
# Iterates through the child elements, yielding for each Element that
|
329
329
|
# has a particular attribute set.
|
330
|
-
# key::
|
330
|
+
# key::
|
331
331
|
# the name of the attribute to search for
|
332
|
-
# value::
|
332
|
+
# value::
|
333
333
|
# the value of the attribute
|
334
|
-
# max::
|
335
|
-
# (optional) causes this method to return after yielding
|
334
|
+
# max::
|
335
|
+
# (optional) causes this method to return after yielding
|
336
336
|
# for this number of matching children
|
337
|
-
# name::
|
337
|
+
# name::
|
338
338
|
# (optional) if supplied, this is an XPath that filters
|
339
339
|
# the children to check.
|
340
340
|
#
|
@@ -348,7 +348,7 @@ module REXML
|
|
348
348
|
# # Yields d
|
349
349
|
# doc.root.each_element_with_attribute( 'id', '1', 0, 'd' ) {|e| p e}
|
350
350
|
def each_element_with_attribute( key, value=nil, max=0, name=nil, &block ) # :yields: Element
|
351
|
-
each_with_something( proc {|child|
|
351
|
+
each_with_something( proc {|child|
|
352
352
|
if value.nil?
|
353
353
|
child.attributes[key] != nil
|
354
354
|
else
|
@@ -359,13 +359,13 @@ module REXML
|
|
359
359
|
|
360
360
|
# Iterates through the children, yielding for each Element that
|
361
361
|
# has a particular text set.
|
362
|
-
# text::
|
362
|
+
# text::
|
363
363
|
# the text to search for. If nil, or not supplied, will iterate
|
364
364
|
# over all +Element+ children that contain at least one +Text+ node.
|
365
|
-
# max::
|
365
|
+
# max::
|
366
366
|
# (optional) causes this method to return after yielding
|
367
367
|
# for this number of matching children
|
368
|
-
# name::
|
368
|
+
# name::
|
369
369
|
# (optional) if supplied, this is an XPath that filters
|
370
370
|
# the children to check.
|
371
371
|
#
|
@@ -379,7 +379,7 @@ module REXML
|
|
379
379
|
# # Yields d
|
380
380
|
# doc.each_element_with_text(nil, 0, 'd'){|e|p e}
|
381
381
|
def each_element_with_text( text=nil, max=0, name=nil, &block ) # :yields: Element
|
382
|
-
each_with_something( proc {|child|
|
382
|
+
each_with_something( proc {|child|
|
383
383
|
if text.nil?
|
384
384
|
child.has_text?
|
385
385
|
else
|
@@ -408,7 +408,7 @@ module REXML
|
|
408
408
|
# doc.root.elements['c'].next_element #-> nil
|
409
409
|
def next_element
|
410
410
|
element = next_sibling
|
411
|
-
element = element.next_sibling until element.nil? or element.kind_of? Element
|
411
|
+
element = element.next_sibling until element.nil? or element.kind_of? Element
|
412
412
|
return element
|
413
413
|
end
|
414
414
|
|
@@ -477,7 +477,7 @@ module REXML
|
|
477
477
|
# this method with a nil argument. In this case, the next Text
|
478
478
|
# child becomes the first Text child. In no case is the order of
|
479
479
|
# any siblings disturbed.
|
480
|
-
# text::
|
480
|
+
# text::
|
481
481
|
# If a String, a new Text child is created and added to
|
482
482
|
# this Element as the first Text child. If Text, the text is set
|
483
483
|
# as the first Child element. If nil, then any existing first Text
|
@@ -520,7 +520,7 @@ module REXML
|
|
520
520
|
# Note that at the end of this example, the branch has <b>3</b> nodes; the 'e'
|
521
521
|
# element and <b>2</b> Text node children.
|
522
522
|
def add_text( text )
|
523
|
-
if text.kind_of? String
|
523
|
+
if text.kind_of? String
|
524
524
|
if @children[-1].kind_of? Text
|
525
525
|
@children[-1] << text
|
526
526
|
return
|
@@ -552,9 +552,25 @@ module REXML
|
|
552
552
|
|
553
553
|
def attribute( name, namespace=nil )
|
554
554
|
prefix = nil
|
555
|
-
|
555
|
+
if namespaces.respond_to? :key
|
556
|
+
prefix = namespaces.key(namespace) if namespace
|
557
|
+
else
|
558
|
+
prefix = namespaces.index(namespace) if namespace
|
559
|
+
end
|
556
560
|
prefix = nil if prefix == 'xmlns'
|
557
|
-
|
561
|
+
|
562
|
+
ret_val =
|
563
|
+
attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" )
|
564
|
+
|
565
|
+
return ret_val unless ret_val.nil?
|
566
|
+
return nil if prefix.nil?
|
567
|
+
|
568
|
+
# now check that prefix'es namespace is not the same as the
|
569
|
+
# default namespace
|
570
|
+
return nil unless ( namespaces[ prefix ] == namespaces[ 'xmlns' ] )
|
571
|
+
|
572
|
+
attributes.get_attribute( name )
|
573
|
+
|
558
574
|
end
|
559
575
|
|
560
576
|
# Evaluates to +true+ if this element has any attributes set, false
|
@@ -570,7 +586,7 @@ module REXML
|
|
570
586
|
# the attribute is added to the list of Element attributes. If String,
|
571
587
|
# the argument is used as the name of the new attribute, and the value
|
572
588
|
# parameter must be supplied.
|
573
|
-
# value::
|
589
|
+
# value::
|
574
590
|
# Required if +key+ is a String, and ignored if the first argument is
|
575
591
|
# an Attribute. This is a String, and is used as the value
|
576
592
|
# of the new Attribute. This should be the unnormalized value of the
|
@@ -605,7 +621,7 @@ module REXML
|
|
605
621
|
# either an Attribute or a String. In either case, the
|
606
622
|
# attribute is found by matching the attribute name to the argument,
|
607
623
|
# and then removed. If no attribute is found, no action is taken.
|
608
|
-
# Returns::
|
624
|
+
# Returns::
|
609
625
|
# the attribute removed, or nil if this Element did not contain
|
610
626
|
# a matching attribute
|
611
627
|
# e = Element.new('E')
|
@@ -622,7 +638,7 @@ module REXML
|
|
622
638
|
# Other Utilities #
|
623
639
|
#################################################
|
624
640
|
|
625
|
-
# Get an array of all CData children.
|
641
|
+
# Get an array of all CData children.
|
626
642
|
# IMMUTABLE
|
627
643
|
def cdatas
|
628
644
|
find_all { |child| child.kind_of? CData }.freeze
|
@@ -651,7 +667,7 @@ module REXML
|
|
651
667
|
#
|
652
668
|
# Writes out this element, and recursively, all children.
|
653
669
|
# output::
|
654
|
-
#
|
670
|
+
# output an object which supports '<< string'; this is where the
|
655
671
|
# document will be written.
|
656
672
|
# indent::
|
657
673
|
# An integer. If -1, no indenting will be used; otherwise, the
|
@@ -662,19 +678,17 @@ module REXML
|
|
662
678
|
# pretty-printed in such a way that the added whitespace does not affect
|
663
679
|
# the parse tree of the document
|
664
680
|
# ie_hack::
|
665
|
-
#
|
666
|
-
#
|
667
|
-
# unable to parse proper XML, we have to provide a hack to generate XML
|
668
|
-
# that IE's limited abilities can handle. This hack inserts a space
|
669
|
-
# before the /> on empty tags. Defaults to false
|
681
|
+
# This hack inserts a space before the /> on empty tags to address
|
682
|
+
# a limitation of Internet Explorer. Defaults to false
|
670
683
|
#
|
671
684
|
# out = ''
|
672
685
|
# doc.write( out ) #-> doc is written to the string 'out'
|
673
686
|
# doc.write( $stdout ) #-> doc written to the console
|
674
|
-
def write(
|
687
|
+
def write(output=$stdout, indent=-1, transitive=false, ie_hack=false)
|
675
688
|
Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters")
|
676
689
|
formatter = if indent > -1
|
677
690
|
if transitive
|
691
|
+
require "rexml/formatters/transitive"
|
678
692
|
REXML::Formatters::Transitive.new( indent, ie_hack )
|
679
693
|
else
|
680
694
|
REXML::Formatters::Pretty.new( indent, ie_hack )
|
@@ -690,8 +704,8 @@ module REXML
|
|
690
704
|
def __to_xpath_helper node
|
691
705
|
rv = node.expanded_name.clone
|
692
706
|
if node.parent
|
693
|
-
results = node.parent.find_all {|n|
|
694
|
-
n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name
|
707
|
+
results = node.parent.find_all {|n|
|
708
|
+
n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name
|
695
709
|
}
|
696
710
|
if results.length > 1
|
697
711
|
idx = results.index( node )
|
@@ -704,7 +718,6 @@ module REXML
|
|
704
718
|
# A private helper method
|
705
719
|
def each_with_something( test, max=0, name=nil )
|
706
720
|
num = 0
|
707
|
-
child=nil
|
708
721
|
@elements.each( name ){ |child|
|
709
722
|
yield child if test.call(child) and num += 1
|
710
723
|
return if max>0 and num == max
|
@@ -718,7 +731,7 @@ module REXML
|
|
718
731
|
|
719
732
|
# A class which provides filtering of children for Elements, and
|
720
733
|
# XPath search support. You are expected to only encounter this class as
|
721
|
-
# the <tt>element.elements</tt> object. Therefore, you are
|
734
|
+
# the <tt>element.elements</tt> object. Therefore, you are
|
722
735
|
# _not_ expected to instantiate this yourself.
|
723
736
|
class Elements
|
724
737
|
include Enumerable
|
@@ -730,7 +743,7 @@ module REXML
|
|
730
743
|
|
731
744
|
# Fetches a child element. Filters only Element children, regardless of
|
732
745
|
# the XPath match.
|
733
|
-
# index::
|
746
|
+
# index::
|
734
747
|
# the search parameter. This is either an Integer, which
|
735
748
|
# will be used to find the index'th child Element, or an XPath,
|
736
749
|
# which will be used to search for the Element. <em>Because
|
@@ -740,7 +753,7 @@ module REXML
|
|
740
753
|
# child element is at index 1, not 0, and the +n+th element is at index
|
741
754
|
# +n+, not <tt>n-1</tt>. This is because XPath indexes element children
|
742
755
|
# starting from 1, not 0, and the indexes should be the same.
|
743
|
-
# name::
|
756
|
+
# name::
|
744
757
|
# optional, and only used in the first argument is an
|
745
758
|
# Integer. In that case, the index'th child Element that has the
|
746
759
|
# supplied name will be returned. Note again that the indexes start at 1.
|
@@ -754,16 +767,15 @@ module REXML
|
|
754
767
|
raise "index (#{index}) must be >= 1" if index < 1
|
755
768
|
name = literalize(name) if name
|
756
769
|
num = 0
|
757
|
-
child = nil
|
758
770
|
@element.find { |child|
|
759
771
|
child.kind_of? Element and
|
760
|
-
(name.nil? ? true : child.has_name?( name )) and
|
772
|
+
(name.nil? ? true : child.has_name?( name )) and
|
761
773
|
(num += 1) == index
|
762
774
|
}
|
763
775
|
else
|
764
776
|
return XPath::first( @element, index )
|
765
|
-
#{ |element|
|
766
|
-
#
|
777
|
+
#{ |element|
|
778
|
+
# return element if element.kind_of? Element
|
767
779
|
#}
|
768
780
|
#return nil
|
769
781
|
end
|
@@ -772,7 +784,7 @@ module REXML
|
|
772
784
|
# Sets an element, replacing any previous matching element. If no
|
773
785
|
# existing element is found ,the element is added.
|
774
786
|
# index:: Used to find a matching element to replace. See []().
|
775
|
-
# element::
|
787
|
+
# element::
|
776
788
|
# The element to replace the existing element with
|
777
789
|
# the previous element
|
778
790
|
# Returns:: nil if no previous element was found.
|
@@ -797,12 +809,12 @@ module REXML
|
|
797
809
|
@element.find{ |child| child.kind_of? Element}.nil?
|
798
810
|
end
|
799
811
|
|
800
|
-
# Returns the index of the supplied child (starting at 1), or -1 if
|
812
|
+
# Returns the index of the supplied child (starting at 1), or -1 if
|
801
813
|
# the element is not a child
|
802
814
|
# element:: an +Element+ child
|
803
815
|
def index element
|
804
816
|
rv = 0
|
805
|
-
found = @element.find do |child|
|
817
|
+
found = @element.find do |child|
|
806
818
|
child.kind_of? Element and
|
807
819
|
(rv += 1) and
|
808
820
|
child == element
|
@@ -812,7 +824,7 @@ module REXML
|
|
812
824
|
end
|
813
825
|
|
814
826
|
# Deletes a child Element
|
815
|
-
# element::
|
827
|
+
# element::
|
816
828
|
# Either an Element, which is removed directly; an
|
817
829
|
# xpath, where the first matching child is removed; or an Integer,
|
818
830
|
# where the n'th Element is removed.
|
@@ -839,7 +851,7 @@ module REXML
|
|
839
851
|
# deleted = doc.elements.delete_all 'a/c' #-> [<c/>, <c/>, <c/>, <c/>]
|
840
852
|
def delete_all( xpath )
|
841
853
|
rv = []
|
842
|
-
XPath::each( @element, xpath) {|element|
|
854
|
+
XPath::each( @element, xpath) {|element|
|
843
855
|
rv << element if element.kind_of? Element
|
844
856
|
}
|
845
857
|
rv.each do |element|
|
@@ -850,7 +862,7 @@ module REXML
|
|
850
862
|
end
|
851
863
|
|
852
864
|
# Adds an element
|
853
|
-
# element::
|
865
|
+
# element::
|
854
866
|
# if supplied, is either an Element, String, or
|
855
867
|
# Source (see Element.initialize). If not supplied or nil, a
|
856
868
|
# new, default Element will be constructed
|
@@ -859,7 +871,6 @@ module REXML
|
|
859
871
|
# a.elements.add(Element.new('b')) #-> <a><b/></a>
|
860
872
|
# a.elements.add('c') #-> <a><b/><c/></a>
|
861
873
|
def add element=nil
|
862
|
-
rv = nil
|
863
874
|
if element.nil?
|
864
875
|
Element.new("", self, @element.context)
|
865
876
|
elsif not element.kind_of?(Element)
|
@@ -875,31 +886,31 @@ module REXML
|
|
875
886
|
|
876
887
|
# Iterates through all of the child Elements, optionally filtering
|
877
888
|
# them by a given XPath
|
878
|
-
# xpath::
|
879
|
-
# optional. If supplied, this is a String XPath, and is used to
|
889
|
+
# xpath::
|
890
|
+
# optional. If supplied, this is a String XPath, and is used to
|
880
891
|
# filter the children, so that only matching children are yielded. Note
|
881
892
|
# that XPaths are automatically filtered for Elements, so that
|
882
893
|
# non-Element children will not be yielded
|
883
894
|
# doc = Document.new '<a><b/><c/><d/>sean<b/><c/><d/></a>'
|
884
|
-
# doc.root.each {|e|p e} #-> Yields b, c, d, b, c, d elements
|
885
|
-
# doc.root.each('b') {|e|p e} #-> Yields b, b elements
|
886
|
-
# doc.root.each('child::node()') {|e|p e}
|
895
|
+
# doc.root.elements.each {|e|p e} #-> Yields b, c, d, b, c, d elements
|
896
|
+
# doc.root.elements.each('b') {|e|p e} #-> Yields b, b elements
|
897
|
+
# doc.root.elements.each('child::node()') {|e|p e}
|
887
898
|
# #-> Yields <b/>, <c/>, <d/>, <b/>, <c/>, <d/>
|
888
899
|
# XPath.each(doc.root, 'child::node()', &block)
|
889
900
|
# #-> Yields <b/>, <c/>, <d/>, sean, <b/>, <c/>, <d/>
|
890
|
-
def each( xpath=nil
|
901
|
+
def each( xpath=nil )
|
891
902
|
XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element }
|
892
903
|
end
|
893
904
|
|
894
|
-
def collect( xpath=nil
|
905
|
+
def collect( xpath=nil )
|
895
906
|
collection = []
|
896
|
-
XPath::each( @element, xpath ) {|e|
|
897
|
-
collection << yield(e) if e.kind_of?(Element)
|
907
|
+
XPath::each( @element, xpath ) {|e|
|
908
|
+
collection << yield(e) if e.kind_of?(Element)
|
898
909
|
}
|
899
910
|
collection
|
900
911
|
end
|
901
912
|
|
902
|
-
def inject( xpath=nil, initial=nil
|
913
|
+
def inject( xpath=nil, initial=nil )
|
903
914
|
first = true
|
904
915
|
XPath::each( @element, xpath ) {|e|
|
905
916
|
if (e.kind_of? Element)
|
@@ -929,7 +940,7 @@ module REXML
|
|
929
940
|
# supplied XPath matches non-Element children.
|
930
941
|
# doc = Document.new '<a>sean<b/>elliott<c/></a>'
|
931
942
|
# doc.root.elements.to_a #-> [ <b/>, <c/> ]
|
932
|
-
# doc.root.elements.to_a("child::node()") #-> [ <b/>, <c/> ]
|
943
|
+
# doc.root.elements.to_a("child::node()") #-> [ <b/>, <c/> ]
|
933
944
|
# XPath.match(doc.root, "child::node()") #-> [ sean, <b/>, elliott, <c/> ]
|
934
945
|
def to_a( xpath=nil )
|
935
946
|
rv = XPath.match( @element, xpath )
|
@@ -949,7 +960,7 @@ module REXML
|
|
949
960
|
# ATTRIBUTES #
|
950
961
|
########################################################################
|
951
962
|
|
952
|
-
# A class that defines the set of Attributes of an Element and provides
|
963
|
+
# A class that defines the set of Attributes of an Element and provides
|
953
964
|
# operations for accessing elements in that set.
|
954
965
|
class Attributes < Hash
|
955
966
|
# Constructor
|
@@ -961,11 +972,11 @@ module REXML
|
|
961
972
|
# Fetches an attribute value. If you want to get the Attribute itself,
|
962
973
|
# use get_attribute()
|
963
974
|
# name:: an XPath attribute name. Namespaces are relevant here.
|
964
|
-
# Returns::
|
975
|
+
# Returns::
|
965
976
|
# the String value of the matching attribute, or +nil+ if no
|
966
977
|
# matching attribute was found. This is the unnormalized value
|
967
978
|
# (with entities expanded).
|
968
|
-
#
|
979
|
+
#
|
969
980
|
# doc = Document.new "<a foo:att='1' bar:att='2' att='<'/>"
|
970
981
|
# doc.root.attributes['att'] #-> '<'
|
971
982
|
# doc.root.attributes['bar:att'] #-> '2'
|
@@ -976,7 +987,7 @@ module REXML
|
|
976
987
|
end
|
977
988
|
|
978
989
|
def to_a
|
979
|
-
|
990
|
+
enum_for(:each_attribute).to_a
|
980
991
|
end
|
981
992
|
|
982
993
|
# Returns the number of attributes the owning Element contains.
|
@@ -991,7 +1002,7 @@ module REXML
|
|
991
1002
|
|
992
1003
|
# Iterates over the attributes of an Element. Yields actual Attribute
|
993
1004
|
# nodes, not String values.
|
994
|
-
#
|
1005
|
+
#
|
995
1006
|
# doc = Document.new '<a x="1" y="2"/>'
|
996
1007
|
# doc.root.attributes.each_attribute {|attr|
|
997
1008
|
# p attr.expanded_name+" => "+attr.value
|
@@ -1013,12 +1024,12 @@ module REXML
|
|
1013
1024
|
# doc.root.attributes.each {|name, value| p name+" => "+value }
|
1014
1025
|
def each
|
1015
1026
|
each_attribute do |attr|
|
1016
|
-
yield attr.expanded_name, attr.value
|
1027
|
+
yield [attr.expanded_name, attr.value]
|
1017
1028
|
end
|
1018
1029
|
end
|
1019
1030
|
|
1020
1031
|
# Fetches an attribute
|
1021
|
-
# name::
|
1032
|
+
# name::
|
1022
1033
|
# the name by which to search for the attribute. Can be a
|
1023
1034
|
# <tt>prefix:name</tt> namespace name.
|
1024
1035
|
# Returns:: The first matching attribute, or nil if there was none. This
|
@@ -1062,22 +1073,22 @@ module REXML
|
|
1062
1073
|
# Sets an attribute, overwriting any existing attribute value by the
|
1063
1074
|
# same name. Namespace is significant.
|
1064
1075
|
# name:: the name of the attribute
|
1065
|
-
# value::
|
1076
|
+
# value::
|
1066
1077
|
# (optional) If supplied, the value of the attribute. If
|
1067
1078
|
# nil, any existing matching attribute is deleted.
|
1068
|
-
# Returns::
|
1079
|
+
# Returns::
|
1069
1080
|
# Owning element
|
1070
1081
|
# doc = Document.new "<a x:foo='1' foo='3'/>"
|
1071
1082
|
# doc.root.attributes['y:foo'] = '2'
|
1072
1083
|
# doc.root.attributes['foo'] = '4'
|
1073
1084
|
# doc.root.attributes['x:foo'] = nil
|
1074
1085
|
def []=( name, value )
|
1075
|
-
if value.nil?
|
1086
|
+
if value.nil? # Delete the named attribute
|
1076
1087
|
attr = get_attribute(name)
|
1077
1088
|
delete attr
|
1078
1089
|
return
|
1079
1090
|
end
|
1080
|
-
|
1091
|
+
|
1081
1092
|
unless value.kind_of? Attribute
|
1082
1093
|
if @element.document and @element.document.doctype
|
1083
1094
|
value = Text::normalize( value, @element.document.doctype )
|
@@ -1094,23 +1105,23 @@ module REXML
|
|
1094
1105
|
old_attr[value.prefix] = value
|
1095
1106
|
elsif old_attr.prefix != value.prefix
|
1096
1107
|
# Check for conflicting namespaces
|
1097
|
-
raise ParseException.new(
|
1108
|
+
raise ParseException.new(
|
1098
1109
|
"Namespace conflict in adding attribute \"#{value.name}\": "+
|
1099
1110
|
"Prefix \"#{old_attr.prefix}\" = "+
|
1100
1111
|
"\"#{@element.namespace(old_attr.prefix)}\" and prefix "+
|
1101
|
-
"\"#{value.prefix}\" = \"#{@element.namespace(value.prefix)}\"") if
|
1112
|
+
"\"#{value.prefix}\" = \"#{@element.namespace(value.prefix)}\"") if
|
1102
1113
|
value.prefix != "xmlns" and old_attr.prefix != "xmlns" and
|
1103
|
-
@element.namespace( old_attr.prefix ) ==
|
1114
|
+
@element.namespace( old_attr.prefix ) ==
|
1104
1115
|
@element.namespace( value.prefix )
|
1105
|
-
store value.name, { old_attr.prefix
|
1106
|
-
value.prefix
|
1116
|
+
store value.name, { old_attr.prefix => old_attr,
|
1117
|
+
value.prefix => value }
|
1107
1118
|
else
|
1108
1119
|
store value.name, value
|
1109
1120
|
end
|
1110
1121
|
return @element
|
1111
1122
|
end
|
1112
1123
|
|
1113
|
-
# Returns an array of Strings containing all of the prefixes declared
|
1124
|
+
# Returns an array of Strings containing all of the prefixes declared
|
1114
1125
|
# by this set of # attributes. The array does not include the default
|
1115
1126
|
# namespace declaration, if one exists.
|
1116
1127
|
# doc = Document.new("<a xmlns='foo' xmlns:x='bar' xmlns:y='twee' "+
|
@@ -1149,7 +1160,7 @@ module REXML
|
|
1149
1160
|
end
|
1150
1161
|
|
1151
1162
|
# Removes an attribute
|
1152
|
-
# attribute::
|
1163
|
+
# attribute::
|
1153
1164
|
# either a String, which is the name of the attribute to remove --
|
1154
1165
|
# namespaces are significant here -- or the attribute to remove.
|
1155
1166
|
# Returns:: the owning element
|
@@ -1182,7 +1193,7 @@ module REXML
|
|
1182
1193
|
return @element
|
1183
1194
|
else # the supplied attribute is a top-level one
|
1184
1195
|
attr = old
|
1185
|
-
|
1196
|
+
super(name)
|
1186
1197
|
end
|
1187
1198
|
@element
|
1188
1199
|
end
|
@@ -1197,12 +1208,12 @@ module REXML
|
|
1197
1208
|
alias :<< :add
|
1198
1209
|
|
1199
1210
|
# Deletes all attributes matching a name. Namespaces are significant.
|
1200
|
-
# name::
|
1211
|
+
# name::
|
1201
1212
|
# A String; all attributes that match this path will be removed
|
1202
1213
|
# Returns:: an Array of the Attributes that were removed
|
1203
1214
|
def delete_all( name )
|
1204
1215
|
rv = []
|
1205
|
-
each_attribute { |attribute|
|
1216
|
+
each_attribute { |attribute|
|
1206
1217
|
rv << attribute if attribute.expanded_name == name
|
1207
1218
|
}
|
1208
1219
|
rv.each{ |attr| attr.remove }
|
@@ -1212,16 +1223,20 @@ module REXML
|
|
1212
1223
|
# The +get_attribute_ns+ method retrieves a method by its namespace
|
1213
1224
|
# and name. Thus it is possible to reliably identify an attribute
|
1214
1225
|
# even if an XML processor has changed the prefix.
|
1215
|
-
#
|
1226
|
+
#
|
1216
1227
|
# Method contributed by Henrik Martensson
|
1217
1228
|
def get_attribute_ns(namespace, name)
|
1229
|
+
result = nil
|
1218
1230
|
each_attribute() { |attribute|
|
1219
1231
|
if name == attribute.name &&
|
1220
|
-
namespace == attribute.namespace()
|
1221
|
-
|
1232
|
+
namespace == attribute.namespace() &&
|
1233
|
+
( !namespace.empty? || !attribute.fully_expanded_name.index(':') )
|
1234
|
+
# foo will match xmlns:foo, but only if foo isn't also an attribute
|
1235
|
+
result = attribute if !result or !namespace.empty? or
|
1236
|
+
!attribute.fully_expanded_name.index(':')
|
1222
1237
|
end
|
1223
1238
|
}
|
1224
|
-
|
1239
|
+
result
|
1225
1240
|
end
|
1226
1241
|
end
|
1227
1242
|
end
|