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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -2
  3. data/lib/rexml/attlistdecl.rb +56 -56
  4. data/lib/rexml/attribute.rb +155 -149
  5. data/lib/rexml/cdata.rb +48 -48
  6. data/lib/rexml/child.rb +82 -82
  7. data/lib/rexml/comment.rb +59 -59
  8. data/lib/rexml/doctype.rb +22 -24
  9. data/lib/rexml/document.rb +185 -129
  10. data/lib/rexml/dtd/attlistdecl.rb +7 -7
  11. data/lib/rexml/dtd/dtd.rb +41 -41
  12. data/lib/rexml/dtd/elementdecl.rb +13 -13
  13. data/lib/rexml/dtd/entitydecl.rb +49 -49
  14. data/lib/rexml/dtd/notationdecl.rb +32 -32
  15. data/lib/rexml/element.rb +122 -107
  16. data/lib/rexml/encoding.rb +37 -58
  17. data/lib/rexml/entity.rb +144 -144
  18. data/lib/rexml/formatters/default.rb +6 -4
  19. data/lib/rexml/formatters/pretty.rb +11 -8
  20. data/lib/rexml/formatters/transitive.rb +4 -3
  21. data/lib/rexml/functions.rb +33 -21
  22. data/lib/rexml/instruction.rb +49 -49
  23. data/lib/rexml/light/node.rb +190 -191
  24. data/lib/rexml/namespace.rb +39 -39
  25. data/lib/rexml/node.rb +38 -38
  26. data/lib/rexml/output.rb +17 -12
  27. data/lib/rexml/parent.rb +26 -25
  28. data/lib/rexml/parseexception.rb +4 -4
  29. data/lib/rexml/parsers/baseparser.rb +90 -61
  30. data/lib/rexml/parsers/lightparser.rb +41 -43
  31. data/lib/rexml/parsers/pullparser.rb +1 -1
  32. data/lib/rexml/parsers/sax2parser.rb +233 -198
  33. data/lib/rexml/parsers/streamparser.rb +6 -2
  34. data/lib/rexml/parsers/treeparser.rb +9 -6
  35. data/lib/rexml/parsers/ultralightparser.rb +40 -40
  36. data/lib/rexml/parsers/xpathparser.rb +51 -52
  37. data/lib/rexml/quickpath.rb +247 -248
  38. data/lib/rexml/rexml.rb +9 -10
  39. data/lib/rexml/sax2listener.rb +92 -92
  40. data/lib/rexml/security.rb +27 -0
  41. data/lib/rexml/source.rb +95 -50
  42. data/lib/rexml/streamlistener.rb +90 -90
  43. data/lib/rexml/syncenumerator.rb +3 -4
  44. data/lib/rexml/text.rb +157 -76
  45. data/lib/rexml/validation/relaxng.rb +18 -18
  46. data/lib/rexml/validation/validation.rb +5 -5
  47. data/lib/rexml/xmldecl.rb +59 -63
  48. data/lib/rexml/xmltokens.rb +14 -14
  49. data/lib/rexml/xpath.rb +67 -53
  50. data/lib/rexml/xpath_parser.rb +49 -38
  51. data/lib/rubysl/rexml.rb +1 -0
  52. data/lib/rubysl/rexml/version.rb +1 -1
  53. data/rubysl-rexml.gemspec +3 -1
  54. metadata +19 -28
  55. data/lib/rexml/encodings/CP-1252.rb +0 -103
  56. data/lib/rexml/encodings/EUC-JP.rb +0 -35
  57. data/lib/rexml/encodings/ICONV.rb +0 -22
  58. data/lib/rexml/encodings/ISO-8859-1.rb +0 -7
  59. data/lib/rexml/encodings/ISO-8859-15.rb +0 -72
  60. data/lib/rexml/encodings/SHIFT-JIS.rb +0 -37
  61. data/lib/rexml/encodings/SHIFT_JIS.rb +0 -1
  62. data/lib/rexml/encodings/UNILE.rb +0 -34
  63. data/lib/rexml/encodings/US-ASCII.rb +0 -30
  64. data/lib/rexml/encodings/UTF-16.rb +0 -35
  65. data/lib/rexml/encodings/UTF-8.rb +0 -18
@@ -1,17 +1,17 @@
1
1
  require "rexml/child"
2
2
  module REXML
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)
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
- def initialize match
12
- @name = match[1]
13
- @rest = match[2]
14
- end
15
- end
16
- end
11
+ def initialize match
12
+ @name = match[1]
13
+ @rest = match[2]
14
+ end
15
+ end
16
+ end
17
17
  end
@@ -1,56 +1,56 @@
1
1
  require "rexml/child"
2
2
  module REXML
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
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
- def to_s
38
- rv = "<!ENTITY #@name "
39
- rv << "#@middle " if @middle.size > 0
40
- rv << @content
41
- rv
42
- end
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
- def write( output, indent )
44
+ def write( output, indent )
45
45
  indent( output, indent )
46
- output << to_s
47
- end
46
+ output << to_s
47
+ end
48
48
 
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
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
- 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
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
- def to_s
24
- "<!NOTATION #@name #@middle #@rest>"
25
- end
23
+ def to_s
24
+ "<!NOTATION #@name #@middle #@rest>"
25
+ end
26
26
 
27
- def write( output, indent )
27
+ def write( output, indent )
28
28
  indent( output, indent )
29
- output << to_s
30
- end
29
+ output << to_s
30
+ end
31
31
 
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
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"; # The default name
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
- # 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.
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
- # If supplied, must be a hash containing context items. Context items
44
- # include:
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]=Attribute.new(key,value,self)
300
- end if attrs.kind_of? Hash
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
- prefix = namespaces.index(namespace) if namespace
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
- attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" )
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
- # output an object which supports '<< string'; this is where the
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
- # Internet Explorer is the worst piece of crap to have ever been
666
- # written, with the possible exception of Windows itself. Since IE is
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(writer=$stdout, indent=-1, transitive=false, ie_hack=false)
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
- # return element if element.kind_of? Element
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, &block)
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, &block )
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, &block )
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='&lt;'/>"
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
- values.flatten
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? # Delete the named attribute
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
- element_document = @element.document
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 => old_attr,
1106
- value.prefix => value }
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
- res = super(name)
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
- return attribute
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
- nil
1239
+ result
1225
1240
  end
1226
1241
  end
1227
1242
  end