nokogiri 1.5.0-x86-mingw32 → 1.5.1.rc1-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 (63) hide show
  1. data/CHANGELOG.ja.rdoc +39 -12
  2. data/CHANGELOG.rdoc +28 -0
  3. data/C_CODING_STYLE.rdoc +27 -0
  4. data/Manifest.txt +4 -0
  5. data/README.rdoc +11 -7
  6. data/Rakefile +40 -25
  7. data/bin/nokogiri +10 -2
  8. data/ext/nokogiri/extconf.rb +9 -1
  9. data/ext/nokogiri/html_document.c +16 -0
  10. data/ext/nokogiri/html_sax_parser_context.c +59 -37
  11. data/ext/nokogiri/html_sax_push_parser.c +87 -0
  12. data/ext/nokogiri/html_sax_push_parser.h +9 -0
  13. data/ext/nokogiri/nokogiri.c +6 -8
  14. data/ext/nokogiri/nokogiri.h +3 -0
  15. data/ext/nokogiri/xml_document.c +101 -3
  16. data/ext/nokogiri/xml_document.h +3 -3
  17. data/ext/nokogiri/xml_node.c +150 -58
  18. data/ext/nokogiri/xml_node_set.c +169 -120
  19. data/ext/nokogiri/xml_node_set.h +5 -0
  20. data/ext/nokogiri/xml_sax_parser_context.c +64 -41
  21. data/ext/nokogiri/xml_text.c +2 -0
  22. data/ext/nokogiri/xml_xpath_context.c +30 -24
  23. data/ext/nokogiri/xslt_stylesheet.c +62 -16
  24. data/ext/nokogiri/xslt_stylesheet.h +5 -0
  25. data/lib/nokogiri/1.8/nokogiri.so +0 -0
  26. data/lib/nokogiri/1.9/nokogiri.so +0 -0
  27. data/lib/nokogiri/css/parser.rb +165 -159
  28. data/lib/nokogiri/css/parser.y +6 -3
  29. data/lib/nokogiri/css/tokenizer.rb +1 -1
  30. data/lib/nokogiri/css/tokenizer.rex +1 -1
  31. data/lib/nokogiri/html.rb +1 -0
  32. data/lib/nokogiri/html/document.rb +82 -42
  33. data/lib/nokogiri/html/sax/push_parser.rb +16 -0
  34. data/lib/nokogiri/version.rb +1 -1
  35. data/lib/nokogiri/xml.rb +6 -0
  36. data/lib/nokogiri/xml/builder.rb +7 -1
  37. data/lib/nokogiri/xml/document.rb +32 -17
  38. data/lib/nokogiri/xml/document_fragment.rb +6 -1
  39. data/lib/nokogiri/xml/node.rb +40 -9
  40. data/lib/nokogiri/xslt.rb +5 -1
  41. data/tasks/cross_compile.rb +1 -0
  42. data/tasks/nokogiri.org.rb +6 -0
  43. data/tasks/test.rb +1 -0
  44. data/test/css/test_xpath_visitor.rb +6 -0
  45. data/test/helper.rb +1 -0
  46. data/test/html/test_document.rb +26 -0
  47. data/test/html/test_document_fragment.rb +1 -2
  48. data/test/test_memory_leak.rb +81 -1
  49. data/test/test_xslt_transforms.rb +152 -123
  50. data/test/xml/test_builder.rb +24 -2
  51. data/test/xml/test_c14n.rb +151 -0
  52. data/test/xml/test_document.rb +48 -0
  53. data/test/xml/test_namespace.rb +5 -0
  54. data/test/xml/test_node.rb +82 -1
  55. data/test/xml/test_node_attributes.rb +19 -0
  56. data/test/xml/test_node_inheritance.rb +32 -0
  57. data/test/xml/test_node_reparenting.rb +32 -0
  58. data/test/xml/test_node_set.rb +16 -8
  59. data/test/xml/test_reader_encoding.rb +16 -0
  60. data/test/xml/test_unparented_node.rb +24 -0
  61. data/test/xml/test_xinclude.rb +83 -0
  62. data/test/xml/test_xpath.rb +22 -0
  63. metadata +159 -126
@@ -69,6 +69,10 @@ rule
69
69
  : '.' IDENT { result = Node.new(:CLASS_CONDITION, [val[1]]) }
70
70
  ;
71
71
  element_name
72
+ : namespaced_ident
73
+ | '*' { result = Node.new(:ELEMENT_NAME, val) }
74
+ ;
75
+ namespaced_ident
72
76
  : namespace '|' IDENT {
73
77
  result = Node.new(:ELEMENT_NAME,
74
78
  [[val.first, val.last].compact.join(':')]
@@ -78,16 +82,15 @@ rule
78
82
  name = @namespaces.key?('xmlns') ? "xmlns:#{val.first}" : val.first
79
83
  result = Node.new(:ELEMENT_NAME, [name])
80
84
  }
81
- | '*' { result = Node.new(:ELEMENT_NAME, val) }
82
85
  ;
83
86
  namespace
84
87
  : IDENT { result = val[0] }
85
88
  |
86
89
  ;
87
90
  attrib
88
- : LSQUARE IDENT attrib_val_0or1 RSQUARE {
91
+ : LSQUARE namespaced_ident attrib_val_0or1 RSQUARE {
89
92
  result = Node.new(:ATTRIBUTE_CONDITION,
90
- [Node.new(:ELEMENT_NAME, [val[1]])] + (val[2] || [])
93
+ [val[1]] + (val[2] || [])
91
94
  )
92
95
  }
93
96
  | LSQUARE function attrib_val_0or1 RSQUARE {
@@ -6,7 +6,7 @@
6
6
 
7
7
  module Nokogiri
8
8
  module CSS
9
- class Tokenizer
9
+ class Tokenizer # :nodoc:
10
10
  require 'strscan'
11
11
 
12
12
  class ScanError < StandardError ; end
@@ -1,6 +1,6 @@
1
1
  module Nokogiri
2
2
  module CSS
3
- class Tokenizer
3
+ class Tokenizer # :nodoc:
4
4
 
5
5
  macro
6
6
  nl \n|\r\n|\r|\f
@@ -3,6 +3,7 @@ require 'nokogiri/html/document'
3
3
  require 'nokogiri/html/document_fragment'
4
4
  require 'nokogiri/html/sax/parser_context'
5
5
  require 'nokogiri/html/sax/parser'
6
+ require 'nokogiri/html/sax/push_parser'
6
7
  require 'nokogiri/html/element_description'
7
8
  require 'nokogiri/html/element_description_defaults'
8
9
 
@@ -19,7 +19,9 @@ module Nokogiri
19
19
 
20
20
  def meta_content_type
21
21
  css('meta[@http-equiv]').find { |node|
22
- node['http-equiv'] =~ /\AContent-Type\z/i
22
+ node['http-equiv'] =~ /\AContent-Type\z/i and
23
+ !node['content'].nil? and
24
+ !node['content'].empty?
23
25
  }
24
26
  end
25
27
  private :meta_content_type
@@ -92,17 +94,22 @@ module Nokogiri
92
94
  if string_or_io.respond_to?(:read)
93
95
  url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
94
96
  if !encoding
95
- # Perform advanced encoding detection that libxml2 does
96
- # not do.
97
+ # Libxml2's parser has poor support for encoding
98
+ # detection. First, it does not recognize the HTML5
99
+ # style meta charset declaration. Secondly, even if it
100
+ # successfully detects an encoding hint, it does not
101
+ # re-decode or re-parse the preceding part which may be
102
+ # garbled.
103
+ #
104
+ # EncodingReader aims to perform advanced encoding
105
+ # detection beyond what Libxml2 does, and to emulate
106
+ # rewinding of a stream and make Libxml2 redo parsing
107
+ # from the start when an encoding hint is found.
97
108
  string_or_io = EncodingReader.new(string_or_io)
98
109
  begin
99
110
  return read_io(string_or_io, url, encoding, options.to_i)
100
- rescue EncodingFoundException => e
101
- # A retry is required because libxml2 has a problem in
102
- # that it cannot switch encoding well in the middle of
103
- # parsing, especially if it has already seen a
104
- # non-ASCII character when it finds an encoding hint.
105
- encoding = e.encoding
111
+ rescue EncodingFound => e
112
+ encoding = e.found_encoding
106
113
  end
107
114
  end
108
115
  return read_io(string_or_io, url, encoding, options.to_i)
@@ -111,19 +118,17 @@ module Nokogiri
111
118
  # read_memory pukes on empty docs
112
119
  return new if string_or_io.nil? or string_or_io.empty?
113
120
 
114
- if !encoding
115
- encoding = EncodingReader.detect_encoding(string_or_io)
116
- end
121
+ encoding ||= EncodingReader.detect_encoding(string_or_io)
117
122
 
118
123
  read_memory(string_or_io, url, encoding, options.to_i)
119
124
  end
120
125
  end
121
126
 
122
- class EncodingFoundException < Exception # :nodoc:
123
- attr_reader :encoding
127
+ class EncodingFound < StandardError # :nodoc:
128
+ attr_reader :found_encoding
124
129
 
125
130
  def initialize(encoding)
126
- @encoding = encoding
131
+ @found_encoding = encoding
127
132
  super("encoding found: %s" % encoding)
128
133
  end
129
134
  end
@@ -131,57 +136,91 @@ module Nokogiri
131
136
  class EncodingReader # :nodoc:
132
137
  class SAXHandler < Nokogiri::XML::SAX::Document # :nodoc:
133
138
  attr_reader :encoding
134
-
135
- def found(encoding)
136
- @encoding = encoding
137
- throw :found
139
+
140
+ def initialize
141
+ @encoding = nil
142
+ super()
138
143
  end
139
-
140
- def not_found(encoding)
141
- found nil
144
+
145
+ def start_element(name, attrs = [])
146
+ return unless name == 'meta'
147
+ attr = Hash[attrs]
148
+ charset = attr['charset'] and
149
+ @encoding = charset
150
+ http_equiv = attr['http-equiv'] and
151
+ http_equiv.match(/\AContent-Type\z/i) and
152
+ content = attr['content'] and
153
+ m = content.match(/;\s*charset\s*=\s*([\w-]+)/) and
154
+ @encoding = m[1]
155
+ end
156
+ end
157
+
158
+ class JumpSAXHandler < SAXHandler
159
+ def initialize(jumptag)
160
+ @jumptag = jumptag
161
+ super()
142
162
  end
143
163
 
144
164
  def start_element(name, attrs = [])
145
- case name
146
- when /\A(?:div|h1|img|p|br)\z/
147
- not_found
148
- when 'meta'
149
- attr = Hash[attrs]
150
- charset = attr['charset'] and
151
- found charset
152
- http_equiv = attr['http-equiv'] and
153
- http_equiv.match(/\AContent-Type\z/i) and
154
- content = attr['content'] and
155
- m = content.match(/;\s*charset\s*=\s*([\w-]+)/) and
156
- found m[1]
157
- end
165
+ super
166
+ throw @jumptag, @encoding if @encoding
167
+ throw @jumptag, nil if name =~ /\A(?:div|h1|img|p|br)\z/
158
168
  end
159
169
  end
160
170
 
161
171
  def self.detect_encoding(chunk)
172
+ if Nokogiri.jruby? && EncodingReader.is_jruby_without_fix?
173
+ return EncodingReader.detect_encoding_for_jruby_without_fix(chunk)
174
+ end
162
175
  m = chunk.match(/\A(<\?xml[ \t\r\n]+[^>]*>)/) and
163
176
  return Nokogiri.XML(m[1]).encoding
164
177
 
165
178
  if Nokogiri.jruby?
166
179
  m = chunk.match(/(<meta\s)(.*)(charset\s*=\s*([\w-]+))(.*)/i) and
167
180
  return m[4]
181
+ catch(:encoding_found) {
182
+ Nokogiri::HTML::SAX::Parser.new(JumpSAXHandler.new(:encoding_found.to_s)).parse(chunk)
183
+ nil
184
+ }
185
+ else
186
+ handler = SAXHandler.new
187
+ parser = Nokogiri::HTML::SAX::PushParser.new(handler)
188
+ parser << chunk rescue Nokogiri::SyntaxError
189
+ handler.encoding
168
190
  end
191
+ end
192
+
193
+ def self.is_jruby_without_fix?
194
+ JRUBY_VERSION.split('.').join.to_i < 165
195
+ end
169
196
 
170
- handler = SAXHandler.new
171
- parser = Nokogiri::HTML::SAX::Parser.new(handler)
172
- catch(:found) {
173
- parser.parse(chunk)
197
+ def self.detect_encoding_for_jruby_without_fix(chunk)
198
+ m = chunk.match(/\A(<\?xml[ \t\r\n]+[^>]*>)/) and
199
+ return Nokogiri.XML(m[1]).encoding
200
+
201
+ m = chunk.match(/(<meta\s)(.*)(charset\s*=\s*([\w-]+))(.*)/i) and
202
+ return m[4]
203
+
204
+ catch(:encoding_found) {
205
+ Nokogiri::HTML::SAX::Parser.new(JumpSAXHandler.new(:encoding_found.to_s)).parse(chunk)
206
+ nil
174
207
  }
175
- handler.encoding
176
- rescue
208
+ rescue Nokogiri::SyntaxError, RuntimeError
209
+ # Ignore parser errors that nokogiri may raise
177
210
  nil
178
211
  end
179
212
 
180
213
  def initialize(io)
181
214
  @io = io
182
215
  @firstchunk = nil
216
+ @encoding_found = nil
183
217
  end
184
218
 
219
+ # This method is used by the C extension so that
220
+ # Nokogiri::HTML::Document#read_io() does not leak memory when
221
+ # EncodingFound is raised.
222
+ attr_reader :encoding_found
223
+
185
224
  def read(len)
186
225
  # no support for a call without len
187
226
 
@@ -193,9 +232,10 @@ module Nokogiri
193
232
  # achieve advanced encoding detection.
194
233
  if encoding = EncodingReader.detect_encoding(@firstchunk)
195
234
  # The first chunk is stored for the next read in retry.
196
- raise EncodingFoundException, encoding
235
+ raise @encoding_found = EncodingFound.new(encoding)
197
236
  end
198
237
  end
238
+ @encoding_found = nil
199
239
 
200
240
  ret = @firstchunk.slice!(0, len)
201
241
  if (len -= ret.length) > 0
@@ -0,0 +1,16 @@
1
+ module Nokogiri
2
+ module HTML
3
+ module SAX
4
+ class PushParser
5
+ def initialize(doc = XML::SAX::Document.new, file_name = nil, encoding = 'UTF-8')
6
+ @document = doc
7
+ @encoding = encoding
8
+ @sax_parser = HTML::SAX::Parser.new(doc, @encoding)
9
+
10
+ ## Create our push parser context
11
+ initialize_native(@sax_parser, file_name, @encoding)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,6 +1,6 @@
1
1
  module Nokogiri
2
2
  # The version of Nokogiri you are using
3
- VERSION = '1.5.0'
3
+ VERSION = '1.5.1.rc1'
4
4
 
5
5
  class VersionInfo # :nodoc:
6
6
  def jruby?
@@ -35,6 +35,12 @@ module Nokogiri
35
35
  end
36
36
 
37
37
  module XML
38
+ # Original C14N 1.0 spec canonicalization
39
+ XML_C14N_1_0 = 0
40
+ # Exclusive C14N 1.0 spec canonicalization
41
+ XML_C14N_EXCLUSIVE_1_0 = 1
42
+ # C14N 1.1 spec canonicalization
43
+ XML_C14N_1_1 = 2
38
44
  class << self
39
45
  ###
40
46
  # Parse an XML document using the Nokogiri::XML::Reader API. See
@@ -305,7 +305,13 @@ module Nokogiri
305
305
  ###
306
306
  # Create a CDATA Node with content of +string+
307
307
  def cdata string
308
- insert(doc.create_cdata(string))
308
+ insert doc.create_cdata(string)
309
+ end
310
+
311
+ ###
312
+ # Create a Comment Node with content of +string+
313
+ def comment string
314
+ insert doc.create_comment(string)
309
315
  end
310
316
 
311
317
  ###
@@ -8,6 +8,12 @@ module Nokogiri
8
8
  # For searching a Document, see Nokogiri::XML::Node#css and
9
9
  # Nokogiri::XML::Node#xpath
10
10
  class Document < Nokogiri::XML::Node
11
+ # I'm ignoring unicode characters here.
12
+ # See http://www.w3.org/TR/REC-xml-names/#ns-decl for more details.
13
+ NCNAME_START_CHAR = "A-Za-z_"
14
+ NCNAME_CHAR = NCNAME_START_CHAR + "\\-.0-9"
15
+ NCNAME_RE = /^xmlns(:[#{NCNAME_START_CHAR}][#{NCNAME_CHAR}]*)?$/
16
+
11
17
  ##
12
18
  # Parse an XML file. +string_or_io+ may be a String, or any object that
13
19
  # responds to _read_ and _close_ such as an IO, or StringIO.
@@ -17,20 +23,23 @@ module Nokogiri
17
23
  # Nokogiri::XML::ParseOptions::RECOVER. See the constants in
18
24
  # Nokogiri::XML::ParseOptions.
19
25
  def self.parse string_or_io, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML, &block
20
-
21
26
  options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
22
27
  # Give the options to the user
23
28
  yield options if block_given?
24
29
 
25
- if string_or_io.respond_to?(:read)
30
+ doc = if string_or_io.respond_to?(:read)
26
31
  url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
27
- return read_io(string_or_io, url, encoding, options.to_i)
32
+ read_io(string_or_io, url, encoding, options.to_i)
33
+ else
34
+ # read_memory pukes on empty docs
35
+ return new if string_or_io.nil? or string_or_io.empty?
36
+ read_memory(string_or_io, url, encoding, options.to_i)
28
37
  end
29
38
 
30
- # read_memory pukes on empty docs
31
- return new if string_or_io.nil? or string_or_io.empty?
39
+ # do xinclude processing
40
+ doc.do_xinclude(options) if options.xinclude?
32
41
 
33
- read_memory(string_or_io, url, encoding, options.to_i)
42
+ return doc
34
43
  end
35
44
 
36
45
  # A list of Nokogiri::XML::SyntaxError found when parsing a document
@@ -57,7 +66,7 @@ module Nokogiri
57
66
  when Hash
58
67
  arg.each { |k,v|
59
68
  key = k.to_s
60
- if key =~ /^xmlns(:\w+)?$/
69
+ if key =~ NCNAME_RE
61
70
  ns_name = key.split(":", 2)[1]
62
71
  elm.add_namespace_definition ns_name, v
63
72
  next
@@ -71,14 +80,19 @@ module Nokogiri
71
80
  elm
72
81
  end
73
82
 
74
- # Create a text node with +text+
75
- def create_text_node text, &block
76
- Nokogiri::XML::Text.new(text.to_s, self, &block)
83
+ # Create a Text Node with +string+
84
+ def create_text_node string, &block
85
+ Nokogiri::XML::Text.new string.to_s, self, &block
86
+ end
87
+
88
+ # Create a CDATA Node containing +string+
89
+ def create_cdata string, &block
90
+ Nokogiri::XML::CDATA.new self, string.to_s, &block
77
91
  end
78
92
 
79
- # Create a CDATA element containing +text+
80
- def create_cdata text
81
- Nokogiri::XML::CDATA.new(self, text.to_s)
93
+ # Create a Comment Node containing +string+
94
+ def create_comment string, &block
95
+ Nokogiri::XML::Comment.new self, string.to_s, &block
82
96
  end
83
97
 
84
98
  # The name of this document. Always returns "document"
@@ -194,11 +208,12 @@ module Nokogiri
194
208
  undef_method :add_namespace_definition, :attributes
195
209
  undef_method :namespace_definitions, :line, :add_namespace
196
210
 
197
- def add_child child
211
+ def add_child node_or_tags
198
212
  raise "Document already has a root node" if root
199
- if child.type == Node::DOCUMENT_FRAG_NODE
200
- raise "Document cannot have multiple root nodes" if child.children.size > 1
201
- super(child.children.first)
213
+ node_or_tags = coerce(node_or_tags)
214
+ if node_or_tags.is_a?(XML::NodeSet)
215
+ raise "Document cannot have multiple root nodes" if node_or_tags.size > 1
216
+ super(node_or_tags.first)
202
217
  else
203
218
  super
204
219
  end
@@ -11,7 +11,12 @@ module Nokogiri
11
11
  return self unless tags
12
12
 
13
13
  children = if ctx
14
- ctx.parse(tags)
14
+ # Fix for issue#490
15
+ if Nokogiri.jruby?
16
+ ctx.parse("<root>#{tags}</root>").xpath("/root/node()")
17
+ else
18
+ ctx.parse(tags)
19
+ end
15
20
  else
16
21
  XML::Document.parse("<root>#{tags}</root>") \
17
22
  .xpath("/root/node()")
@@ -255,6 +255,12 @@ module Nokogiri
255
255
  get(name.to_s)
256
256
  end
257
257
 
258
+ ###
259
+ # Set the attribute value for the attribute +name+ to +value+
260
+ def []= name, value
261
+ set name.to_s, value
262
+ end
263
+
258
264
  ###
259
265
  # Add +node_or_tags+ as a child of this Node.
260
266
  # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
@@ -291,6 +297,8 @@ module Nokogiri
291
297
  #
292
298
  # Also see related method +before+.
293
299
  def add_previous_sibling node_or_tags
300
+ raise ArgumentError.new("A document may not have multiple root nodes.") if parent.is_a?(XML::Document)
301
+
294
302
  node_or_tags = coerce(node_or_tags)
295
303
  if node_or_tags.is_a?(XML::NodeSet)
296
304
  if text?
@@ -315,6 +323,8 @@ module Nokogiri
315
323
  #
316
324
  # Also see related method +after+.
317
325
  def add_next_sibling node_or_tags
326
+ raise ArgumentError.new("A document may not have multiple root nodes.") if parent.is_a?(XML::Document)
327
+
318
328
  node_or_tags = coerce(node_or_tags)
319
329
  if node_or_tags.is_a?(XML::NodeSet)
320
330
  if text?
@@ -452,9 +462,9 @@ module Nokogiri
452
462
  # If you need to distinguish attributes with the same name, with different namespaces
453
463
  # use #attribute_nodes instead.
454
464
  def attributes
455
- Hash[*(attribute_nodes.map { |node|
465
+ Hash[attribute_nodes.map { |node|
456
466
  [node.node_name, node]
457
- }.flatten)]
467
+ }]
458
468
  end
459
469
 
460
470
  ###
@@ -471,9 +481,9 @@ module Nokogiri
471
481
 
472
482
  ###
473
483
  # Iterate over each attribute name and value pair for this Node.
474
- def each &block
484
+ def each
475
485
  attribute_nodes.each { |node|
476
- block.call([node.node_name, node.value])
486
+ yield [node.node_name, node.value]
477
487
  }
478
488
  end
479
489
 
@@ -555,7 +565,7 @@ module Nokogiri
555
565
  # default namespaces set on ancestor will NOT be, even if self
556
566
  # has no explicit default namespace.
557
567
  def namespaces
558
- Hash[*namespace_scopes.map { |nd|
568
+ Hash[namespace_scopes.map { |nd|
559
569
  key = ['xmlns', nd.prefix].compact.join(':')
560
570
  if RUBY_VERSION >= '1.9' && document.encoding
561
571
  begin
@@ -564,7 +574,7 @@ module Nokogiri
564
574
  end
565
575
  end
566
576
  [key, nd.href]
567
- }.flatten]
577
+ }]
568
578
  end
569
579
 
570
580
  # Returns true if this is a Comment
@@ -766,8 +776,7 @@ module Nokogiri
766
776
  #
767
777
  # See Node#write_to for a list of +options+
768
778
  def to_xml options = {}
769
- options[:save_with] |= SaveOptions::DEFAULT_XML if options[:save_with]
770
- options[:save_with] = SaveOptions::DEFAULT_XML unless options[:save_with]
779
+ options[:save_with] ||= SaveOptions::DEFAULT_XML
771
780
  serialize(options)
772
781
  end
773
782
 
@@ -865,6 +874,28 @@ module Nokogiri
865
874
  compare other
866
875
  end
867
876
 
877
+ ###
878
+ # Do xinclude substitution on the subtree below node. If given a block, a
879
+ # Nokogiri::XML::ParseOptions object initialized from +options+, will be
880
+ # passed to it, allowing more convenient modification of the parser options.
881
+ def do_xinclude options = XML::ParseOptions::DEFAULT_XML, &block
882
+ options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
883
+
884
+ # give options to user
885
+ yield options if block_given?
886
+
887
+ # call c extension
888
+ process_xincludes(options.to_i)
889
+ end
890
+
891
+ def canonicalize(mode=XML::XML_C14N_1_0,inclusive_namespaces=nil,with_comments=false)
892
+ c14n_root = self
893
+ document.canonicalize(mode, inclusive_namespaces, with_comments) do |node, parent|
894
+ tn = node.is_a?(XML::Node) ? node : parent
895
+ tn == c14n_root || tn.ancestors.include?(c14n_root)
896
+ end
897
+ end
898
+
868
899
  private
869
900
 
870
901
  def extract_params params # :nodoc:
@@ -893,7 +924,7 @@ module Nokogiri
893
924
  return data.children if data.is_a?(XML::DocumentFragment)
894
925
  return fragment(data).children if data.is_a?(String)
895
926
 
896
- if data.is_a?(Document) || !data.is_a?(XML::Node)
927
+ if data.is_a?(Document) || data.is_a?(XML::Attr) || !data.is_a?(XML::Node)
897
928
  raise ArgumentError, <<-EOERR
898
929
  Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
899
930
  (You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)