nokogiri 1.3.3-x86-mingw32 → 1.4.0-x86-mingw32

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.

Files changed (202) hide show
  1. data/CHANGELOG.ja.rdoc +48 -3
  2. data/CHANGELOG.rdoc +42 -0
  3. data/Manifest.txt +44 -29
  4. data/README.ja.rdoc +0 -2
  5. data/README.rdoc +4 -7
  6. data/Rakefile +14 -22
  7. data/bin/nokogiri +7 -5
  8. data/ext/nokogiri/extconf.rb +5 -21
  9. data/ext/nokogiri/html_document.c +14 -50
  10. data/ext/nokogiri/html_element_description.c +7 -7
  11. data/ext/nokogiri/html_entity_lookup.c +6 -4
  12. data/ext/nokogiri/html_sax_parser_context.c +92 -0
  13. data/ext/nokogiri/html_sax_parser_context.h +11 -0
  14. data/ext/nokogiri/nokogiri.c +9 -3
  15. data/ext/nokogiri/nokogiri.h +16 -20
  16. data/ext/nokogiri/xml_attr.c +1 -1
  17. data/ext/nokogiri/xml_attribute_decl.c +67 -0
  18. data/ext/nokogiri/xml_attribute_decl.h +9 -0
  19. data/ext/nokogiri/xml_cdata.c +6 -5
  20. data/ext/nokogiri/xml_comment.c +3 -2
  21. data/ext/nokogiri/xml_document.c +93 -23
  22. data/ext/nokogiri/xml_document_fragment.c +1 -3
  23. data/ext/nokogiri/xml_dtd.c +63 -6
  24. data/ext/nokogiri/xml_element_content.c +123 -0
  25. data/ext/nokogiri/xml_element_content.h +10 -0
  26. data/ext/nokogiri/xml_element_decl.c +69 -0
  27. data/ext/nokogiri/xml_element_decl.h +9 -0
  28. data/ext/nokogiri/xml_entity_decl.c +97 -0
  29. data/ext/nokogiri/xml_entity_decl.h +10 -0
  30. data/ext/nokogiri/xml_entity_reference.c +1 -1
  31. data/ext/nokogiri/xml_io.c +10 -3
  32. data/ext/nokogiri/xml_io.h +1 -0
  33. data/ext/nokogiri/xml_namespace.c +2 -2
  34. data/ext/nokogiri/xml_node.c +139 -34
  35. data/ext/nokogiri/xml_node.h +0 -1
  36. data/ext/nokogiri/xml_node_set.c +23 -16
  37. data/ext/nokogiri/xml_processing_instruction.c +1 -1
  38. data/ext/nokogiri/xml_reader.c +78 -50
  39. data/ext/nokogiri/xml_sax_parser.c +109 -168
  40. data/ext/nokogiri/xml_sax_parser.h +33 -0
  41. data/ext/nokogiri/xml_sax_parser_context.c +155 -0
  42. data/ext/nokogiri/xml_sax_parser_context.h +10 -0
  43. data/ext/nokogiri/xml_sax_push_parser.c +11 -6
  44. data/ext/nokogiri/xml_syntax_error.c +63 -12
  45. data/ext/nokogiri/xml_text.c +4 -3
  46. data/ext/nokogiri/xml_xpath.c +1 -1
  47. data/ext/nokogiri/xml_xpath_context.c +12 -25
  48. data/ext/nokogiri/xslt_stylesheet.c +3 -3
  49. data/lib/nokogiri.rb +4 -4
  50. data/lib/nokogiri/1.8/nokogiri.so +0 -0
  51. data/lib/nokogiri/1.9/nokogiri.so +0 -0
  52. data/lib/nokogiri/css/node.rb +1 -9
  53. data/lib/nokogiri/css/xpath_visitor.rb +11 -21
  54. data/lib/nokogiri/ffi/html/document.rb +0 -9
  55. data/lib/nokogiri/ffi/html/sax/parser_context.rb +38 -0
  56. data/lib/nokogiri/ffi/io_callbacks.rb +4 -2
  57. data/lib/nokogiri/ffi/libxml.rb +44 -10
  58. data/lib/nokogiri/ffi/structs/common_node.rb +1 -1
  59. data/lib/nokogiri/ffi/structs/xml_attribute.rb +27 -0
  60. data/lib/nokogiri/ffi/structs/xml_dtd.rb +3 -1
  61. data/lib/nokogiri/ffi/structs/xml_element.rb +26 -0
  62. data/lib/nokogiri/ffi/structs/xml_element_content.rb +17 -0
  63. data/lib/nokogiri/ffi/structs/xml_entity.rb +32 -0
  64. data/lib/nokogiri/ffi/structs/xml_enumeration.rb +12 -0
  65. data/lib/nokogiri/ffi/structs/xml_parser_context.rb +19 -0
  66. data/lib/nokogiri/ffi/structs/xml_sax_push_parser_context.rb +4 -3
  67. data/lib/nokogiri/ffi/structs/xml_syntax_error.rb +1 -1
  68. data/lib/nokogiri/ffi/xml/attribute_decl.rb +27 -0
  69. data/lib/nokogiri/ffi/xml/comment.rb +2 -2
  70. data/lib/nokogiri/ffi/xml/document.rb +29 -12
  71. data/lib/nokogiri/ffi/xml/document_fragment.rb +0 -5
  72. data/lib/nokogiri/ffi/xml/dtd.rb +14 -3
  73. data/lib/nokogiri/ffi/xml/element_content.rb +43 -0
  74. data/lib/nokogiri/ffi/xml/element_decl.rb +19 -0
  75. data/lib/nokogiri/ffi/xml/entity_decl.rb +27 -0
  76. data/lib/nokogiri/ffi/xml/node.rb +45 -5
  77. data/lib/nokogiri/ffi/xml/node_set.rb +1 -1
  78. data/lib/nokogiri/ffi/xml/reader.rb +45 -24
  79. data/lib/nokogiri/ffi/xml/sax/parser.rb +27 -34
  80. data/lib/nokogiri/ffi/xml/sax/parser_context.rb +67 -0
  81. data/lib/nokogiri/ffi/xml/sax/push_parser.rb +5 -4
  82. data/lib/nokogiri/ffi/xml/syntax_error.rb +31 -16
  83. data/lib/nokogiri/ffi/xml/text.rb +2 -2
  84. data/lib/nokogiri/html.rb +1 -0
  85. data/lib/nokogiri/html/document.rb +39 -24
  86. data/lib/nokogiri/html/sax/parser.rb +2 -2
  87. data/lib/nokogiri/html/sax/parser_context.rb +16 -0
  88. data/lib/nokogiri/version.rb +1 -1
  89. data/lib/nokogiri/xml.rb +6 -1
  90. data/lib/nokogiri/xml/attr.rb +5 -0
  91. data/lib/nokogiri/xml/attribute_decl.rb +18 -0
  92. data/lib/nokogiri/xml/builder.rb +121 -13
  93. data/lib/nokogiri/xml/character_data.rb +7 -0
  94. data/lib/nokogiri/xml/document.rb +43 -29
  95. data/lib/nokogiri/xml/document_fragment.rb +26 -6
  96. data/lib/nokogiri/xml/dtd.rb +5 -5
  97. data/lib/nokogiri/xml/element_content.rb +36 -0
  98. data/lib/nokogiri/xml/element_decl.rb +13 -0
  99. data/lib/nokogiri/xml/entity_decl.rb +15 -0
  100. data/lib/nokogiri/xml/fragment_handler.rb +22 -11
  101. data/lib/nokogiri/xml/namespace.rb +6 -0
  102. data/lib/nokogiri/xml/node.rb +33 -15
  103. data/lib/nokogiri/xml/node_set.rb +66 -44
  104. data/lib/nokogiri/xml/pp.rb +2 -0
  105. data/lib/nokogiri/xml/pp/character_data.rb +18 -0
  106. data/lib/nokogiri/xml/pp/node.rb +56 -0
  107. data/lib/nokogiri/xml/reader.rb +8 -0
  108. data/lib/nokogiri/xml/sax.rb +1 -1
  109. data/lib/nokogiri/xml/sax/document.rb +18 -1
  110. data/lib/nokogiri/xml/sax/parser.rb +15 -8
  111. data/lib/nokogiri/xml/sax/parser_context.rb +16 -0
  112. data/lib/nokogiri/xml/sax/push_parser.rb +0 -3
  113. data/lib/nokogiri/xml/syntax_error.rb +4 -0
  114. data/lib/nokogiri/xslt/stylesheet.rb +1 -1
  115. data/test/css/test_nthiness.rb +1 -1
  116. data/test/css/test_parser.rb +1 -1
  117. data/test/css/test_tokenizer.rb +1 -1
  118. data/test/css/test_xpath_visitor.rb +1 -1
  119. data/test/ffi/test_document.rb +1 -1
  120. data/test/files/shift_jis.html +10 -0
  121. data/test/files/staff.dtd +10 -0
  122. data/test/helper.rb +12 -3
  123. data/test/html/sax/test_parser.rb +1 -1
  124. data/test/html/sax/test_parser_context.rb +48 -0
  125. data/test/html/test_builder.rb +8 -2
  126. data/test/html/test_document.rb +23 -1
  127. data/test/html/test_document_encoding.rb +15 -1
  128. data/test/html/test_document_fragment.rb +10 -1
  129. data/test/html/test_element_description.rb +1 -2
  130. data/test/html/test_named_characters.rb +1 -1
  131. data/test/html/test_node.rb +61 -1
  132. data/test/html/test_node_encoding.rb +27 -0
  133. data/test/test_convert_xpath.rb +1 -3
  134. data/test/test_css_cache.rb +1 -1
  135. data/test/test_gc.rb +1 -1
  136. data/test/test_memory_leak.rb +1 -1
  137. data/test/test_nokogiri.rb +3 -3
  138. data/test/test_reader.rb +29 -1
  139. data/test/test_xslt_transforms.rb +1 -1
  140. data/test/xml/node/test_save_options.rb +1 -1
  141. data/test/xml/node/test_subclass.rb +1 -1
  142. data/test/xml/sax/test_parser.rb +64 -3
  143. data/test/xml/sax/test_parser_context.rb +56 -0
  144. data/test/xml/sax/test_push_parser.rb +11 -1
  145. data/test/xml/test_attr.rb +1 -1
  146. data/test/xml/test_attribute_decl.rb +82 -0
  147. data/test/xml/test_builder.rb +95 -1
  148. data/test/xml/test_cdata.rb +1 -1
  149. data/test/xml/test_comment.rb +7 -1
  150. data/test/xml/test_document.rb +147 -6
  151. data/test/xml/test_document_encoding.rb +1 -1
  152. data/test/xml/test_document_fragment.rb +55 -5
  153. data/test/xml/test_dtd.rb +40 -5
  154. data/test/xml/test_dtd_encoding.rb +3 -1
  155. data/test/xml/test_element_content.rb +56 -0
  156. data/test/xml/test_element_decl.rb +73 -0
  157. data/test/xml/test_entity_decl.rb +83 -0
  158. data/test/xml/test_entity_reference.rb +1 -1
  159. data/test/xml/test_namespace.rb +21 -1
  160. data/test/xml/test_node.rb +70 -4
  161. data/test/xml/test_node_attributes.rb +1 -1
  162. data/test/xml/test_node_encoding.rb +1 -1
  163. data/test/xml/test_node_set.rb +136 -2
  164. data/test/xml/test_parse_options.rb +1 -1
  165. data/test/xml/test_processing_instruction.rb +1 -1
  166. data/test/xml/test_reader_encoding.rb +1 -1
  167. data/test/xml/test_relax_ng.rb +1 -1
  168. data/test/xml/test_schema.rb +1 -1
  169. data/test/xml/test_syntax_error.rb +27 -0
  170. data/test/xml/test_text.rb +13 -1
  171. data/test/xml/test_unparented_node.rb +1 -1
  172. data/test/xml/test_xpath.rb +1 -1
  173. metadata +55 -38
  174. data/ext/nokogiri/html_sax_parser.c +0 -57
  175. data/ext/nokogiri/html_sax_parser.h +0 -11
  176. data/lib/action-nokogiri.rb +0 -38
  177. data/lib/nokogiri/decorators.rb +0 -2
  178. data/lib/nokogiri/decorators/hpricot.rb +0 -3
  179. data/lib/nokogiri/decorators/hpricot/node.rb +0 -56
  180. data/lib/nokogiri/decorators/hpricot/node_set.rb +0 -54
  181. data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +0 -30
  182. data/lib/nokogiri/ffi/html/sax/parser.rb +0 -21
  183. data/lib/nokogiri/hpricot.rb +0 -92
  184. data/lib/nokogiri/xml/entity_declaration.rb +0 -11
  185. data/lib/nokogiri/xml/sax/legacy_handlers.rb +0 -65
  186. data/test/hpricot/files/basic.xhtml +0 -17
  187. data/test/hpricot/files/boingboing.html +0 -2266
  188. data/test/hpricot/files/cy0.html +0 -3653
  189. data/test/hpricot/files/immob.html +0 -400
  190. data/test/hpricot/files/pace_application.html +0 -1320
  191. data/test/hpricot/files/tenderlove.html +0 -16
  192. data/test/hpricot/files/uswebgen.html +0 -220
  193. data/test/hpricot/files/utf8.html +0 -1054
  194. data/test/hpricot/files/week9.html +0 -1723
  195. data/test/hpricot/files/why.xml +0 -19
  196. data/test/hpricot/load_files.rb +0 -11
  197. data/test/hpricot/test_alter.rb +0 -68
  198. data/test/hpricot/test_builder.rb +0 -20
  199. data/test/hpricot/test_parser.rb +0 -350
  200. data/test/hpricot/test_paths.rb +0 -15
  201. data/test/hpricot/test_preserved.rb +0 -77
  202. data/test/hpricot/test_xml.rb +0 -30
@@ -3,12 +3,15 @@ module Nokogiri
3
3
  class DocumentFragment < Nokogiri::XML::Node
4
4
  def initialize document, tags=nil
5
5
  if tags
6
- parser = if self.kind_of?(Nokogiri::HTML::DocumentFragment)
7
- HTML::SAX::Parser.new(FragmentHandler.new(self, tags))
8
- else
9
- XML::SAX::Parser.new(FragmentHandler.new(self, tags))
10
- end
11
- parser.parse(tags)
6
+ if self.kind_of?(Nokogiri::HTML::DocumentFragment)
7
+ HTML::SAX::Parser.new(FragmentHandler.new(self, tags)).parse(tags)
8
+ else
9
+ wrapped = "<div>#{tags.strip}</div>"
10
+ XML::SAX::Parser.new(FragmentHandler.new(self, wrapped)).parse(wrapped)
11
+ div = self.child
12
+ div.children.each { |child| child.parent = self }
13
+ div.unlink
14
+ end
12
15
  end
13
16
  end
14
17
 
@@ -18,22 +21,39 @@ module Nokogiri
18
21
  '#document-fragment'
19
22
  end
20
23
 
24
+ ###
25
+ # Convert this DocumentFragment to a string
21
26
  def to_s
22
27
  children.to_s
23
28
  end
24
29
 
30
+ ###
31
+ # Convert this DocumentFragment to html
32
+ # See Nokogiri::XML::NodeSet#to_html
25
33
  def to_html *args
26
34
  children.to_html(*args)
27
35
  end
28
36
 
37
+ ###
38
+ # Convert this DocumentFragment to xhtml
39
+ # See Nokogiri::XML::NodeSet#to_xhtml
29
40
  def to_xhtml *args
30
41
  children.to_xhtml(*args)
31
42
  end
32
43
 
44
+ ###
45
+ # Convert this DocumentFragment to xml
46
+ # See Nokogiri::XML::NodeSet#to_xml
33
47
  def to_xml *args
34
48
  children.to_xml(*args)
35
49
  end
36
50
 
51
+ ###
52
+ # Search this fragment. See Nokogiri::XML::Node#css
53
+ def css *args
54
+ children.css(*args)
55
+ end
56
+
37
57
  alias :serialize :to_s
38
58
 
39
59
  class << self
@@ -1,11 +1,11 @@
1
1
  module Nokogiri
2
2
  module XML
3
3
  class DTD < Nokogiri::XML::Node
4
- ###
5
- # Return attributes for DTD. Always returns +nil+
6
- def attributes
7
- nil
8
- end
4
+ undef_method :attribute_nodes
5
+ undef_method :content
6
+ undef_method :namespace
7
+ undef_method :namespace_definitions
8
+ undef_method :line
9
9
  end
10
10
  end
11
11
  end
@@ -0,0 +1,36 @@
1
+ module Nokogiri
2
+ module XML
3
+ ###
4
+ # Represents the allowed content in an Element Declaration inside a DTD:
5
+ #
6
+ # <?xml version="1.0"?><?TEST-STYLE PIDATA?>
7
+ # <!DOCTYPE staff SYSTEM "staff.dtd" [
8
+ # <!ELEMENT div1 (head, (p | list | note)*, div2*)>
9
+ # ]>
10
+ # </root>
11
+ #
12
+ # ElementContent represents the tree inside the <!ELEMENT> tag shown above
13
+ # that lists the possible content for the div1 tag.
14
+ class ElementContent
15
+ # Possible definitions of type
16
+ PCDATA = 1
17
+ ELEMENT = 2
18
+ SEQ = 3
19
+ OR = 4
20
+
21
+ # Possible content occurrences
22
+ ONCE = 1
23
+ OPT = 2
24
+ MULT = 3
25
+ PLUS = 4
26
+
27
+ attr_reader :document
28
+
29
+ ###
30
+ # Get the children of this ElementContent node
31
+ def children
32
+ [c1, c2].compact
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ module Nokogiri
2
+ module XML
3
+ class ElementDecl < Nokogiri::XML::Node
4
+ undef_method :namespace
5
+ undef_method :namespace_definitions
6
+ undef_method :line
7
+
8
+ def inspect
9
+ "#<#{self.class.name}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Nokogiri
2
+ module XML
3
+ class EntityDecl < Nokogiri::XML::Node
4
+ undef_method :attribute_nodes
5
+ undef_method :attributes
6
+ undef_method :namespace
7
+ undef_method :namespace_definitions
8
+ undef_method :line
9
+
10
+ def inspect
11
+ "#<#{self.class.name}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,16 +1,14 @@
1
1
  module Nokogiri
2
2
  module XML
3
3
  class FragmentHandler < Nokogiri::XML::SAX::Document # :nodoc:
4
+ QNAME_REGEX = /(.*):(.*)/
5
+
4
6
  def initialize node, original_html
5
7
  @doc_started = false
6
8
  @document = node.document
7
9
  @stack = [node]
8
- @klass = if node.kind_of?(Nokogiri::HTML::DocumentFragment)
9
- Nokogiri::HTML::DocumentFragment
10
- else
11
- Nokogiri::XML::DocumentFragment
12
- end
13
- #
10
+ @html_eh = node.kind_of? HTML::DocumentFragment
11
+
14
12
  # the regexes used in start_element() and characters() anchor at
15
13
  # start-of-line, but we really only want them to anchor at
16
14
  # start-of-doc. so let's only save up to the first newline.
@@ -24,31 +22,44 @@ module Nokogiri
24
22
  end
25
23
 
26
24
  def start_element name, attrs = []
27
- regex = (@klass == Nokogiri::HTML::DocumentFragment) ? %r{^\s*<#{Regexp.escape(name)}}i \
28
- : %r{^\s*<#{Regexp.escape(name)}}
25
+ regex = @html_eh ? %r{^\s*<#{Regexp.escape(name)}}i :
26
+ %r{^\s*<#{Regexp.escape(name)}}
27
+
29
28
  @doc_started = true if @original_html =~ regex
30
29
  return unless @doc_started
31
30
 
31
+ if match = name.match(QNAME_REGEX)
32
+ prefix, name = match[1], match[2]
33
+ ns = @document.root.namespace_definitions.detect { |x|
34
+ x.prefix == prefix
35
+ }
36
+ else
37
+ ns = nil
38
+ end
39
+
32
40
  node = Element.new(name, @document)
33
41
  attrs << "" unless (attrs.length % 2) == 0
34
42
  Hash[*attrs].each do |k,v|
35
43
  node[k] = v
36
44
  end
45
+
46
+ node.namespace = ns if ns
47
+
37
48
  @stack.last << node
38
49
  @stack << node
39
50
  end
40
51
 
41
52
  def characters string
42
53
  @doc_started = true if @original_html.strip =~ %r{^\s*#{Regexp.escape(string.strip)}}
43
- @stack.last << Nokogiri::XML::Text.new(string, @document)
54
+ @stack.last << Text.new(string, @document)
44
55
  end
45
56
 
46
57
  def comment string
47
- @stack.last << Nokogiri::XML::Comment.new(@document, string)
58
+ @stack.last << Comment.new(@document, string)
48
59
  end
49
60
 
50
61
  def cdata_block string
51
- @stack.last << Nokogiri::XML::CDATA.new(@document, string)
62
+ @stack.last << CDATA.new(@document, string)
52
63
  end
53
64
 
54
65
  def end_element name
@@ -1,7 +1,13 @@
1
1
  module Nokogiri
2
2
  module XML
3
3
  class Namespace
4
+ include Nokogiri::XML::PP::Node
4
5
  attr_reader :document
6
+
7
+ private
8
+ def inspect_attributes
9
+ [:prefix, :href]
10
+ end
5
11
  end
6
12
  end
7
13
  end
@@ -34,6 +34,8 @@ module Nokogiri
34
34
  #
35
35
  # You may search this node's subtree using Node#xpath and Node#css
36
36
  class Node
37
+ include Nokogiri::XML::PP::Node
38
+
37
39
  # Element node type, see Nokogiri::XML::Node#element?
38
40
  ELEMENT_NODE = 1
39
41
  # Attribute node type
@@ -198,6 +200,24 @@ module Nokogiri
198
200
  end
199
201
  alias :% :at
200
202
 
203
+ ##
204
+ # Search this node for the first occurrence of XPath +paths+.
205
+ # Equivalent to <tt>xpath(paths).first</tt>
206
+ # See Node#xpath for more information.
207
+ #
208
+ def at_xpath *paths
209
+ xpath(*paths).first
210
+ end
211
+
212
+ ##
213
+ # Search this node for the first occurrence of CSS +rules+.
214
+ # Equivalent to <tt>css(rules).first</tt>
215
+ # See Node#css for more information.
216
+ #
217
+ def at_css *rules
218
+ css(*rules).first
219
+ end
220
+
201
221
  ###
202
222
  # Get the attribute value for the attribute +name+
203
223
  def [] name
@@ -388,8 +408,8 @@ module Nokogiri
388
408
  end
389
409
 
390
410
  # Get the inner_html for this node's Node#children
391
- def inner_html
392
- children.map { |x| x.to_html }.join
411
+ def inner_html *args
412
+ children.map { |x| x.to_html(*args) }.join
393
413
  end
394
414
 
395
415
  # Get the path to this node as a CSS expression
@@ -399,14 +419,6 @@ module Nokogiri
399
419
  }.compact.join(' > ')
400
420
  end
401
421
 
402
- # recursively get all namespaces from this node and its subtree
403
- def collect_namespaces
404
- # TODO: print warning message if a prefix refers to more than one URI in the document?
405
- ns = {}
406
- traverse {|j| ns.merge!(j.namespaces)}
407
- ns
408
- end
409
-
410
422
  ###
411
423
  # Get a list of ancestor Node for this Node. If +selector+ is given,
412
424
  # the ancestors must match +selector+
@@ -461,7 +473,8 @@ module Nokogiri
461
473
  end
462
474
 
463
475
  ####
464
- # replace this Node with the +new_node+ in the Document.
476
+ # +replace+ this Node with the +new_node+ in the Document. The new node
477
+ # must be a Nokogiri::XML::Node or a non-empty String
465
478
  def replace new_node
466
479
  if new_node.is_a?(Document) || !new_node.is_a?(XML::Node)
467
480
  raise ArgumentError, <<-EOERR
@@ -500,9 +513,11 @@ Node.replace requires a Node argument, and cannot accept a Document.
500
513
  :save_with => args[1] || SaveOptions::FORMAT
501
514
  }
502
515
 
516
+ encoding = options[:encoding] || document.encoding
517
+
503
518
  outstring = ""
504
- if document.encoding && outstring.respond_to?(:force_encoding)
505
- outstring.force_encoding(Encoding.find(document.encoding))
519
+ if encoding && outstring.respond_to?(:force_encoding)
520
+ outstring.force_encoding(Encoding.find(encoding))
506
521
  end
507
522
  io = StringIO.new(outstring)
508
523
  write_to io, options, &block
@@ -640,8 +655,11 @@ Node.replace requires a Node argument, and cannot accept a Document.
640
655
  return nil unless document == other.document
641
656
  compare other
642
657
  end
658
+
659
+ private
660
+ def inspect_attributes
661
+ [:name, :namespace, :attribute_nodes, :children]
662
+ end
643
663
  end
644
664
  end
645
665
  end
646
-
647
- class Nokogiri::XML::Element < Nokogiri::XML::Node ; end
@@ -68,16 +68,21 @@ module Nokogiri
68
68
  # For more information see Nokogiri::XML::Node#css and
69
69
  # Nokogiri::XML::Node#xpath
70
70
  def search *paths
71
- ns = paths.last.is_a?(Hash) ? paths.pop :
72
- (document.root ? document.root.namespaces : {})
71
+ handler = ![
72
+ Hash, String, Symbol
73
+ ].include?(paths.last.class) ? paths.pop : nil
74
+
75
+ ns = paths.last.is_a?(Hash) ? paths.pop : nil
73
76
 
74
77
  sub_set = NodeSet.new(document)
75
- each do |node|
76
- paths.each do |path|
77
- sub_set +=
78
- send(path =~ /^(\.\/|\/)/ ? :xpath : :css, *(paths + [ns]))
79
- end
78
+
79
+ paths.each do |path|
80
+ sub_set += send(
81
+ path =~ /^(\.\/|\/)/ ? :xpath : :css,
82
+ *(paths + [ns, handler]).compact
83
+ )
80
84
  end
85
+
81
86
  document.decorate(sub_set)
82
87
  sub_set
83
88
  end
@@ -88,19 +93,26 @@ module Nokogiri
88
93
  #
89
94
  # For more information see Nokogiri::XML::Node#css
90
95
  def css *paths
91
- ns = paths.last.is_a?(Hash) ? paths.pop :
92
- (document.root ? document.root.namespaces : {})
96
+ handler = ![
97
+ Hash, String, Symbol
98
+ ].include?(paths.last.class) ? paths.pop : nil
99
+
100
+ ns = paths.last.is_a?(Hash) ? paths.pop : nil
93
101
 
94
102
  sub_set = NodeSet.new(document)
95
103
 
96
- xpaths = paths.map { |rule|
97
- [
98
- CSS.xpath_for(rule.to_s, :prefix => ".//", :ns => ns),
99
- CSS.xpath_for(rule.to_s, :prefix => "self::", :ns => ns)
100
- ].join(' | ')
101
- }
102
104
  each do |node|
103
- sub_set += node.xpath(*(xpaths + [ns]))
105
+ doc = node.document
106
+ search_ns = ns || doc.root ? doc.root.namespaces : {}
107
+
108
+ xpaths = paths.map { |rule|
109
+ [
110
+ CSS.xpath_for(rule.to_s, :prefix => ".//", :ns => search_ns),
111
+ CSS.xpath_for(rule.to_s, :prefix => "self::", :ns => search_ns)
112
+ ].join(' | ')
113
+ }
114
+
115
+ sub_set += node.xpath(*(xpaths + [search_ns, handler].compact))
104
116
  end
105
117
  document.decorate(sub_set)
106
118
  sub_set
@@ -111,12 +123,15 @@ module Nokogiri
111
123
  #
112
124
  # For more information see Nokogiri::XML::Node#xpath
113
125
  def xpath *paths
114
- ns = paths.last.is_a?(Hash) ? paths.pop :
115
- (document.root ? document.root.namespaces : {})
126
+ handler = ![
127
+ Hash, String, Symbol
128
+ ].include?(paths.last.class) ? paths.pop : nil
129
+
130
+ ns = paths.last.is_a?(Hash) ? paths.pop : nil
116
131
 
117
132
  sub_set = NodeSet.new(document)
118
133
  each do |node|
119
- sub_set += node.xpath(*(paths + [ns]))
134
+ sub_set += node.xpath(*(paths + [ns, handler].compact))
120
135
  end
121
136
  document.decorate(sub_set)
122
137
  sub_set
@@ -135,23 +150,27 @@ module Nokogiri
135
150
  # Append the class attribute +name+ to all Node objects in the NodeSet.
136
151
  def add_class name
137
152
  each do |el|
138
- next unless el.respond_to? :get_attribute
139
- classes = el.get_attribute('class').to_s.split(" ")
140
- el.set_attribute('class', classes.push(name).uniq.join(" "))
153
+ classes = el['class'].to_s.split(/\s+/)
154
+ el['class'] = classes.push(name).uniq.join " "
141
155
  end
142
156
  self
143
157
  end
144
158
 
145
159
  ###
146
160
  # Remove the class attribute +name+ from all Node objects in the NodeSet.
161
+ # If +name+ is nil, remove the class attribute from all Nodes in the
162
+ # NodeSet.
147
163
  def remove_class name = nil
148
164
  each do |el|
149
- next unless el.respond_to? :get_attribute
150
165
  if name
151
- classes = el.get_attribute('class').to_s.split(" ")
152
- el.set_attribute('class', (classes - [name]).uniq.join(" "))
166
+ classes = el['class'].to_s.split(/\s+/)
167
+ if classes.empty?
168
+ el.delete 'class'
169
+ else
170
+ el['class'] = (classes - [name]).uniq.join " "
171
+ end
153
172
  else
154
- el.remove_attribute("class")
173
+ el.delete "class"
155
174
  end
156
175
  end
157
176
  self
@@ -161,28 +180,23 @@ module Nokogiri
161
180
  # Set the attribute +key+ to +value+ or the return value of +blk+
162
181
  # on all Node objects in the NodeSet.
163
182
  def attr key, value = nil, &blk
164
- if value or blk
165
- each do |el|
166
- el.set_attribute(key, value || blk[el])
167
- end
168
- return self
169
- end
170
- if key.is_a? Hash
171
- key.each { |k,v| self.attr(k,v) }
172
- return self
173
- else
174
- return self[0].get_attribute(key)
183
+ unless Hash === key || key && (value || blk)
184
+ return first.attribute(key)
175
185
  end
186
+
187
+ hash = key.is_a?(Hash) ? key : { key => value }
188
+
189
+ hash.each { |k,v| each { |el| el[k] = v || blk[el] } }
190
+
191
+ self
176
192
  end
177
- alias_method :set, :attr
193
+ alias :set :attr
194
+ alias :attribute :attr
178
195
 
179
196
  ###
180
197
  # Remove the attributed named +name+ from all Node objects in the NodeSet
181
198
  def remove_attr name
182
- each do |el|
183
- next unless el.respond_to? :remove_attribute
184
- el.remove_attribute(name)
185
- end
199
+ each { |el| el.delete name }
186
200
  self
187
201
  end
188
202
 
@@ -212,7 +226,7 @@ module Nokogiri
212
226
  def wrap(html, &blk)
213
227
  each do |j|
214
228
  new_parent = Nokogiri.make(html, &blk)
215
- j.parent.add_child(new_parent)
229
+ j.add_next_sibling(new_parent)
216
230
  new_parent.add_child(j)
217
231
  end
218
232
  self
@@ -275,11 +289,19 @@ module Nokogiri
275
289
  end
276
290
 
277
291
  ###
278
- # Returns a new NodeSet containing all the children of all the nodes in the NodeSet
292
+ # Returns a new NodeSet containing all the children of all the nodes in
293
+ # the NodeSet
279
294
  def children
280
295
  inject(NodeSet.new(document)) { |set, node| set += node.children }
281
296
  end
282
297
 
298
+ ###
299
+ # Return a nicely formated string representation
300
+ def inspect
301
+ "[#{map { |c| c.inspect }.join ', '}]"
302
+ end
303
+
304
+ alias :+ :|
283
305
  end
284
306
  end
285
307
  end