nokogiri 1.6.5-x86-mingw32 → 1.6.6.1-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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.cross_rubies +5 -0
  3. data/.travis.yml +10 -20
  4. data/CHANGELOG.ja.rdoc +28 -1
  5. data/CHANGELOG.rdoc +28 -1
  6. data/Gemfile +1 -1
  7. data/Manifest.txt +5 -1
  8. data/README.ja.rdoc +10 -9
  9. data/README.rdoc +6 -9
  10. data/ROADMAP.md +15 -3
  11. data/Rakefile +1 -3
  12. data/bin/nokogiri +48 -8
  13. data/ext/nokogiri/extconf.rb +18 -3
  14. data/ext/nokogiri/xml_comment.c +17 -2
  15. data/ext/nokogiri/xml_node.c +66 -6
  16. data/ext/nokogiri/xml_syntax_error.c +4 -0
  17. data/ext/nokogiri/xml_syntax_error.h +1 -0
  18. data/lib/nokogiri.rb +2 -2
  19. data/lib/nokogiri/1.9/nokogiri.so +0 -0
  20. data/lib/nokogiri/2.0/nokogiri.so +0 -0
  21. data/lib/nokogiri/2.1/nokogiri.so +0 -0
  22. data/lib/nokogiri/decorators/slop.rb +7 -8
  23. data/lib/nokogiri/html/document_fragment.rb +0 -2
  24. data/lib/nokogiri/html/sax/push_parser.rb +22 -2
  25. data/lib/nokogiri/version.rb +1 -1
  26. data/lib/nokogiri/xml.rb +1 -0
  27. data/lib/nokogiri/xml/document.rb +4 -4
  28. data/lib/nokogiri/xml/document_fragment.rb +39 -2
  29. data/lib/nokogiri/xml/node.rb +11 -181
  30. data/lib/nokogiri/xml/node_set.rb +41 -85
  31. data/lib/nokogiri/xml/searchable.rb +221 -0
  32. data/test/css/test_nthiness.rb +1 -1
  33. data/test/html/sax/test_push_parser.rb +87 -0
  34. data/test/html/test_document.rb +20 -5
  35. data/test/html/test_document_fragment.rb +25 -0
  36. data/test/xml/test_attr.rb +5 -2
  37. data/test/xml/test_builder.rb +27 -1
  38. data/test/xml/test_comment.rb +11 -0
  39. data/test/xml/test_document.rb +34 -0
  40. data/test/xml/test_document_fragment.rb +40 -9
  41. data/test/xml/test_namespace.rb +1 -0
  42. data/test/xml/test_node.rb +37 -1
  43. data/test/xml/test_node_set.rb +56 -36
  44. data/test/xml/test_xpath.rb +65 -19
  45. data/test_all +11 -1
  46. metadata +10 -7
  47. data/tasks/nokogiri.org.rb +0 -24
@@ -1,10 +1,13 @@
1
1
  #include <xml_comment.h>
2
2
 
3
+ static ID document_id ;
4
+
3
5
  /*
4
6
  * call-seq:
5
- * new(document, content)
7
+ * new(document_or_node, content)
6
8
  *
7
- * Create a new Comment element on the +document+ with +content+
9
+ * Create a new Comment element on the +document+ with +content+.
10
+ * Alternatively, if a +node+ is passed, the +node+'s document is used.
8
11
  */
9
12
  static VALUE new(int argc, VALUE *argv, VALUE klass)
10
13
  {
@@ -17,6 +20,16 @@ static VALUE new(int argc, VALUE *argv, VALUE klass)
17
20
 
18
21
  rb_scan_args(argc, argv, "2*", &document, &content, &rest);
19
22
 
23
+ if (rb_obj_is_kind_of(document, cNokogiriXmlNode))
24
+ {
25
+ document = rb_funcall(document, document_id, 0);
26
+ }
27
+ else if ( !rb_obj_is_kind_of(document, cNokogiriXmlDocument)
28
+ && !rb_obj_is_kind_of(document, cNokogiriXmlDocumentFragment))
29
+ {
30
+ rb_raise(rb_eArgError, "first argument must be a XML::Document or XML::Node");
31
+ }
32
+
20
33
  Data_Get_Struct(document, xmlDoc, xml_doc);
21
34
 
22
35
  node = xmlNewDocComment(
@@ -51,4 +64,6 @@ void init_xml_comment()
51
64
  cNokogiriXmlComment = klass;
52
65
 
53
66
  rb_define_singleton_method(klass, "new", new, -1);
67
+
68
+ document_id = rb_intern("document");
54
69
  }
@@ -14,7 +14,7 @@ static void debug_node_dealloc(xmlNodePtr x)
14
14
 
15
15
  static void mark(xmlNodePtr node)
16
16
  {
17
- xmlNodePtr doc = node->doc;
17
+ xmlDocPtr doc = node->doc;
18
18
  if(doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE) {
19
19
  if(DOC_RUBY_OBJECT_TEST(doc)) {
20
20
  rb_gc_mark(DOC_RUBY_OBJECT(doc));
@@ -234,7 +234,15 @@ ok:
234
234
  * reparent the actual reparentee, so we reparent a duplicate.
235
235
  */
236
236
  nokogiri_root_node(reparentee);
237
- if (!(reparentee = xmlDocCopyNode(reparentee, pivot->doc, 1))) {
237
+
238
+ xmlResetLastError();
239
+ xmlSetStructuredErrorFunc((void *)rb_iv_get(DOC_RUBY_OBJECT(pivot->doc), "@errors"), Nokogiri_error_array_pusher);
240
+
241
+ reparentee = xmlDocCopyNode(reparentee, pivot->doc, 1) ;
242
+
243
+ xmlSetStructuredErrorFunc(NULL, NULL);
244
+
245
+ if (! reparentee) {
238
246
  rb_raise(rb_eRuntimeError, "Could not reparent node (xmlDocCopyNode)");
239
247
  }
240
248
  }
@@ -473,7 +481,13 @@ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
473
481
 
474
482
  Data_Get_Struct(self, xmlNode, node);
475
483
 
484
+ xmlResetLastError();
485
+ xmlSetStructuredErrorFunc(NULL, Nokogiri_error_silencer);
486
+
476
487
  dup = xmlDocCopyNode(node, node->doc, (int)NUM2INT(level));
488
+
489
+ xmlSetStructuredErrorFunc(NULL, NULL);
490
+
477
491
  if(dup == NULL) return Qnil;
478
492
 
479
493
  nokogiri_root_node(dup);
@@ -1012,7 +1026,7 @@ static VALUE node_type(VALUE self)
1012
1026
  *
1013
1027
  * Set the content for this Node
1014
1028
  */
1015
- static VALUE native_content(VALUE self, VALUE content)
1029
+ static VALUE set_native_content(VALUE self, VALUE content)
1016
1030
  {
1017
1031
  xmlNodePtr node, child, next ;
1018
1032
  Data_Get_Struct(self, xmlNode, node);
@@ -1035,7 +1049,7 @@ static VALUE native_content(VALUE self, VALUE content)
1035
1049
  *
1036
1050
  * Returns the content for this Node
1037
1051
  */
1038
- static VALUE get_content(VALUE self)
1052
+ static VALUE get_native_content(VALUE self)
1039
1053
  {
1040
1054
  xmlNodePtr node;
1041
1055
  xmlChar * content;
@@ -1051,6 +1065,50 @@ static VALUE get_content(VALUE self)
1051
1065
  return Qnil;
1052
1066
  }
1053
1067
 
1068
+ /*
1069
+ * call-seq:
1070
+ * lang=
1071
+ *
1072
+ * Set the language of a node, i.e. the values of the xml:lang attribute.
1073
+ */
1074
+ static VALUE set_lang(VALUE self_rb, VALUE lang_rb)
1075
+ {
1076
+ xmlNodePtr self ;
1077
+ xmlChar* lang ;
1078
+
1079
+ Data_Get_Struct(self_rb, xmlNode, self);
1080
+ lang = (xmlChar*)StringValuePtr(lang_rb);
1081
+
1082
+ xmlNodeSetLang(self, lang);
1083
+
1084
+ return Qnil ;
1085
+ }
1086
+
1087
+ /*
1088
+ * call-seq:
1089
+ * lang
1090
+ *
1091
+ * Searches the language of a node, i.e. the values of the xml:lang attribute or
1092
+ * the one carried by the nearest ancestor.
1093
+ */
1094
+ static VALUE get_lang(VALUE self_rb)
1095
+ {
1096
+ xmlNodePtr self ;
1097
+ xmlChar* lang ;
1098
+ VALUE lang_rb ;
1099
+
1100
+ Data_Get_Struct(self_rb, xmlNode, self);
1101
+
1102
+ lang = xmlNodeGetLang(self);
1103
+ if (lang) {
1104
+ lang_rb = NOKOGIRI_STR_NEW2(lang);
1105
+ xmlFree(lang);
1106
+ return lang_rb ;
1107
+ }
1108
+
1109
+ return Qnil ;
1110
+ }
1111
+
1054
1112
  /* :nodoc: */
1055
1113
  static VALUE add_child(VALUE self, VALUE new_child)
1056
1114
  {
@@ -1561,7 +1619,6 @@ void init_xml_node()
1561
1619
  rb_define_method(klass, "next_element", next_element, 0);
1562
1620
  rb_define_method(klass, "previous_element", previous_element, 0);
1563
1621
  rb_define_method(klass, "node_type", node_type, 0);
1564
- rb_define_method(klass, "content", get_content, 0);
1565
1622
  rb_define_method(klass, "path", path, 0);
1566
1623
  rb_define_method(klass, "key?", key_eh, 1);
1567
1624
  rb_define_method(klass, "namespaced_key?", namespaced_key_eh, 2);
@@ -1581,7 +1638,10 @@ void init_xml_node()
1581
1638
  rb_define_method(klass, "create_external_subset", create_external_subset, 3);
1582
1639
  rb_define_method(klass, "pointer_id", pointer_id, 0);
1583
1640
  rb_define_method(klass, "line", line, 0);
1584
- rb_define_method(klass, "native_content=", native_content, 1);
1641
+ rb_define_method(klass, "content", get_native_content, 0);
1642
+ rb_define_method(klass, "native_content=", set_native_content, 1);
1643
+ rb_define_method(klass, "lang", get_lang, 0);
1644
+ rb_define_method(klass, "lang=", set_lang, 1);
1585
1645
 
1586
1646
  rb_define_private_method(klass, "process_xincludes", process_xincludes, 1);
1587
1647
  rb_define_private_method(klass, "in_context", in_context, 2);
@@ -7,6 +7,10 @@ void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error)
7
7
  rb_ary_push(list, Nokogiri_wrap_xml_syntax_error(error));
8
8
  }
9
9
 
10
+ void Nokogiri_error_silencer(void * ctx, xmlErrorPtr error)
11
+ {
12
+ }
13
+
10
14
  void Nokogiri_error_raise(void * ctx, xmlErrorPtr error)
11
15
  {
12
16
  rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
@@ -6,6 +6,7 @@
6
6
  void init_xml_syntax_error();
7
7
  VALUE Nokogiri_wrap_xml_syntax_error(xmlErrorPtr error);
8
8
  void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error);
9
+ void Nokogiri_error_silencer(void * ctx, xmlErrorPtr error);
9
10
  NORETURN(void Nokogiri_error_raise(void * ctx, xmlErrorPtr error));
10
11
 
11
12
  extern VALUE cNokogiriXmlSyntaxError;
@@ -61,8 +61,8 @@ require 'nokogiri/html/builder'
61
61
  # puts link.content
62
62
  # end
63
63
  #
64
- # See Nokogiri::XML::Node#css for more information about CSS searching.
65
- # See Nokogiri::XML::Node#xpath for more information about XPath searching.
64
+ # See Nokogiri::XML::Searchable#css for more information about CSS searching.
65
+ # See Nokogiri::XML::Searchable#xpath for more information about XPath searching.
66
66
  module Nokogiri
67
67
  class << self
68
68
  ###
Binary file
Binary file
Binary file
@@ -4,25 +4,26 @@ module Nokogiri
4
4
  # The Slop decorator implements method missing such that a methods may be
5
5
  # used instead of XPath or CSS. See Nokogiri.Slop
6
6
  module Slop
7
+ # The default XPath search context for Slop
8
+ XPATH_PREFIX = "./"
9
+
7
10
  ###
8
11
  # look for node with +name+. See Nokogiri.Slop
9
12
  def method_missing name, *args, &block
10
- prefix = implied_xpath_context
11
-
12
13
  if args.empty?
13
- list = xpath("#{prefix}#{name.to_s.sub(/^_/, '')}")
14
+ list = xpath("#{XPATH_PREFIX}#{name.to_s.sub(/^_/, '')}")
14
15
  elsif args.first.is_a? Hash
15
16
  hash = args.first
16
17
  if hash[:css]
17
18
  list = css("#{name}#{hash[:css]}")
18
19
  elsif hash[:xpath]
19
20
  conds = Array(hash[:xpath]).join(' and ')
20
- list = xpath("#{prefix}#{name}[#{conds}]")
21
+ list = xpath("#{XPATH_PREFIX}#{name}[#{conds}]")
21
22
  end
22
23
  else
23
24
  CSS::Parser.without_cache do
24
25
  list = xpath(
25
- *CSS.xpath_for("#{name}#{args.first}", :prefix => prefix)
26
+ *CSS.xpath_for("#{name}#{args.first}", :prefix => XPATH_PREFIX)
26
27
  )
27
28
  end
28
29
  end
@@ -32,9 +33,7 @@ module Nokogiri
32
33
  end
33
34
 
34
35
  def respond_to_missing? name, include_private = false
35
- prefix = implied_xpath_context
36
-
37
- list = xpath("#{prefix}#{name.to_s.sub(/^_/, '')}")
36
+ list = xpath("#{XPATH_PREFIX}#{name.to_s.sub(/^_/, '')}")
38
37
 
39
38
  !list.empty?
40
39
  end
@@ -1,8 +1,6 @@
1
1
  module Nokogiri
2
2
  module HTML
3
3
  class DocumentFragment < Nokogiri::XML::DocumentFragment
4
- attr_accessor :errors
5
-
6
4
  ####
7
5
  # Create a Nokogiri::XML::DocumentFragment from +tags+, using +encoding+
8
6
  def self.parse tags, encoding = nil
@@ -2,13 +2,33 @@ module Nokogiri
2
2
  module HTML
3
3
  module SAX
4
4
  class PushParser
5
- def initialize(doc = XML::SAX::Document.new, file_name = nil, encoding = 'UTF-8')
5
+
6
+ # The Nokogiri::HTML::SAX::Document on which the PushParser will be
7
+ # operating
8
+ attr_accessor :document
9
+
10
+ def initialize(doc = HTML::SAX::Document.new, file_name = nil, encoding = 'UTF-8')
6
11
  @document = doc
7
12
  @encoding = encoding
8
13
  @sax_parser = HTML::SAX::Parser.new(doc, @encoding)
9
14
 
10
15
  ## Create our push parser context
11
- initialize_native(@sax_parser, file_name, @encoding)
16
+ initialize_native(@sax_parser, file_name, encoding)
17
+ end
18
+
19
+ ###
20
+ # Write a +chunk+ of HTML to the PushParser. Any callback methods
21
+ # that can be called will be called immediately.
22
+ def write chunk, last_chunk = false
23
+ native_write(chunk, last_chunk)
24
+ end
25
+ alias :<< :write
26
+
27
+ ###
28
+ # Finish the parsing. This method is only necessary for
29
+ # Nokogiri::HTML::SAX::Document#end_document to be called.
30
+ def finish
31
+ write '', true
12
32
  end
13
33
  end
14
34
  end
@@ -1,6 +1,6 @@
1
1
  module Nokogiri
2
2
  # The version of Nokogiri you are using
3
- VERSION = '1.6.5'
3
+ VERSION = '1.6.6.1'
4
4
 
5
5
  class VersionInfo # :nodoc:
6
6
  def jruby?
@@ -1,6 +1,7 @@
1
1
  require 'nokogiri/xml/pp'
2
2
  require 'nokogiri/xml/parse_options'
3
3
  require 'nokogiri/xml/sax'
4
+ require 'nokogiri/xml/searchable'
4
5
  require 'nokogiri/xml/node'
5
6
  require 'nokogiri/xml/attribute_decl'
6
7
  require 'nokogiri/xml/element_decl'
@@ -5,8 +5,8 @@ module Nokogiri
5
5
  # XML documents. The Document is created by parsing an XML document.
6
6
  # See Nokogiri::XML::Document.parse() for more information on parsing.
7
7
  #
8
- # For searching a Document, see Nokogiri::XML::Node#css and
9
- # Nokogiri::XML::Node#xpath
8
+ # For searching a Document, see Nokogiri::XML::Searchable#css and
9
+ # Nokogiri::XML::Searchable#xpath
10
10
  #
11
11
  class Document < Nokogiri::XML::Node
12
12
  # I'm ignoring unicode characters here.
@@ -267,8 +267,8 @@ module Nokogiri
267
267
  (string_or_io.respond_to?(:eof?) && string_or_io.eof?)
268
268
  end
269
269
 
270
- def implied_xpath_context
271
- "/"
270
+ def implied_xpath_contexts # :nodoc:
271
+ ["//"]
272
272
  end
273
273
 
274
274
  def inspect_attributes
@@ -73,15 +73,43 @@ module Nokogiri
73
73
  end
74
74
 
75
75
  ###
76
- # Search this fragment. See Nokogiri::XML::Node#css
76
+ # call-seq: css *rules, [namespace-bindings, custom-pseudo-class]
77
+ #
78
+ # Search this fragment for CSS +rules+. +rules+ must be one or more CSS
79
+ # selectors. For example:
80
+ #
81
+ # For more information see Nokogiri::XML::Searchable#css
77
82
  def css *args
78
83
  if children.any?
79
- children.css(*args)
84
+ children.css(*args) # 'children' is a smell here
80
85
  else
81
86
  NodeSet.new(document)
82
87
  end
83
88
  end
84
89
 
90
+ #
91
+ # NOTE that we don't delegate #xpath to children ... another smell.
92
+ # def xpath ; end
93
+ #
94
+
95
+ ###
96
+ # call-seq: search *paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class]
97
+ #
98
+ # Search this fragment for +paths+. +paths+ must be one or more XPath or CSS queries.
99
+ #
100
+ # For more information see Nokogiri::XML::Searchable#search
101
+ def search *rules
102
+ rules, handler, ns, binds = extract_params(rules)
103
+
104
+ rules.inject(NodeSet.new(document)) do |set, rule|
105
+ set += if rule =~ Searchable::LOOKS_LIKE_XPATH
106
+ xpath(*([rule, ns, handler, binds].compact))
107
+ else
108
+ children.css(*([rule, ns, handler].compact)) # 'children' is a smell here
109
+ end
110
+ end
111
+ end
112
+
85
113
  alias :serialize :to_s
86
114
 
87
115
  class << self
@@ -92,6 +120,15 @@ module Nokogiri
92
120
  end
93
121
  end
94
122
 
123
+ # A list of Nokogiri::XML::SyntaxError found when parsing a document
124
+ def errors
125
+ document.errors
126
+ end
127
+
128
+ def errors= things # :nodoc:
129
+ document.errors = things
130
+ end
131
+
95
132
  private
96
133
 
97
134
  # fix for issue 770
@@ -32,9 +32,10 @@ module Nokogiri
32
32
  # * Nokogiri::XML::Node#next
33
33
  # * Nokogiri::XML::Node#previous
34
34
  #
35
- # You may search this node's subtree using Node#xpath and Node#css
35
+ # You may search this node's subtree using Searchable#xpath and Searchable#css
36
36
  class Node
37
37
  include Nokogiri::XML::PP::Node
38
+ include Nokogiri::XML::Searchable
38
39
  include Enumerable
39
40
 
40
41
  # Element node type, see Nokogiri::XML::Node#element?
@@ -90,130 +91,6 @@ module Nokogiri
90
91
  document.decorate(self)
91
92
  end
92
93
 
93
- ###
94
- # Search this node for +paths+. +paths+ can be XPath or CSS, and an
95
- # optional hash of namespaces may be appended.
96
- # See Node#xpath and Node#css.
97
- def search *paths
98
- # TODO use paths, handler, ns, binds = extract_params(paths)
99
- ns = paths.last.is_a?(Hash) ? paths.pop :
100
- (document.root ? document.root.namespaces : {})
101
-
102
- prefix = "#{implied_xpath_context}/"
103
-
104
- xpath(*(paths.map { |path|
105
- path = path.to_s
106
- path =~ /^(\.\/|\/|\.\.|\.$)/ ? path : CSS.xpath_for(
107
- path,
108
- :prefix => prefix,
109
- :ns => ns
110
- )
111
- }.flatten.uniq) + [ns])
112
- end
113
- alias :/ :search
114
-
115
- ###
116
- # call-seq: xpath *paths, [namespace-bindings, variable-bindings, custom-handler-class]
117
- #
118
- # Search this node for XPath +paths+. +paths+ must be one or more XPath
119
- # queries.
120
- #
121
- # node.xpath('.//title')
122
- #
123
- # A hash of namespace bindings may be appended. For example:
124
- #
125
- # node.xpath('.//foo:name', {'foo' => 'http://example.org/'})
126
- # node.xpath('.//xmlns:name', node.root.namespaces)
127
- #
128
- # A hash of variable bindings may also be appended to the namespace bindings. For example:
129
- #
130
- # node.xpath('.//address[@domestic=$value]', nil, {:value => 'Yes'})
131
- #
132
- # Custom XPath functions may also be defined. To define custom
133
- # functions create a class and implement the function you want
134
- # to define. The first argument to the method will be the
135
- # current matching NodeSet. Any other arguments are ones that
136
- # you pass in. Note that this class may appear anywhere in the
137
- # argument list. For example:
138
- #
139
- # node.xpath('.//title[regex(., "\w+")]', Class.new {
140
- # def regex node_set, regex
141
- # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
142
- # end
143
- # }.new)
144
- #
145
- def xpath *paths
146
- return NodeSet.new(document) unless document
147
-
148
- paths, handler, ns, binds = extract_params(paths)
149
-
150
- sets = paths.map { |path|
151
- ctx = XPathContext.new(self)
152
- ctx.register_namespaces(ns)
153
- path = path.gsub(/xmlns:/, ' :') unless Nokogiri.uses_libxml?
154
-
155
- binds.each do |key,value|
156
- ctx.register_variable key.to_s, value
157
- end if binds
158
-
159
- ctx.evaluate(path, handler)
160
- }
161
- return sets.first if sets.length == 1
162
-
163
- NodeSet.new(document) do |combined|
164
- sets.each do |set|
165
- set.each do |node|
166
- combined << node
167
- end
168
- end
169
- end
170
- end
171
-
172
- ###
173
- # call-seq: css *rules, [namespace-bindings, custom-pseudo-class]
174
- #
175
- # Search this node for CSS +rules+. +rules+ must be one or more CSS
176
- # selectors. For example:
177
- #
178
- # node.css('title')
179
- # node.css('body h1.bold')
180
- # node.css('div + p.green', 'div#one')
181
- #
182
- # A hash of namespace bindings may be appended. For example:
183
- #
184
- # node.css('bike|tire', {'bike' => 'http://schwinn.com/'})
185
- #
186
- # Custom CSS pseudo classes may also be defined. To define
187
- # custom pseudo classes, create a class and implement the custom
188
- # pseudo class you want defined. The first argument to the
189
- # method will be the current matching NodeSet. Any other
190
- # arguments are ones that you pass in. For example:
191
- #
192
- # node.css('title:regex("\w+")', Class.new {
193
- # def regex node_set, regex
194
- # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
195
- # end
196
- # }.new)
197
- #
198
- # Note that the CSS query string is case-sensitive with regards
199
- # to your document type. That is, if you're looking for "H1" in
200
- # an HTML document, you'll never find anything, since HTML tags
201
- # will match only lowercase CSS queries. However, "H1" might be
202
- # found in an XML document, where tags names are case-sensitive
203
- # (e.g., "H1" is distinct from "h1").
204
- #
205
- def css *rules
206
- rules, handler, ns, binds = extract_params(rules)
207
-
208
- prefix = "#{implied_xpath_context}/"
209
-
210
- rules = rules.map { |rule|
211
- CSS.xpath_for(rule, :prefix => prefix, :ns => ns)
212
- }.flatten.uniq + [ns, handler, binds].compact
213
-
214
- xpath(*rules)
215
- end
216
-
217
94
  ###
218
95
  # Search this node's immediate children using CSS selector +selector+
219
96
  def > selector
@@ -221,33 +98,6 @@ module Nokogiri
221
98
  xpath CSS.xpath_for(selector, :prefix => "./", :ns => ns).first
222
99
  end
223
100
 
224
- ###
225
- # Search for the first occurrence of +path+.
226
- #
227
- # Returns nil if nothing is found, otherwise a Node.
228
- def at path, ns = document.root ? document.root.namespaces : {}
229
- search(path, ns).first
230
- end
231
- alias :% :at
232
-
233
- ##
234
- # Search this node for the first occurrence of XPath +paths+.
235
- # Equivalent to <tt>xpath(paths).first</tt>
236
- # See Node#xpath for more information.
237
- #
238
- def at_xpath *paths
239
- xpath(*paths).first
240
- end
241
-
242
- ##
243
- # Search this node for the first occurrence of CSS +rules+.
244
- # Equivalent to <tt>css(rules).first</tt>
245
- # See Node#css for more information.
246
- #
247
- def at_css *rules
248
- css(*rules).first
249
- end
250
-
251
101
  ###
252
102
  # Get the attribute value for the attribute +name+
253
103
  def [] name
@@ -327,7 +177,7 @@ module Nokogiri
327
177
  # Also see related method +after+.
328
178
  def add_next_sibling node_or_tags
329
179
  raise ArgumentError.new("A document may not have multiple root nodes.") if (parent && parent.document?) && !node_or_tags.processing_instruction?
330
-
180
+
331
181
  add_sibling :next, node_or_tags
332
182
  end
333
183
 
@@ -485,7 +335,9 @@ module Nokogiri
485
335
  ###
486
336
  # Remove the attribute named +name+
487
337
  def remove_attribute name
488
- attributes[name].remove if key? name
338
+ attr = attributes[name].remove if key? name
339
+ clear_xpath_context if Nokogiri.jruby?
340
+ attr
489
341
  end
490
342
  alias :delete :remove_attribute
491
343
 
@@ -930,25 +782,8 @@ module Nokogiri
930
782
  write_to io, options
931
783
  end
932
784
 
933
- def extract_params params # :nodoc:
934
- # Pop off our custom function handler if it exists
935
- handler = params.find { |param|
936
- ![Hash, String, Symbol].include?(param.class)
937
- }
938
-
939
- params -= [handler] if handler
940
-
941
- hashes = []
942
- while Hash === params.last || params.last.nil?
943
- hashes << params.pop
944
- break if params.empty?
945
- end
946
-
947
- ns, binds = hashes.reverse
948
-
949
- ns ||= document.root ? document.root.namespaces : {}
950
-
951
- [params, handler, ns, binds]
785
+ def inspect_attributes
786
+ [:name, :namespace, :attribute_nodes, :children]
952
787
  end
953
788
 
954
789
  def coerce data # :nodoc:
@@ -971,22 +806,17 @@ Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
971
806
  EOERR
972
807
  end
973
808
 
974
- def implied_xpath_context
975
- "./"
976
- end
977
-
978
- def inspect_attributes
979
- [:name, :namespace, :attribute_nodes, :children]
809
+ def implied_xpath_contexts # :nodoc:
810
+ [".//"]
980
811
  end
981
812
 
982
- def add_child_node_and_reparent_attrs node
813
+ def add_child_node_and_reparent_attrs node # :nodoc:
983
814
  add_child_node node
984
815
  node.attribute_nodes.find_all { |a| a.name =~ /:/ }.each do |attr_node|
985
816
  attr_node.remove
986
817
  node[attr_node.name] = attr_node.value
987
818
  end
988
819
  end
989
-
990
820
  end
991
821
  end
992
822
  end