rubysl-rexml 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/lib/rexml/attlistdecl.rb +62 -0
  9. data/lib/rexml/attribute.rb +185 -0
  10. data/lib/rexml/cdata.rb +67 -0
  11. data/lib/rexml/child.rb +96 -0
  12. data/lib/rexml/comment.rb +80 -0
  13. data/lib/rexml/doctype.rb +271 -0
  14. data/lib/rexml/document.rb +230 -0
  15. data/lib/rexml/dtd/attlistdecl.rb +10 -0
  16. data/lib/rexml/dtd/dtd.rb +51 -0
  17. data/lib/rexml/dtd/elementdecl.rb +17 -0
  18. data/lib/rexml/dtd/entitydecl.rb +56 -0
  19. data/lib/rexml/dtd/notationdecl.rb +39 -0
  20. data/lib/rexml/element.rb +1227 -0
  21. data/lib/rexml/encoding.rb +71 -0
  22. data/lib/rexml/encodings/CP-1252.rb +103 -0
  23. data/lib/rexml/encodings/EUC-JP.rb +35 -0
  24. data/lib/rexml/encodings/ICONV.rb +22 -0
  25. data/lib/rexml/encodings/ISO-8859-1.rb +7 -0
  26. data/lib/rexml/encodings/ISO-8859-15.rb +72 -0
  27. data/lib/rexml/encodings/SHIFT-JIS.rb +37 -0
  28. data/lib/rexml/encodings/SHIFT_JIS.rb +1 -0
  29. data/lib/rexml/encodings/UNILE.rb +34 -0
  30. data/lib/rexml/encodings/US-ASCII.rb +30 -0
  31. data/lib/rexml/encodings/UTF-16.rb +35 -0
  32. data/lib/rexml/encodings/UTF-8.rb +18 -0
  33. data/lib/rexml/entity.rb +166 -0
  34. data/lib/rexml/formatters/default.rb +109 -0
  35. data/lib/rexml/formatters/pretty.rb +138 -0
  36. data/lib/rexml/formatters/transitive.rb +56 -0
  37. data/lib/rexml/functions.rb +382 -0
  38. data/lib/rexml/instruction.rb +70 -0
  39. data/lib/rexml/light/node.rb +196 -0
  40. data/lib/rexml/namespace.rb +47 -0
  41. data/lib/rexml/node.rb +75 -0
  42. data/lib/rexml/output.rb +24 -0
  43. data/lib/rexml/parent.rb +166 -0
  44. data/lib/rexml/parseexception.rb +51 -0
  45. data/lib/rexml/parsers/baseparser.rb +503 -0
  46. data/lib/rexml/parsers/lightparser.rb +60 -0
  47. data/lib/rexml/parsers/pullparser.rb +196 -0
  48. data/lib/rexml/parsers/sax2parser.rb +238 -0
  49. data/lib/rexml/parsers/streamparser.rb +46 -0
  50. data/lib/rexml/parsers/treeparser.rb +97 -0
  51. data/lib/rexml/parsers/ultralightparser.rb +56 -0
  52. data/lib/rexml/parsers/xpathparser.rb +698 -0
  53. data/lib/rexml/quickpath.rb +266 -0
  54. data/lib/rexml/rexml.rb +32 -0
  55. data/lib/rexml/sax2listener.rb +97 -0
  56. data/lib/rexml/source.rb +251 -0
  57. data/lib/rexml/streamlistener.rb +92 -0
  58. data/lib/rexml/syncenumerator.rb +33 -0
  59. data/lib/rexml/text.rb +344 -0
  60. data/lib/rexml/undefinednamespaceexception.rb +8 -0
  61. data/lib/rexml/validation/relaxng.rb +559 -0
  62. data/lib/rexml/validation/validation.rb +155 -0
  63. data/lib/rexml/validation/validationexception.rb +9 -0
  64. data/lib/rexml/xmldecl.rb +119 -0
  65. data/lib/rexml/xmltokens.rb +18 -0
  66. data/lib/rexml/xpath.rb +66 -0
  67. data/lib/rexml/xpath_parser.rb +792 -0
  68. data/lib/rubysl/rexml.rb +1 -0
  69. data/lib/rubysl/rexml/version.rb +5 -0
  70. data/rubysl-rexml.gemspec +23 -0
  71. data/spec/attribute/clone_spec.rb +10 -0
  72. data/spec/attribute/element_spec.rb +22 -0
  73. data/spec/attribute/equal_value_spec.rb +17 -0
  74. data/spec/attribute/hash_spec.rb +12 -0
  75. data/spec/attribute/initialize_spec.rb +28 -0
  76. data/spec/attribute/inspect_spec.rb +19 -0
  77. data/spec/attribute/namespace_spec.rb +23 -0
  78. data/spec/attribute/node_type_spec.rb +9 -0
  79. data/spec/attribute/prefix_spec.rb +17 -0
  80. data/spec/attribute/remove_spec.rb +19 -0
  81. data/spec/attribute/to_s_spec.rb +13 -0
  82. data/spec/attribute/to_string_spec.rb +14 -0
  83. data/spec/attribute/value_spec.rb +14 -0
  84. data/spec/attribute/write_spec.rb +22 -0
  85. data/spec/attribute/xpath_spec.rb +19 -0
  86. data/spec/attributes/add_spec.rb +6 -0
  87. data/spec/attributes/append_spec.rb +6 -0
  88. data/spec/attributes/delete_all_spec.rb +30 -0
  89. data/spec/attributes/delete_spec.rb +26 -0
  90. data/spec/attributes/each_attribute_spec.rb +24 -0
  91. data/spec/attributes/each_spec.rb +24 -0
  92. data/spec/attributes/element_reference_spec.rb +18 -0
  93. data/spec/attributes/element_set_spec.rb +25 -0
  94. data/spec/attributes/get_attribute_ns_spec.rb +13 -0
  95. data/spec/attributes/get_attribute_spec.rb +28 -0
  96. data/spec/attributes/initialize_spec.rb +18 -0
  97. data/spec/attributes/length_spec.rb +6 -0
  98. data/spec/attributes/namespaces_spec.rb +5 -0
  99. data/spec/attributes/prefixes_spec.rb +23 -0
  100. data/spec/attributes/shared/add.rb +17 -0
  101. data/spec/attributes/shared/length.rb +12 -0
  102. data/spec/attributes/size_spec.rb +6 -0
  103. data/spec/attributes/to_a_spec.rb +20 -0
  104. data/spec/cdata/clone_spec.rb +9 -0
  105. data/spec/cdata/initialize_spec.rb +24 -0
  106. data/spec/cdata/shared/to_s.rb +11 -0
  107. data/spec/cdata/to_s_spec.rb +6 -0
  108. data/spec/cdata/value_spec.rb +6 -0
  109. data/spec/document/add_element_spec.rb +30 -0
  110. data/spec/document/add_spec.rb +60 -0
  111. data/spec/document/clone_spec.rb +19 -0
  112. data/spec/document/doctype_spec.rb +14 -0
  113. data/spec/document/encoding_spec.rb +21 -0
  114. data/spec/document/expanded_name_spec.rb +15 -0
  115. data/spec/document/new_spec.rb +37 -0
  116. data/spec/document/node_type_spec.rb +7 -0
  117. data/spec/document/root_spec.rb +11 -0
  118. data/spec/document/stand_alone_spec.rb +18 -0
  119. data/spec/document/version_spec.rb +13 -0
  120. data/spec/document/write_spec.rb +38 -0
  121. data/spec/document/xml_decl_spec.rb +14 -0
  122. data/spec/element/add_attribute_spec.rb +40 -0
  123. data/spec/element/add_attributes_spec.rb +21 -0
  124. data/spec/element/add_element_spec.rb +38 -0
  125. data/spec/element/add_namespace_spec.rb +23 -0
  126. data/spec/element/add_text_spec.rb +23 -0
  127. data/spec/element/attribute_spec.rb +16 -0
  128. data/spec/element/attributes_spec.rb +18 -0
  129. data/spec/element/cdatas_spec.rb +23 -0
  130. data/spec/element/clone_spec.rb +28 -0
  131. data/spec/element/comments_spec.rb +20 -0
  132. data/spec/element/delete_attribute_spec.rb +38 -0
  133. data/spec/element/delete_element_spec.rb +50 -0
  134. data/spec/element/delete_namespace_spec.rb +24 -0
  135. data/spec/element/document_spec.rb +17 -0
  136. data/spec/element/each_element_with_attribute_spec.rb +34 -0
  137. data/spec/element/each_element_with_text_spec.rb +30 -0
  138. data/spec/element/get_text_spec.rb +17 -0
  139. data/spec/element/has_attributes_spec.rb +16 -0
  140. data/spec/element/has_elements_spec.rb +17 -0
  141. data/spec/element/has_text_spec.rb +15 -0
  142. data/spec/element/inspect_spec.rb +26 -0
  143. data/spec/element/instructions_spec.rb +20 -0
  144. data/spec/element/namespace_spec.rb +26 -0
  145. data/spec/element/namespaces_spec.rb +31 -0
  146. data/spec/element/new_spec.rb +34 -0
  147. data/spec/element/next_element_spec.rb +18 -0
  148. data/spec/element/node_type_spec.rb +7 -0
  149. data/spec/element/prefixes_spec.rb +22 -0
  150. data/spec/element/previous_element_spec.rb +19 -0
  151. data/spec/element/raw_spec.rb +23 -0
  152. data/spec/element/root_spec.rb +27 -0
  153. data/spec/element/text_spec.rb +45 -0
  154. data/spec/element/texts_spec.rb +15 -0
  155. data/spec/element/whitespace_spec.rb +22 -0
  156. data/spec/node/each_recursive_spec.rb +20 -0
  157. data/spec/node/find_first_recursive_spec.rb +24 -0
  158. data/spec/node/index_in_parent_spec.rb +14 -0
  159. data/spec/node/next_sibling_node_spec.rb +20 -0
  160. data/spec/node/parent_spec.rb +20 -0
  161. data/spec/node/previous_sibling_node_spec.rb +20 -0
  162. data/spec/shared/each_element.rb +35 -0
  163. data/spec/shared/elements_to_a.rb +35 -0
  164. data/spec/text/append_spec.rb +9 -0
  165. data/spec/text/clone_spec.rb +9 -0
  166. data/spec/text/comparison_spec.rb +24 -0
  167. data/spec/text/empty_spec.rb +11 -0
  168. data/spec/text/indent_text_spec.rb +23 -0
  169. data/spec/text/inspect_spec.rb +7 -0
  170. data/spec/text/new_spec.rb +48 -0
  171. data/spec/text/node_type_spec.rb +7 -0
  172. data/spec/text/normalize_spec.rb +7 -0
  173. data/spec/text/read_with_substitution_spec.rb +12 -0
  174. data/spec/text/to_s_spec.rb +17 -0
  175. data/spec/text/unnormalize_spec.rb +7 -0
  176. data/spec/text/value_spec.rb +36 -0
  177. data/spec/text/wrap_spec.rb +20 -0
  178. data/spec/text/write_with_substitution_spec.rb +32 -0
  179. metadata +385 -0
@@ -0,0 +1,196 @@
1
+ require 'rexml/xmltokens'
2
+ require 'rexml/light/node'
3
+
4
+ # [ :element, parent, name, attributes, children* ]
5
+ # a = Node.new
6
+ # a << "B" # => <a>B</a>
7
+ # a.b # => <a>B<b/></a>
8
+ # a.b[1] # => <a>B<b/><b/><a>
9
+ # a.b[1]["x"] = "y" # => <a>B<b/><b x="y"/></a>
10
+ # a.b[0].c # => <a>B<b><c/></b><b x="y"/></a>
11
+ # a.b.c << "D" # => <a>B<b><c>D</c></b><b x="y"/></a>
12
+ module REXML
13
+ module Light
14
+ # Represents a tagged XML element. Elements are characterized by
15
+ # having children, attributes, and names, and can themselves be
16
+ # children.
17
+ class Node
18
+ NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u
19
+ PARENTS = [ :element, :document, :doctype ]
20
+ # Create a new element.
21
+ def initialize node=nil
22
+ @node = node
23
+ if node.kind_of? String
24
+ node = [ :text, node ]
25
+ elsif node.nil?
26
+ node = [ :document, nil, nil ]
27
+ elsif node[0] == :start_element
28
+ node[0] = :element
29
+ elsif node[0] == :start_doctype
30
+ node[0] = :doctype
31
+ elsif node[0] == :start_document
32
+ node[0] = :document
33
+ end
34
+ end
35
+
36
+ def size
37
+ if PARENTS.include? @node[0]
38
+ @node[-1].size
39
+ else
40
+ 0
41
+ end
42
+ end
43
+
44
+ def each( &block )
45
+ size.times { |x| yield( at(x+4) ) }
46
+ end
47
+
48
+ def name
49
+ at(2)
50
+ end
51
+
52
+ def name=( name_str, ns=nil )
53
+ pfx = ''
54
+ pfx = "#{prefix(ns)}:" if ns
55
+ _old_put(2, "#{pfx}#{name_str}")
56
+ end
57
+
58
+ def parent=( node )
59
+ _old_put(1,node)
60
+ end
61
+
62
+ def local_name
63
+ namesplit
64
+ @name
65
+ end
66
+
67
+ def local_name=( name_str )
68
+ _old_put( 1, "#@prefix:#{name_str}" )
69
+ end
70
+
71
+ def prefix( namespace=nil )
72
+ prefix_of( self, namespace )
73
+ end
74
+
75
+ def namespace( prefix=prefix() )
76
+ namespace_of( self, prefix )
77
+ end
78
+
79
+ def namespace=( namespace )
80
+ @prefix = prefix( namespace )
81
+ pfx = ''
82
+ pfx = "#@prefix:" if @prefix.size > 0
83
+ _old_put(1, "#{pfx}#@name")
84
+ end
85
+
86
+ def []( reference, ns=nil )
87
+ if reference.kind_of? String
88
+ pfx = ''
89
+ pfx = "#{prefix(ns)}:" if ns
90
+ at(3)["#{pfx}#{reference}"]
91
+ elsif reference.kind_of? Range
92
+ _old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) )
93
+ else
94
+ _old_get( 4+reference )
95
+ end
96
+ end
97
+
98
+ def =~( path )
99
+ XPath.match( self, path )
100
+ end
101
+
102
+ # Doesn't handle namespaces yet
103
+ def []=( reference, ns, value=nil )
104
+ if reference.kind_of? String
105
+ value = ns unless value
106
+ at( 3 )[reference] = value
107
+ elsif reference.kind_of? Range
108
+ _old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns )
109
+ else
110
+ if value
111
+ _old_put( 4+reference, ns, value )
112
+ else
113
+ _old_put( 4+reference, ns )
114
+ end
115
+ end
116
+ end
117
+
118
+ # Append a child to this element, optionally under a provided namespace.
119
+ # The namespace argument is ignored if the element argument is an Element
120
+ # object. Otherwise, the element argument is a string, the namespace (if
121
+ # provided) is the namespace the element is created in.
122
+ def << element
123
+ if node_type() == :text
124
+ at(-1) << element
125
+ else
126
+ newnode = Node.new( element )
127
+ newnode.parent = self
128
+ self.push( newnode )
129
+ end
130
+ at(-1)
131
+ end
132
+
133
+ def node_type
134
+ _old_get(0)
135
+ end
136
+
137
+ def text=( foo )
138
+ replace = at(4).kind_of?(String)? 1 : 0
139
+ self._old_put(4,replace, normalizefoo)
140
+ end
141
+
142
+ def root
143
+ context = self
144
+ context = context.at(1) while context.at(1)
145
+ end
146
+
147
+ def has_name?( name, namespace = '' )
148
+ at(3) == name and namespace() == namespace
149
+ end
150
+
151
+ def children
152
+ self
153
+ end
154
+
155
+ def parent
156
+ at(1)
157
+ end
158
+
159
+ def to_s
160
+
161
+ end
162
+
163
+ private
164
+
165
+ def namesplit
166
+ return if @name.defined?
167
+ at(2) =~ NAMESPLIT
168
+ @prefix = '' || $1
169
+ @name = $2
170
+ end
171
+
172
+ def namespace_of( node, prefix=nil )
173
+ if not prefix
174
+ name = at(2)
175
+ name =~ NAMESPLIT
176
+ prefix = $1
177
+ end
178
+ to_find = 'xmlns'
179
+ to_find = "xmlns:#{prefix}" if not prefix.nil?
180
+ ns = at(3)[ to_find ]
181
+ ns ? ns : namespace_of( @node[0], prefix )
182
+ end
183
+
184
+ def prefix_of( node, namespace=nil )
185
+ if not namespace
186
+ name = node.name
187
+ name =~ NAMESPLIT
188
+ $1
189
+ else
190
+ ns = at(3).find { |k,v| v == namespace }
191
+ ns ? ns : prefix_of( node.parent, namespace )
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,47 @@
1
+ require 'rexml/xmltokens'
2
+
3
+ module REXML
4
+ # Adds named attributes to an object.
5
+ module Namespace
6
+ # The name of the object, valid if set
7
+ attr_reader :name, :expanded_name
8
+ # The expanded name of the object, valid if name is set
9
+ attr_accessor :prefix
10
+ include XMLTokens
11
+ NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u
12
+
13
+ # Sets the name and the expanded name
14
+ def name=( name )
15
+ @expanded_name = name
16
+ name =~ NAMESPLIT
17
+ if $1
18
+ @prefix = $1
19
+ else
20
+ @prefix = ""
21
+ @namespace = ""
22
+ end
23
+ @name = $2
24
+ end
25
+
26
+ # Compares names optionally WITH namespaces
27
+ def has_name?( other, ns=nil )
28
+ if ns
29
+ return (namespace() == ns and name() == other)
30
+ elsif other.include? ":"
31
+ return fully_expanded_name == other
32
+ else
33
+ return name == other
34
+ end
35
+ end
36
+
37
+ alias :local_name :name
38
+
39
+ # Fully expand the name, even if the prefix wasn't specified in the
40
+ # source file.
41
+ def fully_expanded_name
42
+ ns = prefix
43
+ return "#{ns}:#@name" if ns.size > 0
44
+ return @name
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,75 @@
1
+ require "rexml/parseexception"
2
+ require "rexml/formatters/pretty"
3
+ require "rexml/formatters/default"
4
+
5
+ module REXML
6
+ # Represents a node in the tree. Nodes are never encountered except as
7
+ # superclasses of other objects. Nodes have siblings.
8
+ module Node
9
+ # @return the next sibling (nil if unset)
10
+ def next_sibling_node
11
+ return nil if @parent.nil?
12
+ @parent[ @parent.index(self) + 1 ]
13
+ end
14
+
15
+ # @return the previous sibling (nil if unset)
16
+ def previous_sibling_node
17
+ return nil if @parent.nil?
18
+ ind = @parent.index(self)
19
+ return nil if ind == 0
20
+ @parent[ ind - 1 ]
21
+ end
22
+
23
+ # indent::
24
+ # *DEPRECATED* This parameter is now ignored. See the formatters in the
25
+ # REXML::Formatters package for changing the output style.
26
+ def to_s indent=nil
27
+ unless indent.nil?
28
+ Kernel.warn( "#{self.class.name}.to_s(indent) parameter is deprecated" )
29
+ f = REXML::Formatters::Pretty.new( indent )
30
+ f.write( self, rv = "" )
31
+ else
32
+ f = REXML::Formatters::Default.new
33
+ f.write( self, rv = "" )
34
+ end
35
+ return rv
36
+ end
37
+
38
+ def indent to, ind
39
+ if @parent and @parent.context and not @parent.context[:indentstyle].nil? then
40
+ indentstyle = @parent.context[:indentstyle]
41
+ else
42
+ indentstyle = ' '
43
+ end
44
+ to << indentstyle*ind unless ind<1
45
+ end
46
+
47
+ def parent?
48
+ false;
49
+ end
50
+
51
+
52
+ # Visit all subnodes of +self+ recursively
53
+ def each_recursive(&block) # :yields: node
54
+ self.elements.each {|node|
55
+ block.call(node)
56
+ node.each_recursive(&block)
57
+ }
58
+ end
59
+
60
+ # Find (and return) first subnode (recursively) for which the block
61
+ # evaluates to true. Returns +nil+ if none was found.
62
+ def find_first_recursive(&block) # :yields: node
63
+ each_recursive {|node|
64
+ return node if block.call(node)
65
+ }
66
+ return nil
67
+ end
68
+
69
+ # Returns the position that +self+ holds in its parent's array, indexed
70
+ # from 1.
71
+ def index_in_parent
72
+ parent.index(self)+1
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,24 @@
1
+ require 'rexml/encoding'
2
+
3
+ module REXML
4
+ class Output
5
+ include Encoding
6
+
7
+ attr_reader :encoding
8
+
9
+ def initialize real_IO, encd="iso-8859-1"
10
+ @output = real_IO
11
+ self.encoding = encd
12
+
13
+ @to_utf = encd == UTF_8 ? false : true
14
+ end
15
+
16
+ def <<( content )
17
+ @output << (@to_utf ? self.encode(content) : content)
18
+ end
19
+
20
+ def to_s
21
+ "Output[#{encoding}]"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,166 @@
1
+ require "rexml/child"
2
+
3
+ module REXML
4
+ # A parent has children, and has methods for accessing them. The Parent
5
+ # class is never encountered except as the superclass for some other
6
+ # object.
7
+ class Parent < Child
8
+ include Enumerable
9
+
10
+ # Constructor
11
+ # @param parent if supplied, will be set as the parent of this object
12
+ def initialize parent=nil
13
+ super(parent)
14
+ @children = []
15
+ end
16
+
17
+ def add( object )
18
+ #puts "PARENT GOTS #{size} CHILDREN"
19
+ object.parent = self
20
+ @children << object
21
+ #puts "PARENT NOW GOTS #{size} CHILDREN"
22
+ object
23
+ end
24
+
25
+ alias :push :add
26
+ alias :<< :push
27
+
28
+ def unshift( object )
29
+ object.parent = self
30
+ @children.unshift object
31
+ end
32
+
33
+ def delete( object )
34
+ found = false
35
+ @children.delete_if {|c| c.equal?(object) and found = true }
36
+ object.parent = nil if found
37
+ end
38
+
39
+ def each(&block)
40
+ @children.each(&block)
41
+ end
42
+
43
+ def delete_if( &block )
44
+ @children.delete_if(&block)
45
+ end
46
+
47
+ def delete_at( index )
48
+ @children.delete_at index
49
+ end
50
+
51
+ def each_index( &block )
52
+ @children.each_index(&block)
53
+ end
54
+
55
+ # Fetches a child at a given index
56
+ # @param index the Integer index of the child to fetch
57
+ def []( index )
58
+ @children[index]
59
+ end
60
+
61
+ alias :each_child :each
62
+
63
+
64
+
65
+ # Set an index entry. See Array.[]=
66
+ # @param index the index of the element to set
67
+ # @param opt either the object to set, or an Integer length
68
+ # @param child if opt is an Integer, this is the child to set
69
+ # @return the parent (self)
70
+ def []=( *args )
71
+ args[-1].parent = self
72
+ @children[*args[0..-2]] = args[-1]
73
+ end
74
+
75
+ # Inserts an child before another child
76
+ # @param child1 this is either an xpath or an Element. If an Element,
77
+ # child2 will be inserted before child1 in the child list of the parent.
78
+ # If an xpath, child2 will be inserted before the first child to match
79
+ # the xpath.
80
+ # @param child2 the child to insert
81
+ # @return the parent (self)
82
+ def insert_before( child1, child2 )
83
+ if child1.kind_of? String
84
+ child1 = XPath.first( self, child1 )
85
+ child1.parent.insert_before child1, child2
86
+ else
87
+ ind = index(child1)
88
+ child2.parent.delete(child2) if child2.parent
89
+ @children[ind,0] = child2
90
+ child2.parent = self
91
+ end
92
+ self
93
+ end
94
+
95
+ # Inserts an child after another child
96
+ # @param child1 this is either an xpath or an Element. If an Element,
97
+ # child2 will be inserted after child1 in the child list of the parent.
98
+ # If an xpath, child2 will be inserted after the first child to match
99
+ # the xpath.
100
+ # @param child2 the child to insert
101
+ # @return the parent (self)
102
+ def insert_after( child1, child2 )
103
+ if child1.kind_of? String
104
+ child1 = XPath.first( self, child1 )
105
+ child1.parent.insert_after child1, child2
106
+ else
107
+ ind = index(child1)+1
108
+ child2.parent.delete(child2) if child2.parent
109
+ @children[ind,0] = child2
110
+ child2.parent = self
111
+ end
112
+ self
113
+ end
114
+
115
+ def to_a
116
+ @children.dup
117
+ end
118
+
119
+ # Fetches the index of a given child
120
+ # @param child the child to get the index of
121
+ # @return the index of the child, or nil if the object is not a child
122
+ # of this parent.
123
+ def index( child )
124
+ count = -1
125
+ @children.find { |i| count += 1 ; i.hash == child.hash }
126
+ count
127
+ end
128
+
129
+ # @return the number of children of this parent
130
+ def size
131
+ @children.size
132
+ end
133
+
134
+ alias :length :size
135
+
136
+ # Replaces one child with another, making sure the nodelist is correct
137
+ # @param to_replace the child to replace (must be a Child)
138
+ # @param replacement the child to insert into the nodelist (must be a
139
+ # Child)
140
+ def replace_child( to_replace, replacement )
141
+ @children.map! {|c| c.equal?( to_replace ) ? replacement : c }
142
+ to_replace.parent = nil
143
+ replacement.parent = self
144
+ end
145
+
146
+ # Deeply clones this object. This creates a complete duplicate of this
147
+ # Parent, including all descendants.
148
+ def deep_clone
149
+ cl = clone()
150
+ each do |child|
151
+ if child.kind_of? Parent
152
+ cl << child.deep_clone
153
+ else
154
+ cl << child.clone
155
+ end
156
+ end
157
+ cl
158
+ end
159
+
160
+ alias :children :to_a
161
+
162
+ def parent?
163
+ true
164
+ end
165
+ end
166
+ end