nokogiri 1.1.1-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of nokogiri might be problematic. Click here for more details.
- data/History.ja.txt +99 -0
- data/History.txt +99 -0
- data/Manifest.txt +141 -0
- data/README.ja.txt +100 -0
- data/README.txt +109 -0
- data/Rakefile +354 -0
- data/ext/nokogiri/extconf.rb +93 -0
- data/ext/nokogiri/html_document.c +86 -0
- data/ext/nokogiri/html_document.h +10 -0
- data/ext/nokogiri/html_sax_parser.c +36 -0
- data/ext/nokogiri/html_sax_parser.h +11 -0
- data/ext/nokogiri/native.c +41 -0
- data/ext/nokogiri/native.h +50 -0
- data/ext/nokogiri/xml_cdata.c +44 -0
- data/ext/nokogiri/xml_cdata.h +9 -0
- data/ext/nokogiri/xml_comment.c +42 -0
- data/ext/nokogiri/xml_comment.h +9 -0
- data/ext/nokogiri/xml_document.c +206 -0
- data/ext/nokogiri/xml_document.h +10 -0
- data/ext/nokogiri/xml_dtd.c +121 -0
- data/ext/nokogiri/xml_dtd.h +8 -0
- data/ext/nokogiri/xml_io.c +17 -0
- data/ext/nokogiri/xml_io.h +9 -0
- data/ext/nokogiri/xml_node.c +727 -0
- data/ext/nokogiri/xml_node.h +13 -0
- data/ext/nokogiri/xml_node_set.c +118 -0
- data/ext/nokogiri/xml_node_set.h +9 -0
- data/ext/nokogiri/xml_reader.c +465 -0
- data/ext/nokogiri/xml_reader.h +10 -0
- data/ext/nokogiri/xml_sax_parser.c +201 -0
- data/ext/nokogiri/xml_sax_parser.h +10 -0
- data/ext/nokogiri/xml_syntax_error.c +199 -0
- data/ext/nokogiri/xml_syntax_error.h +11 -0
- data/ext/nokogiri/xml_text.c +40 -0
- data/ext/nokogiri/xml_text.h +9 -0
- data/ext/nokogiri/xml_xpath.c +53 -0
- data/ext/nokogiri/xml_xpath.h +11 -0
- data/ext/nokogiri/xml_xpath_context.c +214 -0
- data/ext/nokogiri/xml_xpath_context.h +9 -0
- data/ext/nokogiri/xslt_stylesheet.c +123 -0
- data/ext/nokogiri/xslt_stylesheet.h +9 -0
- data/lib/action-nokogiri.rb +30 -0
- data/lib/nokogiri.rb +72 -0
- data/lib/nokogiri/css.rb +25 -0
- data/lib/nokogiri/css/generated_parser.rb +721 -0
- data/lib/nokogiri/css/generated_tokenizer.rb +159 -0
- data/lib/nokogiri/css/node.rb +97 -0
- data/lib/nokogiri/css/parser.rb +64 -0
- data/lib/nokogiri/css/parser.y +216 -0
- data/lib/nokogiri/css/syntax_error.rb +6 -0
- data/lib/nokogiri/css/tokenizer.rb +9 -0
- data/lib/nokogiri/css/tokenizer.rex +63 -0
- data/lib/nokogiri/css/xpath_visitor.rb +168 -0
- data/lib/nokogiri/decorators.rb +2 -0
- data/lib/nokogiri/decorators/hpricot.rb +3 -0
- data/lib/nokogiri/decorators/hpricot/node.rb +56 -0
- data/lib/nokogiri/decorators/hpricot/node_set.rb +54 -0
- data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +28 -0
- data/lib/nokogiri/decorators/slop.rb +31 -0
- data/lib/nokogiri/hpricot.rb +51 -0
- data/lib/nokogiri/html.rb +105 -0
- data/lib/nokogiri/html/builder.rb +9 -0
- data/lib/nokogiri/html/document.rb +9 -0
- data/lib/nokogiri/html/sax/parser.rb +21 -0
- data/lib/nokogiri/version.rb +3 -0
- data/lib/nokogiri/xml.rb +83 -0
- data/lib/nokogiri/xml/after_handler.rb +18 -0
- data/lib/nokogiri/xml/attr.rb +10 -0
- data/lib/nokogiri/xml/before_handler.rb +33 -0
- data/lib/nokogiri/xml/builder.rb +84 -0
- data/lib/nokogiri/xml/cdata.rb +9 -0
- data/lib/nokogiri/xml/comment.rb +6 -0
- data/lib/nokogiri/xml/document.rb +55 -0
- data/lib/nokogiri/xml/dtd.rb +6 -0
- data/lib/nokogiri/xml/element.rb +6 -0
- data/lib/nokogiri/xml/entity_declaration.rb +9 -0
- data/lib/nokogiri/xml/node.rb +333 -0
- data/lib/nokogiri/xml/node_set.rb +197 -0
- data/lib/nokogiri/xml/notation.rb +6 -0
- data/lib/nokogiri/xml/reader.rb +20 -0
- data/lib/nokogiri/xml/sax.rb +9 -0
- data/lib/nokogiri/xml/sax/document.rb +59 -0
- data/lib/nokogiri/xml/sax/parser.rb +37 -0
- data/lib/nokogiri/xml/syntax_error.rb +21 -0
- data/lib/nokogiri/xml/text.rb +6 -0
- data/lib/nokogiri/xml/xpath.rb +10 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +8 -0
- data/lib/nokogiri/xml/xpath_context.rb +14 -0
- data/lib/nokogiri/xslt.rb +28 -0
- data/lib/nokogiri/xslt/stylesheet.rb +6 -0
- data/test/css/test_nthiness.rb +159 -0
- data/test/css/test_parser.rb +237 -0
- data/test/css/test_tokenizer.rb +162 -0
- data/test/css/test_xpath_visitor.rb +64 -0
- data/test/files/dont_hurt_em_why.xml +422 -0
- data/test/files/exslt.xml +8 -0
- data/test/files/exslt.xslt +35 -0
- data/test/files/staff.xml +59 -0
- data/test/files/staff.xslt +32 -0
- data/test/files/tlm.html +850 -0
- data/test/helper.rb +78 -0
- data/test/hpricot/files/basic.xhtml +17 -0
- data/test/hpricot/files/boingboing.html +2266 -0
- data/test/hpricot/files/cy0.html +3653 -0
- data/test/hpricot/files/immob.html +400 -0
- data/test/hpricot/files/pace_application.html +1320 -0
- data/test/hpricot/files/tenderlove.html +16 -0
- data/test/hpricot/files/uswebgen.html +220 -0
- data/test/hpricot/files/utf8.html +1054 -0
- data/test/hpricot/files/week9.html +1723 -0
- data/test/hpricot/files/why.xml +19 -0
- data/test/hpricot/load_files.rb +11 -0
- data/test/hpricot/test_alter.rb +67 -0
- data/test/hpricot/test_builder.rb +27 -0
- data/test/hpricot/test_parser.rb +426 -0
- data/test/hpricot/test_paths.rb +15 -0
- data/test/hpricot/test_preserved.rb +77 -0
- data/test/hpricot/test_xml.rb +30 -0
- data/test/html/sax/test_parser.rb +27 -0
- data/test/html/test_builder.rb +89 -0
- data/test/html/test_document.rb +150 -0
- data/test/html/test_node.rb +21 -0
- data/test/test_convert_xpath.rb +185 -0
- data/test/test_css_cache.rb +57 -0
- data/test/test_gc.rb +15 -0
- data/test/test_memory_leak.rb +38 -0
- data/test/test_nokogiri.rb +97 -0
- data/test/test_reader.rb +222 -0
- data/test/test_xslt_transforms.rb +93 -0
- data/test/xml/sax/test_parser.rb +95 -0
- data/test/xml/test_attr.rb +15 -0
- data/test/xml/test_builder.rb +16 -0
- data/test/xml/test_cdata.rb +18 -0
- data/test/xml/test_comment.rb +16 -0
- data/test/xml/test_document.rb +195 -0
- data/test/xml/test_dtd.rb +43 -0
- data/test/xml/test_node.rb +394 -0
- data/test/xml/test_node_set.rb +143 -0
- data/test/xml/test_text.rb +13 -0
- data/test/xml/test_xpath.rb +105 -0
- data/vendor/hoe.rb +1020 -0
- metadata +233 -0
@@ -0,0 +1,333 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module XML
|
3
|
+
class Node
|
4
|
+
ELEMENT_NODE = 1
|
5
|
+
ATTRIBUTE_NODE = 2
|
6
|
+
TEXT_NODE = 3
|
7
|
+
CDATA_SECTION_NODE = 4
|
8
|
+
ENTITY_REF_NODE = 5
|
9
|
+
ENTITY_NODE = 6
|
10
|
+
PI_NODE = 7
|
11
|
+
COMMENT_NODE = 8
|
12
|
+
DOCUMENT_NODE = 9
|
13
|
+
DOCUMENT_TYPE_NODE = 10
|
14
|
+
DOCUMENT_FRAG_NODE = 11
|
15
|
+
NOTATION_NODE = 12
|
16
|
+
HTML_DOCUMENT_NODE = 13
|
17
|
+
DTD_NODE = 14
|
18
|
+
ELEMENT_DECL = 15
|
19
|
+
ATTRIBUTE_DECL = 16
|
20
|
+
ENTITY_DECL = 17
|
21
|
+
NAMESPACE_DECL = 18
|
22
|
+
XINCLUDE_START = 19
|
23
|
+
XINCLUDE_END = 20
|
24
|
+
DOCB_DOCUMENT_NODE = 21
|
25
|
+
|
26
|
+
attr_accessor :document
|
27
|
+
|
28
|
+
###
|
29
|
+
# Decorate this node with the decorators set up in this node's Document
|
30
|
+
def decorate!
|
31
|
+
document.decorate(self) if document
|
32
|
+
end
|
33
|
+
|
34
|
+
###
|
35
|
+
# Get the list of children for this node as a NodeSet
|
36
|
+
def children
|
37
|
+
list = NodeSet.new(document)
|
38
|
+
document.decorate(list)
|
39
|
+
|
40
|
+
first = self.child
|
41
|
+
return list unless first # Empty list
|
42
|
+
|
43
|
+
list << first
|
44
|
+
while first = first.next
|
45
|
+
list << first
|
46
|
+
end
|
47
|
+
list
|
48
|
+
end
|
49
|
+
|
50
|
+
###
|
51
|
+
# Search this node for +paths+. +paths+ can be XPath or CSS, and an
|
52
|
+
# optional hash of namespaces may be appended.
|
53
|
+
# See Node#xpath and Node#css.
|
54
|
+
def search *paths
|
55
|
+
ns = paths.last.is_a?(Hash) ? paths.pop : {}
|
56
|
+
xpath(*(paths.map { |path|
|
57
|
+
path = path.to_s
|
58
|
+
path =~ /^(\.\/|\/)/ ? path : CSS.xpath_for(path, :prefix => ".//")
|
59
|
+
}.flatten.uniq) + [ns])
|
60
|
+
end
|
61
|
+
alias :/ :search
|
62
|
+
|
63
|
+
###
|
64
|
+
# Search this node for XPath +paths+. +paths+ must be one or more XPath
|
65
|
+
# queries. A hash of namespaces may be appended. For example:
|
66
|
+
#
|
67
|
+
# node.xpath('.//title')
|
68
|
+
# node.xpath('.//foo:name', { 'foo' => 'http://example.org/' })
|
69
|
+
# node.xpath('.//xmlns:name', node.root.namespaces)
|
70
|
+
#
|
71
|
+
# Custom XPath functions may also be defined. To define custom functions
|
72
|
+
# create a class and implement the # function you want to define.
|
73
|
+
# For example:
|
74
|
+
#
|
75
|
+
# node.xpath('.//title[regex(., "\w+")]', Class.new {
|
76
|
+
# def regex node_set, regex
|
77
|
+
# node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
|
78
|
+
# end
|
79
|
+
# })
|
80
|
+
#
|
81
|
+
def xpath *paths
|
82
|
+
# Pop off our custom function handler if it exists
|
83
|
+
handler = ![
|
84
|
+
Hash, String, Symbol
|
85
|
+
].include?(paths.last.class) ? paths.pop : nil
|
86
|
+
|
87
|
+
ns = paths.last.is_a?(Hash) ? paths.pop : {}
|
88
|
+
|
89
|
+
return NodeSet.new(document) unless document.root
|
90
|
+
|
91
|
+
sets = paths.map { |path|
|
92
|
+
ctx = XPathContext.new(self)
|
93
|
+
ctx.register_namespaces(ns)
|
94
|
+
set = ctx.evaluate(path, handler).node_set
|
95
|
+
set.document = document
|
96
|
+
document.decorate(set)
|
97
|
+
set
|
98
|
+
}
|
99
|
+
return sets.first if sets.length == 1
|
100
|
+
|
101
|
+
NodeSet.new(document) do |combined|
|
102
|
+
document.decorate(combined)
|
103
|
+
sets.each do |set|
|
104
|
+
set.each do |node|
|
105
|
+
combined << node
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
###
|
112
|
+
# Search this node for CSS +rules+. +rules+ must be one or more CSS
|
113
|
+
# selectors. For example:
|
114
|
+
#
|
115
|
+
# node.css('title')
|
116
|
+
# node.css('body h1.bold')
|
117
|
+
# node.css('div + p.green', 'div#one')
|
118
|
+
#
|
119
|
+
# Custom CSS pseudo classes may also be defined. To define custom pseudo
|
120
|
+
# classes, create a class and implement the custom pseudo class you
|
121
|
+
# want defined. The first argument to the method will be the current
|
122
|
+
# matching NodeSet. Any other arguments are ones that you pass in.
|
123
|
+
# For example:
|
124
|
+
#
|
125
|
+
# node.css('title:regex("\w+")', Class.new {
|
126
|
+
# def regex node_set, regex
|
127
|
+
# node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
|
128
|
+
# end
|
129
|
+
# })
|
130
|
+
#
|
131
|
+
def css *rules
|
132
|
+
# Pop off our custom function handler if it exists
|
133
|
+
handler = ![
|
134
|
+
Hash, String, Symbol
|
135
|
+
].include?(rules.last.class) ? rules.pop : nil
|
136
|
+
|
137
|
+
ns = rules.last.is_a?(Hash) ? rules.pop : {}
|
138
|
+
|
139
|
+
rules = rules.map { |rule|
|
140
|
+
CSS.xpath_for(rule, :prefix => ".//")
|
141
|
+
}.flatten.uniq + [ns, handler].compact
|
142
|
+
|
143
|
+
xpath(*rules)
|
144
|
+
end
|
145
|
+
|
146
|
+
def at path, ns = {}
|
147
|
+
search(path, ns).first
|
148
|
+
end
|
149
|
+
|
150
|
+
def [](property)
|
151
|
+
return nil unless key?(property)
|
152
|
+
get(property)
|
153
|
+
end
|
154
|
+
|
155
|
+
def next
|
156
|
+
next_sibling
|
157
|
+
end
|
158
|
+
|
159
|
+
def previous
|
160
|
+
previous_sibling
|
161
|
+
end
|
162
|
+
|
163
|
+
def remove
|
164
|
+
unlink
|
165
|
+
end
|
166
|
+
|
167
|
+
####
|
168
|
+
# Returns a hash containing the node's attributes. The key is the
|
169
|
+
# attribute name, the value is the string value of the attribute.
|
170
|
+
def attributes
|
171
|
+
Hash[*(attribute_nodes.map { |node|
|
172
|
+
[node.name, node]
|
173
|
+
}.flatten)]
|
174
|
+
end
|
175
|
+
|
176
|
+
###
|
177
|
+
# Remove the attribute named +name+
|
178
|
+
def remove_attribute name
|
179
|
+
attributes[name].remove if key? name
|
180
|
+
end
|
181
|
+
alias :delete :remove_attribute
|
182
|
+
|
183
|
+
####
|
184
|
+
# Create nodes from +data+ and insert them before this node
|
185
|
+
# (as a sibling).
|
186
|
+
def before data
|
187
|
+
classes = document.class.name.split('::')
|
188
|
+
classes[-1] = 'SAX::Parser'
|
189
|
+
|
190
|
+
parser = eval(classes.join('::')).new(BeforeHandler.new(self, data))
|
191
|
+
parser.parse(data)
|
192
|
+
end
|
193
|
+
|
194
|
+
####
|
195
|
+
# Create nodes from +data+ and insert them after this node
|
196
|
+
# (as a sibling).
|
197
|
+
def after data
|
198
|
+
classes = document.class.name.split('::')
|
199
|
+
classes[-1] = 'SAX::Parser'
|
200
|
+
|
201
|
+
handler = AfterHandler.new(self, data)
|
202
|
+
parser = eval(classes.join('::')).new(handler)
|
203
|
+
parser.parse(data)
|
204
|
+
handler.after_nodes.reverse.each do |sibling|
|
205
|
+
self.add_next_sibling sibling
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def has_attribute?(property)
|
210
|
+
key? property
|
211
|
+
end
|
212
|
+
|
213
|
+
alias :get_attribute :[]
|
214
|
+
def set_attribute(name, value)
|
215
|
+
self[name] = value
|
216
|
+
end
|
217
|
+
|
218
|
+
def text
|
219
|
+
content
|
220
|
+
end
|
221
|
+
alias :inner_text :text
|
222
|
+
|
223
|
+
####
|
224
|
+
# Set the content to +string+.
|
225
|
+
# If +encode+, encode any special characters first.
|
226
|
+
def content= string, encode = true
|
227
|
+
self.native_content = encode_special_chars(string)
|
228
|
+
end
|
229
|
+
|
230
|
+
###
|
231
|
+
# Set the parent Node for this Node
|
232
|
+
def parent= parent_node
|
233
|
+
parent_node.add_child(self)
|
234
|
+
parent_node
|
235
|
+
end
|
236
|
+
|
237
|
+
def << child
|
238
|
+
add_child child
|
239
|
+
end
|
240
|
+
|
241
|
+
def comment?
|
242
|
+
type == COMMENT_NODE
|
243
|
+
end
|
244
|
+
|
245
|
+
def cdata?
|
246
|
+
type == CDATA_SECTION_NODE
|
247
|
+
end
|
248
|
+
|
249
|
+
def xml?
|
250
|
+
type == DOCUMENT_NODE
|
251
|
+
end
|
252
|
+
|
253
|
+
def html?
|
254
|
+
type == HTML_DOCUMENT_NODE
|
255
|
+
end
|
256
|
+
|
257
|
+
def text?
|
258
|
+
type == TEXT_NODE
|
259
|
+
end
|
260
|
+
|
261
|
+
def read_only?
|
262
|
+
# According to gdome2, these are read-only node types
|
263
|
+
[NOTATION_NODE, ENTITY_NODE, ENTITY_DECL].include?(type)
|
264
|
+
end
|
265
|
+
|
266
|
+
def element?
|
267
|
+
type == ELEMENT_NODE
|
268
|
+
end
|
269
|
+
alias :elem? :element?
|
270
|
+
|
271
|
+
def to_s
|
272
|
+
document.xml? ? to_xml : to_html
|
273
|
+
end
|
274
|
+
|
275
|
+
def inner_html
|
276
|
+
children.map { |x| x.to_html }.join
|
277
|
+
end
|
278
|
+
|
279
|
+
def css_path
|
280
|
+
path.split(/\//).map { |part|
|
281
|
+
part.length == 0 ? nil : part.gsub(/\[(\d+)\]/, ':nth-of-type(\1)')
|
282
|
+
}.compact.join(' > ')
|
283
|
+
end
|
284
|
+
|
285
|
+
# recursively get all namespaces from this node and its subtree
|
286
|
+
def collect_namespaces
|
287
|
+
# TODO: print warning message if a prefix refers to more than one URI in the document?
|
288
|
+
ns = {}
|
289
|
+
traverse {|j| ns.merge!(j.namespaces)}
|
290
|
+
ns
|
291
|
+
end
|
292
|
+
|
293
|
+
###
|
294
|
+
# Get a list of ancestor Node for this Node
|
295
|
+
def ancestors
|
296
|
+
parents = []
|
297
|
+
|
298
|
+
this_parent = self.parent
|
299
|
+
|
300
|
+
while this_parent != nil
|
301
|
+
parents << this_parent
|
302
|
+
this_parent = this_parent.parent
|
303
|
+
end
|
304
|
+
parents
|
305
|
+
end
|
306
|
+
|
307
|
+
####
|
308
|
+
# Yields self and all children to +block+ recursively.
|
309
|
+
def traverse(&block)
|
310
|
+
children.each{|j| j.traverse(&block) }
|
311
|
+
block.call(self)
|
312
|
+
end
|
313
|
+
|
314
|
+
####
|
315
|
+
# replace node with the new node in the document.
|
316
|
+
def replace(new_node)
|
317
|
+
if new_node.is_a?(Document)
|
318
|
+
raise ArgumentError, <<-EOERR
|
319
|
+
Node.replace requires a Node argument, and cannot accept a Document.
|
320
|
+
(You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
|
321
|
+
EOERR
|
322
|
+
end
|
323
|
+
replace_with_node new_node
|
324
|
+
end
|
325
|
+
|
326
|
+
def == other
|
327
|
+
return false unless other
|
328
|
+
return false unless other.respond_to?(:pointer_id)
|
329
|
+
pointer_id == other.pointer_id
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module XML
|
3
|
+
class NodeSet
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
attr_accessor :document
|
7
|
+
|
8
|
+
def initialize document, list = []
|
9
|
+
@document = document
|
10
|
+
list.each { |x| self << x }
|
11
|
+
yield self if block_given?
|
12
|
+
end
|
13
|
+
|
14
|
+
###
|
15
|
+
# Get the first element of the NodeSet.
|
16
|
+
def first
|
17
|
+
self[0]
|
18
|
+
end
|
19
|
+
|
20
|
+
###
|
21
|
+
# Get the last element of the NodeSet.
|
22
|
+
def last
|
23
|
+
self[length - 1]
|
24
|
+
end
|
25
|
+
|
26
|
+
###
|
27
|
+
# Is this NodeSet empty?
|
28
|
+
def empty?
|
29
|
+
length == 0
|
30
|
+
end
|
31
|
+
|
32
|
+
###
|
33
|
+
# Insert +datum+ before the first Node in this NodeSet
|
34
|
+
def before datum
|
35
|
+
first.before datum
|
36
|
+
end
|
37
|
+
|
38
|
+
###
|
39
|
+
# Insert +datum+ after the last Node in this NodeSet
|
40
|
+
def after datum
|
41
|
+
last.after datum
|
42
|
+
end
|
43
|
+
|
44
|
+
###
|
45
|
+
# Append +node+ to the NodeSet.
|
46
|
+
def << node
|
47
|
+
push(node)
|
48
|
+
end
|
49
|
+
|
50
|
+
###
|
51
|
+
# Unlink this NodeSet and all Node objects it contains from their
|
52
|
+
# current context.
|
53
|
+
def unlink
|
54
|
+
each { |node| node.unlink }
|
55
|
+
self
|
56
|
+
end
|
57
|
+
alias :remove :unlink
|
58
|
+
|
59
|
+
###
|
60
|
+
# Search this document for +paths+
|
61
|
+
def search *paths
|
62
|
+
sub_set = NodeSet.new(document)
|
63
|
+
document.decorate(sub_set)
|
64
|
+
each do |node|
|
65
|
+
node.search(*paths).each do |sub_node|
|
66
|
+
sub_set << sub_node
|
67
|
+
end
|
68
|
+
end
|
69
|
+
sub_set
|
70
|
+
end
|
71
|
+
alias :/ :search
|
72
|
+
alias :xpath :search
|
73
|
+
alias :css :search
|
74
|
+
|
75
|
+
###
|
76
|
+
# If path is a string, search this document for +path+ returning the
|
77
|
+
# first Node. Otherwise, index in to the array with +path+.
|
78
|
+
def at path, ns = {}
|
79
|
+
return self[path] if path.is_a?(Numeric)
|
80
|
+
search(path, ns).first
|
81
|
+
end
|
82
|
+
|
83
|
+
###
|
84
|
+
# Append the class attribute +name+ to all Node objects in the NodeSet.
|
85
|
+
def add_class name
|
86
|
+
each do |el|
|
87
|
+
next unless el.respond_to? :get_attribute
|
88
|
+
classes = el.get_attribute('class').to_s.split(" ")
|
89
|
+
el.set_attribute('class', classes.push(name).uniq.join(" "))
|
90
|
+
end
|
91
|
+
self
|
92
|
+
end
|
93
|
+
|
94
|
+
###
|
95
|
+
# Remove the class attribute +name+ from all Node objects in the NodeSet.
|
96
|
+
def remove_class name = nil
|
97
|
+
each do |el|
|
98
|
+
next unless el.respond_to? :get_attribute
|
99
|
+
if name
|
100
|
+
classes = el.get_attribute('class').to_s.split(" ")
|
101
|
+
el.set_attribute('class', (classes - [name]).uniq.join(" "))
|
102
|
+
else
|
103
|
+
el.remove_attribute("class")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
###
|
110
|
+
# Set the attribute +key+ to +value+ or the return value of +blk+
|
111
|
+
# on all Node objects in the NodeSet.
|
112
|
+
def attr key, value = nil, &blk
|
113
|
+
if value or blk
|
114
|
+
each do |el|
|
115
|
+
el.set_attribute(key, value || blk[el])
|
116
|
+
end
|
117
|
+
return self
|
118
|
+
end
|
119
|
+
if key.is_a? Hash
|
120
|
+
key.each { |k,v| self.attr(k,v) }
|
121
|
+
return self
|
122
|
+
else
|
123
|
+
return self[0].get_attribute(key)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
alias_method :set, :attr
|
127
|
+
|
128
|
+
###
|
129
|
+
# Remove the attributed named +name+ from all Node objects in the NodeSet
|
130
|
+
def remove_attr name
|
131
|
+
each do |el|
|
132
|
+
next unless el.respond_to? :remove_attribute
|
133
|
+
el.remove_attribute(name)
|
134
|
+
end
|
135
|
+
self
|
136
|
+
end
|
137
|
+
|
138
|
+
###
|
139
|
+
# Iterate over each node, yielding to +block+
|
140
|
+
def each(&block)
|
141
|
+
x = 0
|
142
|
+
while x < length
|
143
|
+
yield self[x]
|
144
|
+
x += 1
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
###
|
149
|
+
# Get the inner text of all contained Node objects
|
150
|
+
def inner_text
|
151
|
+
collect{|j| j.inner_text}.join('')
|
152
|
+
end
|
153
|
+
alias :text :inner_text
|
154
|
+
|
155
|
+
###
|
156
|
+
# Get the inner html of all contained Node objects
|
157
|
+
def inner_html
|
158
|
+
collect{|j| j.inner_html}.join('')
|
159
|
+
end
|
160
|
+
|
161
|
+
###
|
162
|
+
# Wrap this NodeSet with +html+ or the results of the builder in +blk+
|
163
|
+
def wrap(html, &blk)
|
164
|
+
each do |j|
|
165
|
+
new_parent = Nokogiri.make(html, &blk)
|
166
|
+
j.replace(new_parent)
|
167
|
+
nest = new_parent
|
168
|
+
if nest.child
|
169
|
+
nest = nest.child until nest.child.nil?
|
170
|
+
end
|
171
|
+
j.parent = nest
|
172
|
+
end
|
173
|
+
self
|
174
|
+
end
|
175
|
+
|
176
|
+
def to_s
|
177
|
+
map { |x| x.to_s }.join
|
178
|
+
end
|
179
|
+
|
180
|
+
def to_html
|
181
|
+
map { |x| x.to_html }.join('')
|
182
|
+
end
|
183
|
+
|
184
|
+
def to_xml *args
|
185
|
+
map { |x| x.to_xml(*args) }.join('')
|
186
|
+
end
|
187
|
+
|
188
|
+
def size
|
189
|
+
length
|
190
|
+
end
|
191
|
+
|
192
|
+
def to_ary
|
193
|
+
to_a
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|