nokogiri 1.3.2 → 1.3.3

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 (66) hide show
  1. data/CHANGELOG.ja.rdoc +25 -4
  2. data/CHANGELOG.rdoc +20 -0
  3. data/Manifest.txt +2 -0
  4. data/Rakefile +20 -21
  5. data/ext/nokogiri/extconf.rb +8 -1
  6. data/ext/nokogiri/html_document.c +0 -2
  7. data/ext/nokogiri/nokogiri.c +2 -0
  8. data/ext/nokogiri/nokogiri.h +3 -4
  9. data/ext/nokogiri/xml_document.c +30 -23
  10. data/ext/nokogiri/xml_document.h +3 -2
  11. data/ext/nokogiri/xml_dtd.c +4 -0
  12. data/ext/nokogiri/xml_dtd.h +2 -0
  13. data/ext/nokogiri/xml_node.c +28 -9
  14. data/ext/nokogiri/xml_reader.c +0 -7
  15. data/ext/nokogiri/xml_relax_ng.c +7 -1
  16. data/ext/nokogiri/xml_sax_parser.c +2 -0
  17. data/lib/action-nokogiri.rb +2 -0
  18. data/lib/nokogiri.rb +9 -3
  19. data/lib/nokogiri/css/generated_tokenizer.rb +80 -82
  20. data/lib/nokogiri/css/tokenizer.rb +1 -5
  21. data/lib/nokogiri/decorators/hpricot/node_set.rb +1 -1
  22. data/lib/nokogiri/ffi/structs/common_node.rb +1 -1
  23. data/lib/nokogiri/ffi/structs/xml_document.rb +1 -1
  24. data/lib/nokogiri/ffi/xml/document.rb +15 -4
  25. data/lib/nokogiri/ffi/xml/node.rb +85 -63
  26. data/lib/nokogiri/ffi/xml/reader.rb +4 -15
  27. data/lib/nokogiri/ffi/xml/relax_ng.rb +3 -1
  28. data/lib/nokogiri/hpricot.rb +30 -0
  29. data/lib/nokogiri/html/document.rb +3 -1
  30. data/lib/nokogiri/html/document_fragment.rb +1 -1
  31. data/lib/nokogiri/html/sax/parser.rb +2 -1
  32. data/lib/nokogiri/version.rb +1 -1
  33. data/lib/nokogiri/xml/builder.rb +44 -1
  34. data/lib/nokogiri/xml/document.rb +8 -1
  35. data/lib/nokogiri/xml/document_fragment.rb +1 -1
  36. data/lib/nokogiri/xml/fragment_handler.rb +4 -7
  37. data/lib/nokogiri/xml/node.rb +9 -6
  38. data/lib/nokogiri/xml/node_set.rb +7 -0
  39. data/lib/nokogiri/xml/parse_options.rb +1 -1
  40. data/test/css/test_nthiness.rb +2 -3
  41. data/test/ffi/test_document.rb +6 -6
  42. data/test/files/2ch.html +108 -0
  43. data/test/files/shift_jis.xml +5 -0
  44. data/test/helper.rb +3 -0
  45. data/test/hpricot/test_alter.rb +9 -9
  46. data/test/hpricot/test_builder.rb +2 -2
  47. data/test/hpricot/test_parser.rb +70 -146
  48. data/test/hpricot/test_paths.rb +2 -2
  49. data/test/hpricot/test_preserved.rb +2 -2
  50. data/test/hpricot/test_xml.rb +3 -3
  51. data/test/html/sax/test_parser.rb +12 -0
  52. data/test/html/test_builder.rb +6 -4
  53. data/test/html/test_document.rb +7 -0
  54. data/test/html/test_document_encoding.rb +17 -0
  55. data/test/html/test_document_fragment.rb +12 -0
  56. data/test/html/test_node.rb +5 -2
  57. data/test/test_convert_xpath.rb +1 -50
  58. data/test/test_css_cache.rb +1 -12
  59. data/test/test_nokogiri.rb +7 -0
  60. data/test/test_reader.rb +14 -0
  61. data/test/xml/test_document.rb +44 -0
  62. data/test/xml/test_document_fragment.rb +12 -0
  63. data/test/xml/test_node.rb +10 -2
  64. data/test/xml/test_node_encoding.rb +23 -0
  65. data/test/xml/test_node_set.rb +10 -0
  66. metadata +5 -3
@@ -163,13 +163,6 @@ static VALUE attribute_nodes(VALUE self)
163
163
  xmlNodePtr ptr = xmlTextReaderExpand(reader);
164
164
  if(ptr == NULL) return Qnil;
165
165
 
166
- // FIXME I'm not sure if this is correct..... I don't really like pointing
167
- // at this document, but I have to because of the assertions in
168
- // the node wrapping code.
169
- if(! DOC_RUBY_OBJECT_TEST(ptr->doc)) {
170
- VALUE rb_doc = Nokogiri_wrap_xml_document(cNokogiriXmlDocument, ptr->doc);
171
- RDATA(rb_doc)->dfree = NULL;
172
- }
173
166
  VALUE enc = rb_iv_get(self, "@encoding");
174
167
 
175
168
  if(enc != Qnil && NULL == ptr->doc->encoding) {
@@ -120,7 +120,9 @@ static VALUE from_document(VALUE klass, VALUE document)
120
120
  xmlRelaxNGPtr schema = xmlRelaxNGParse(ctx);
121
121
 
122
122
  xmlSetStructuredErrorFunc(NULL, NULL);
123
- xmlRelaxNGFreeParserCtxt(ctx);
123
+ if (! is_2_6_16()) {
124
+ xmlRelaxNGFreeParserCtxt(ctx);
125
+ }
124
126
 
125
127
  if(NULL == schema) {
126
128
  xmlErrorPtr error = xmlGetLastError();
@@ -132,6 +134,10 @@ static VALUE from_document(VALUE klass, VALUE document)
132
134
  return Qnil;
133
135
  }
134
136
 
137
+ if (is_2_6_16()) {
138
+ xmlRelaxNGFreeParserCtxt(ctx);
139
+ }
140
+
135
141
  VALUE rb_schema = Data_Wrap_Struct(klass, 0, dealloc, schema);
136
142
  rb_iv_set(rb_schema, "@errors", errors);
137
143
 
@@ -310,6 +310,8 @@ static VALUE allocate(VALUE klass)
310
310
  {
311
311
  xmlSAXHandlerPtr handler = calloc(1, sizeof(xmlSAXHandler));
312
312
 
313
+ xmlSetStructuredErrorFunc(NULL, NULL);
314
+
313
315
  handler->startDocument = start_document;
314
316
  handler->endDocument = end_document;
315
317
  handler->startElement = start_element;
@@ -18,6 +18,7 @@ module ActionController
18
18
  # Get your response as a Nokogiri::XML::Document using the
19
19
  # Nokogiri.HTML parser
20
20
  def html(flavor=nil)
21
+ warn "@response.html is deprecated and will be removed in nokogiri 1.4.0"
21
22
  if flavor == :hpricot
22
23
  @_nokogiri_html_hpricot ||= Nokogiri::Hpricot(body)
23
24
  else
@@ -29,6 +30,7 @@ module ActionController
29
30
  # Get your response as a Nokogiri::XML::Document using the
30
31
  # Nokogiri.XML parser
31
32
  def xml
33
+ warn "@response.html is deprecated and will be removed in nokogiri 1.4.0"
32
34
  @_nokogiri_xml ||= Nokogiri::XML(body)
33
35
  end
34
36
 
@@ -54,10 +54,16 @@ module Nokogiri
54
54
  # Parse an HTML or XML document. +string+ contains the document.
55
55
  def parse string, url = nil, encoding = nil, options = nil
56
56
  doc =
57
- if string =~ /^\s*<[^Hh>]*html/i # Probably html
58
- Nokogiri::HTML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_HTML)
57
+ if string.respond_to?(:read) ||
58
+ string =~ /^\s*<[^Hh>]*html/i # Probably html
59
+ Nokogiri::HTML(
60
+ string,
61
+ url,
62
+ encoding, options || XML::ParseOptions::DEFAULT_HTML
63
+ )
59
64
  else
60
- Nokogiri::XML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_XML)
65
+ Nokogiri::XML(string, url, encoding,
66
+ options || XML::ParseOptions::DEFAULT_XML)
61
67
  end
62
68
  yield doc if block_given?
63
69
  doc
@@ -1,6 +1,6 @@
1
1
  #--
2
2
  # DO NOT MODIFY!!!!
3
- # This file is automatically generated by rex 1.0.3
3
+ # This file is automatically generated by rex 1.0.4
4
4
  # from lexical definition file "lib/nokogiri/css/tokenizer.rex".
5
5
  #++
6
6
 
@@ -11,133 +11,131 @@ class GeneratedTokenizer < GeneratedParser
11
11
 
12
12
  class ScanError < StandardError ; end
13
13
 
14
- attr_reader :lineno
15
- attr_reader :filename
14
+ attr_reader :lineno
15
+ attr_reader :filename
16
+ attr_accessor :state
16
17
 
17
- def scan_setup ; end
18
+ def scan_setup(str)
19
+ @ss = StringScanner.new(str)
20
+ @lineno = 1
21
+ @state = nil
22
+ end
18
23
 
19
- def action &block
24
+ def action(&block)
20
25
  yield
21
26
  end
22
27
 
23
- def scan_str( str )
24
- scan_evaluate str
28
+ def scan_str(str)
29
+ scan_setup(str)
25
30
  do_parse
26
31
  end
27
32
 
28
33
  def load_file( filename )
29
34
  @filename = filename
30
35
  open(filename, "r") do |f|
31
- scan_evaluate f.read
36
+ scan_setup(f.read)
32
37
  end
33
38
  end
34
39
 
35
40
  def scan_file( filename )
36
- load_file filename
41
+ load_file(filename)
37
42
  do_parse
38
43
  end
39
44
 
40
- def next_token
41
- @rex_tokens.shift
42
- end
43
45
 
44
- def scan_evaluate( str )
45
- scan_setup
46
- @rex_tokens = []
47
- @lineno = 1
48
- ss = StringScanner.new(str)
49
- state = nil
50
- until ss.eos?
51
- text = ss.peek(1)
52
- @lineno += 1 if text == "\n"
53
- case state
54
- when nil
55
- case
56
- when (text = ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*\(\s*/))
57
- @rex_tokens.push action { [:FUNCTION, text] }
46
+ def next_token
47
+ return if @ss.eos?
58
48
 
59
- when (text = ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*/))
60
- @rex_tokens.push action { [:IDENT, text] }
49
+ text = @ss.peek(1)
50
+ @lineno += 1 if text == "\n"
51
+ token = case @state
52
+ when nil
53
+ case
54
+ when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*\(\s*/))
55
+ action { [:FUNCTION, text] }
61
56
 
62
- when (text = ss.scan(/\#([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])+/))
63
- @rex_tokens.push action { [:HASH, text] }
57
+ when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*/))
58
+ action { [:IDENT, text] }
64
59
 
65
- when (text = ss.scan(/[\s\r\n\f]*~=[\s\r\n\f]*/))
66
- @rex_tokens.push action { [:INCLUDES, text] }
60
+ when (text = @ss.scan(/\#([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])+/))
61
+ action { [:HASH, text] }
67
62
 
68
- when (text = ss.scan(/[\s\r\n\f]*\|=[\s\r\n\f]*/))
69
- @rex_tokens.push action { [:DASHMATCH, text] }
63
+ when (text = @ss.scan(/[\s\r\n\f]*~=[\s\r\n\f]*/))
64
+ action { [:INCLUDES, text] }
70
65
 
71
- when (text = ss.scan(/[\s\r\n\f]*\^=[\s\r\n\f]*/))
72
- @rex_tokens.push action { [:PREFIXMATCH, text] }
66
+ when (text = @ss.scan(/[\s\r\n\f]*\|=[\s\r\n\f]*/))
67
+ action { [:DASHMATCH, text] }
73
68
 
74
- when (text = ss.scan(/[\s\r\n\f]*\$=[\s\r\n\f]*/))
75
- @rex_tokens.push action { [:SUFFIXMATCH, text] }
69
+ when (text = @ss.scan(/[\s\r\n\f]*\^=[\s\r\n\f]*/))
70
+ action { [:PREFIXMATCH, text] }
76
71
 
77
- when (text = ss.scan(/[\s\r\n\f]*\*=[\s\r\n\f]*/))
78
- @rex_tokens.push action { [:SUBSTRINGMATCH, text] }
72
+ when (text = @ss.scan(/[\s\r\n\f]*\$=[\s\r\n\f]*/))
73
+ action { [:SUFFIXMATCH, text] }
79
74
 
80
- when (text = ss.scan(/[\s\r\n\f]*!=[\s\r\n\f]*/))
81
- @rex_tokens.push action { [:NOT_EQUAL, text] }
75
+ when (text = @ss.scan(/[\s\r\n\f]*\*=[\s\r\n\f]*/))
76
+ action { [:SUBSTRINGMATCH, text] }
82
77
 
83
- when (text = ss.scan(/[\s\r\n\f]*=[\s\r\n\f]*/))
84
- @rex_tokens.push action { [:EQUAL, text] }
78
+ when (text = @ss.scan(/[\s\r\n\f]*!=[\s\r\n\f]*/))
79
+ action { [:NOT_EQUAL, text] }
85
80
 
86
- when (text = ss.scan(/[\s\r\n\f]*\)/))
87
- @rex_tokens.push action { [:RPAREN, text] }
81
+ when (text = @ss.scan(/[\s\r\n\f]*=[\s\r\n\f]*/))
82
+ action { [:EQUAL, text] }
88
83
 
89
- when (text = ss.scan(/[\s\r\n\f]*\[[\s\r\n\f]*/))
90
- @rex_tokens.push action { [:LSQUARE, text] }
84
+ when (text = @ss.scan(/[\s\r\n\f]*\)/))
85
+ action { [:RPAREN, text] }
91
86
 
92
- when (text = ss.scan(/[\s\r\n\f]*\]/))
93
- @rex_tokens.push action { [:RSQUARE, text] }
87
+ when (text = @ss.scan(/[\s\r\n\f]*\[[\s\r\n\f]*/))
88
+ action { [:LSQUARE, text] }
94
89
 
95
- when (text = ss.scan(/[\s\r\n\f]*\+[\s\r\n\f]*/))
96
- @rex_tokens.push action { [:PLUS, text] }
90
+ when (text = @ss.scan(/[\s\r\n\f]*\]/))
91
+ action { [:RSQUARE, text] }
97
92
 
98
- when (text = ss.scan(/[\s\r\n\f]*>[\s\r\n\f]*/))
99
- @rex_tokens.push action { [:GREATER, text] }
93
+ when (text = @ss.scan(/[\s\r\n\f]*\+[\s\r\n\f]*/))
94
+ action { [:PLUS, text] }
100
95
 
101
- when (text = ss.scan(/[\s\r\n\f]*,[\s\r\n\f]*/))
102
- @rex_tokens.push action { [:COMMA, text] }
96
+ when (text = @ss.scan(/[\s\r\n\f]*>[\s\r\n\f]*/))
97
+ action { [:GREATER, text] }
103
98
 
104
- when (text = ss.scan(/[\s\r\n\f]*~[\s\r\n\f]*/))
105
- @rex_tokens.push action { [:TILDE, text] }
99
+ when (text = @ss.scan(/[\s\r\n\f]*,[\s\r\n\f]*/))
100
+ action { [:COMMA, text] }
106
101
 
107
- when (text = ss.scan(/\:not\([\s\r\n\f]*/))
108
- @rex_tokens.push action { [:NOT, text] }
102
+ when (text = @ss.scan(/[\s\r\n\f]*~[\s\r\n\f]*/))
103
+ action { [:TILDE, text] }
109
104
 
110
- when (text = ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)/))
111
- @rex_tokens.push action { [:NUMBER, text] }
105
+ when (text = @ss.scan(/\:not\([\s\r\n\f]*/))
106
+ action { [:NOT, text] }
112
107
 
113
- when (text = ss.scan(/[\s\r\n\f]*\/\/[\s\r\n\f]*/))
114
- @rex_tokens.push action { [:DOUBLESLASH, text] }
108
+ when (text = @ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)/))
109
+ action { [:NUMBER, text] }
115
110
 
116
- when (text = ss.scan(/[\s\r\n\f]*\/[\s\r\n\f]*/))
117
- @rex_tokens.push action { [:SLASH, text] }
111
+ when (text = @ss.scan(/[\s\r\n\f]*\/\/[\s\r\n\f]*/))
112
+ action { [:DOUBLESLASH, text] }
118
113
 
119
- when (text = ss.scan(/U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?/))
120
- @rex_tokens.push action {[:UNICODE_RANGE, text] }
114
+ when (text = @ss.scan(/[\s\r\n\f]*\/[\s\r\n\f]*/))
115
+ action { [:SLASH, text] }
121
116
 
122
- when (text = ss.scan(/[\s\t\r\n\f]+/))
123
- @rex_tokens.push action { [:S, text] }
117
+ when (text = @ss.scan(/U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?/))
118
+ action {[:UNICODE_RANGE, text] }
124
119
 
125
- when (text = ss.scan(/"([^\n\r\f"]|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*"|'([^\n\r\f']|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*'/))
126
- @rex_tokens.push action { [:STRING, text] }
120
+ when (text = @ss.scan(/[\s\t\r\n\f]+/))
121
+ action { [:S, text] }
127
122
 
128
- when (text = ss.scan(/./))
129
- @rex_tokens.push action { [text, text] }
123
+ when (text = @ss.scan(/"([^\n\r\f"]|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*"|'([^\n\r\f']|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*'/))
124
+ action { [:STRING, text] }
130
125
 
131
- else
132
- text = ss.string[ss.pos .. -1]
133
- raise ScanError, "can not match: '" + text + "'"
134
- end # if
126
+ when (text = @ss.scan(/./))
127
+ action { [text, text] }
135
128
 
136
129
  else
137
- raise ScanError, "undefined state: '" + state.to_s + "'"
138
- end # case state
139
- end # until ss
140
- end # def scan_evaluate
130
+ text = @ss.string[@ss.pos .. -1]
131
+ raise ScanError, "can not match: '" + text + "'"
132
+ end # if
133
+
134
+ else
135
+ raise ScanError, "undefined state: '" + state.to_s + "'"
136
+ end # case state
137
+ token
138
+ end # def next_token
141
139
 
142
140
  end # class
143
141
  end
@@ -1,11 +1,7 @@
1
1
  module Nokogiri
2
2
  module CSS
3
3
  class Tokenizer < GeneratedTokenizer
4
- ###
5
- # Scan and tokenize +str+
6
- def scan(str)
7
- scan_evaluate(str)
8
- end
4
+ alias :scan :scan_setup
9
5
  end
10
6
  end
11
7
  end
@@ -47,7 +47,7 @@ module Nokogiri
47
47
  end
48
48
  end
49
49
  sub_set
50
- end
50
+ end
51
51
  end
52
52
  end
53
53
  end
@@ -18,7 +18,7 @@ module Nokogiri
18
18
  def keep_reference_from_document! # equivalent to NOKOGIRI_ROOT_NODE
19
19
  doc = self.document
20
20
  raise "no document to add reference to" unless doc
21
- LibXML.xmlXPathNodeSetAdd(doc.node_set, self)
21
+ LibXML.xmlXPathNodeSetAdd(doc.unlinked_nodes, self)
22
22
  end
23
23
  end
24
24
  end
@@ -46,7 +46,7 @@ module Nokogiri
46
46
  self[:_private].put_long(0, object.object_id)
47
47
  end
48
48
 
49
- def node_set
49
+ def unlinked_nodes
50
50
  LibXML::XmlNodeSetCast.new(self[:_private].get_pointer(FFI.type_size(:pointer)))
51
51
  end
52
52
 
@@ -8,9 +8,19 @@ module Nokogiri
8
8
  cstruct[:URL]
9
9
  end
10
10
 
11
- def root=(node) # :nodoc:
12
- LibXML.xmlDocSetRootElement(cstruct, node.cstruct)
13
- node
11
+ def root=(new_root) # :nodoc:
12
+ old_root = nil
13
+ if new_root.cstruct[:doc] != cstruct[:doc]
14
+ old_root_ptr = LibXML.xmlDocGetRootElement(cstruct)
15
+ new_root_ptr = LibXML.xmlDocCopyNode(new_root.cstruct, cstruct, 1)
16
+ raise RuntimeError "Could not reparent node (xmlDocCopyNode)" if new_root_ptr.null?
17
+ new_root = Node.wrap(new_root_ptr)
18
+ end
19
+ LibXML.xmlDocSetRootElement(cstruct, new_root.cstruct)
20
+ if old_root_ptr && ! old_root_ptr.null?
21
+ LibXML::XmlNode.new(old_root_ptr).keep_reference_from_document!
22
+ end
23
+ new_root
14
24
  end
15
25
 
16
26
  def root # :nodoc:
@@ -24,7 +34,8 @@ module Nokogiri
24
34
  end
25
35
 
26
36
  def encoding # :nodoc:
27
- cstruct[:encoding].read_string
37
+ ptr = cstruct[:encoding]
38
+ ptr.null? ? nil : ptr.read_string
28
39
  end
29
40
 
30
41
  def self.read_io(io, url, encoding, options) # :nodoc:
@@ -1,14 +1,15 @@
1
1
  module Nokogiri
2
2
  module XML
3
3
  class Node
4
+ # :stopdoc:
4
5
 
5
- attr_accessor :cstruct # :nodoc:
6
+ attr_accessor :cstruct
6
7
 
7
- def pointer_id # :nodoc:
8
+ def pointer_id
8
9
  cstruct.pointer
9
10
  end
10
11
 
11
- def encode_special_chars(string) # :nodoc:
12
+ def encode_special_chars(string)
12
13
  char_ptr = LibXML.xmlEncodeSpecialChars(self[:doc], string)
13
14
  encoded = char_ptr.read_string
14
15
  # TODO: encoding?
@@ -16,7 +17,7 @@ module Nokogiri
16
17
  encoded
17
18
  end
18
19
 
19
- def internal_subset # :nodoc:
20
+ def internal_subset
20
21
  return nil if cstruct[:doc].null?
21
22
  doc = cstruct.document
22
23
  dtd = LibXML.xmlGetIntSubset(doc)
@@ -24,37 +25,37 @@ module Nokogiri
24
25
  Node.wrap(dtd)
25
26
  end
26
27
 
27
- def dup(deep = 1) # :nodoc:
28
+ def dup(deep = 1)
28
29
  dup_ptr = LibXML.xmlDocCopyNode(cstruct, cstruct.document, deep)
29
30
  return nil if dup_ptr.null?
30
31
  Node.wrap(dup_ptr, self.class)
31
32
  end
32
33
 
33
- def unlink # :nodoc:
34
+ def unlink
34
35
  LibXML.xmlUnlinkNode(cstruct)
35
36
  cstruct.keep_reference_from_document!
36
37
  self
37
38
  end
38
39
 
39
- def blank? # :nodoc:
40
+ def blank?
40
41
  LibXML.xmlIsBlankNode(cstruct) == 1
41
42
  end
42
43
 
43
- def next_sibling # :nodoc:
44
+ def next_sibling
44
45
  cstruct_node_from :next
45
46
  end
46
47
 
47
- def previous_sibling # :nodoc:
48
+ def previous_sibling
48
49
  cstruct_node_from :prev
49
50
  end
50
51
 
51
- def replace_with_node(new_node) # :nodoc:
52
+ def replace_with_node(new_node)
52
53
  LibXML.xmlReplaceNode(cstruct, new_node.cstruct)
53
54
  Node.send(:relink_namespace, new_node.cstruct)
54
55
  self
55
56
  end
56
57
 
57
- def children # :nodoc:
58
+ def children
58
59
  return NodeSet.new(nil) if cstruct[:children].null?
59
60
  child = Node.wrap(cstruct[:children])
60
61
 
@@ -74,26 +75,26 @@ module Nokogiri
74
75
  return set
75
76
  end
76
77
 
77
- def child # :nodoc:
78
+ def child
78
79
  (val = cstruct[:children]).null? ? nil : Node.wrap(val)
79
80
  end
80
81
 
81
- def key?(attribute) # :nodoc:
82
+ def key?(attribute)
82
83
  ! (prop = LibXML.xmlHasProp(cstruct, attribute.to_s)).null?
83
84
  end
84
85
 
85
- def namespaced_key?(attribute, namespace) # :nodoc:
86
+ def namespaced_key?(attribute, namespace)
86
87
  prop = LibXML.xmlHasNsProp(cstruct, attribute.to_s,
87
88
  namespace.nil? ? nil : namespace.to_s)
88
89
  prop.null? ? false : true
89
90
  end
90
91
 
91
- def []=(property, value) # :nodoc:
92
+ def []=(property, value)
92
93
  LibXML.xmlSetProp(cstruct, property, value)
93
94
  value
94
95
  end
95
96
 
96
- def get(attribute) # :nodoc:
97
+ def get(attribute)
97
98
  return nil unless attribute
98
99
  propstr = LibXML.xmlGetProp(cstruct, attribute.to_s)
99
100
  return nil if propstr.null?
@@ -107,33 +108,26 @@ module Nokogiri
107
108
  self
108
109
  end
109
110
 
110
- def attribute(name) # :nodoc:
111
+ def attribute(name)
111
112
  raise "Node#attribute not implemented yet"
112
113
  end
113
114
 
114
- def attribute_with_ns(name, namespace) # :nodoc:
115
+ def attribute_with_ns(name, namespace)
115
116
  prop = LibXML.xmlHasNsProp(cstruct, name.to_s,
116
117
  namespace.nil? ? NULL : namespace.to_s)
117
118
  return prop if prop.null?
118
119
  Node.wrap(prop)
119
120
  end
120
121
 
121
- def attribute_nodes # :nodoc:
122
- attr = []
123
- prop_cstruct = cstruct[:properties]
124
- while ! prop_cstruct.null?
125
- prop = Node.wrap(prop_cstruct)
126
- attr << prop
127
- prop_cstruct = prop.cstruct[:next]
128
- end
129
- attr
122
+ def attribute_nodes
123
+ Node.node_properties cstruct
130
124
  end
131
125
 
132
- def namespace # :nodoc:
126
+ def namespace
133
127
  cstruct[:ns].null? ? nil : Namespace.wrap(cstruct.document, cstruct[:ns])
134
128
  end
135
129
 
136
- def namespace_definitions # :nodoc:
130
+ def namespace_definitions
137
131
  list = []
138
132
  ns_ptr = cstruct[:nsDef]
139
133
  return list if ns_ptr.null?
@@ -145,16 +139,16 @@ module Nokogiri
145
139
  list
146
140
  end
147
141
 
148
- def node_type # :nodoc:
142
+ def node_type
149
143
  cstruct[:type]
150
144
  end
151
145
 
152
- def native_content=(content) # :nodoc:
146
+ def native_content=(content)
153
147
  LibXML.xmlNodeSetContent(cstruct, content)
154
148
  content
155
149
  end
156
150
 
157
- def content # :nodoc:
151
+ def content
158
152
  content_ptr = LibXML.xmlNodeGetContent(cstruct)
159
153
  return nil if content_ptr.null?
160
154
  content = content_ptr.read_string # TODO: encoding?
@@ -162,45 +156,45 @@ module Nokogiri
162
156
  content
163
157
  end
164
158
 
165
- def add_child(child) # :nodoc:
159
+ def add_child(child)
166
160
  Node.reparent_node_with(child, self) do |child_cstruct, my_cstruct|
167
161
  LibXML.xmlAddChild(my_cstruct, child_cstruct)
168
162
  end
169
163
  end
170
164
 
171
- def parent # :nodoc:
165
+ def parent
172
166
  cstruct_node_from :parent
173
167
  end
174
-
175
- def node_name=(string) # :nodoc:
168
+
169
+ def node_name=(string)
176
170
  LibXML.xmlNodeSetName(cstruct, string)
177
171
  string
178
172
  end
179
173
 
180
- def node_name # :nodoc:
174
+ def node_name
181
175
  cstruct[:name] # TODO: encoding?
182
176
  end
183
177
 
184
- def path # :nodoc:
178
+ def path
185
179
  path_ptr = LibXML.xmlGetNodePath(cstruct)
186
180
  val = path_ptr.null? ? nil : path_ptr.read_string # TODO: encoding?
187
181
  LibXML.xmlFree(path_ptr)
188
182
  val
189
183
  end
190
184
 
191
- def add_next_sibling(next_sibling) # :nodoc:
185
+ def add_next_sibling(next_sibling)
192
186
  Node.reparent_node_with(next_sibling, self) do |sibling_cstruct, my_cstruct|
193
187
  LibXML.xmlAddNextSibling(my_cstruct, sibling_cstruct)
194
188
  end
195
189
  end
196
190
 
197
- def add_previous_sibling(prev_sibling) # :nodoc:
191
+ def add_previous_sibling(prev_sibling)
198
192
  Node.reparent_node_with(prev_sibling, self) do |sibling_cstruct, my_cstruct|
199
193
  LibXML.xmlAddPrevSibling(my_cstruct, sibling_cstruct)
200
194
  end
201
195
  end
202
196
 
203
- def native_write_to(io, encoding, indent_string, options) # :nodoc:
197
+ def native_write_to(io, encoding, indent_string, options)
204
198
  set_xml_indent_tree_output 1
205
199
  set_xml_tree_indent_string indent_string
206
200
  savectx = LibXML.xmlSaveToIO(IoCallbacks.writer(io), nil, nil, encoding, options)
@@ -209,11 +203,11 @@ module Nokogiri
209
203
  io
210
204
  end
211
205
 
212
- def line # :nodoc:
206
+ def line
213
207
  cstruct[:line]
214
208
  end
215
209
 
216
- def add_namespace_definition(prefix, href) # :nodoc:
210
+ def add_namespace_definition(prefix, href)
217
211
  ns = LibXML.xmlNewNs(cstruct, href, prefix)
218
212
  if ns.null?
219
213
  ns = LibXML.xmlSearchNs(cstruct.document, cstruct,
@@ -223,43 +217,46 @@ module Nokogiri
223
217
  Namespace.wrap(cstruct.document, ns)
224
218
  end
225
219
 
226
- def self.new(name, document, *rest) # :nodoc:
220
+ def self.new(name, doc, *rest)
227
221
  ptr = LibXML.xmlNewNode(nil, name.to_s)
228
222
 
229
223
  node_cstruct = LibXML::XmlNode.new(ptr)
230
- node_cstruct[:doc] = document.cstruct[:doc]
224
+ node_cstruct[:doc] = doc.cstruct[:doc]
231
225
  node_cstruct.keep_reference_from_document!
232
226
 
233
- node = Node.wrap(node_cstruct, self)
234
- node.send :initialize, name, document, *rest
227
+ node = Node.wrap(
228
+ node_cstruct,
229
+ Node == self ? nil : self
230
+ )
231
+ node.send :initialize, name, doc, *rest
235
232
  yield node if block_given?
236
233
  node
237
234
  end
238
235
 
239
- def dump_html # :nodoc:
236
+ def dump_html
240
237
  return to_xml if type == DOCUMENT_NODE
241
238
  buffer = LibXML::XmlBuffer.new(LibXML.xmlBufferCreate())
242
239
  LibXML.htmlNodeDump(buffer, cstruct[:doc], cstruct)
243
240
  buffer[:content] # TODO: encoding?
244
241
  end
245
242
 
246
- def compare(other) # :nodoc:
243
+ def compare(other)
247
244
  LibXML.xmlXPathCmpNodes(other.cstruct, self.cstruct)
248
245
  end
249
246
 
250
- def self.wrap(node_struct, klass=nil) # :nodoc:
247
+ def self.wrap(node_struct, klass=nil)
251
248
  if node_struct.is_a?(FFI::Pointer)
252
249
  # cast native pointers up into a node cstruct
253
250
  return nil if node_struct.null?
254
- node_struct = LibXML::XmlNode.new(node_struct)
251
+ node_struct = LibXML::XmlNode.new(node_struct)
255
252
  end
256
253
 
257
254
  raise "wrapping a node without a document" unless node_struct.document
258
255
 
259
256
  document_struct = node_struct.document
260
- document = document_struct.nil? ? nil : document_struct.ruby_doc
257
+ document_obj = document_struct.nil? ? nil : document_struct.ruby_doc
261
258
  if node_struct[:type] == DOCUMENT_NODE || node_struct[:type] == HTML_DOCUMENT_NODE
262
- return document
259
+ return document_obj
263
260
  end
264
261
 
265
262
  ruby_node = node_struct.ruby_node
@@ -288,11 +285,13 @@ module Nokogiri
288
285
 
289
286
  node.cstruct.ruby_node = node
290
287
 
291
- cache = document.instance_variable_get(:@node_cache)
292
- cache << node
288
+ if document_obj
289
+ node.instance_variable_set(:@document, document_obj)
290
+ cache = document_obj.instance_variable_get(:@node_cache)
291
+ cache << node
292
+ document_obj.decorate(node)
293
+ end
293
294
 
294
- node.instance_variable_set(:@document, document)
295
- document.decorate(node)
296
295
  node
297
296
  end
298
297
 
@@ -300,11 +299,33 @@ module Nokogiri
300
299
  cstruct.document.ruby_doc
301
300
  end
302
301
 
302
+ class << self
303
+ def node_properties(cstruct)
304
+ attr = []
305
+ prop_cstruct = cstruct[:properties]
306
+ while ! prop_cstruct.null?
307
+ prop = Node.wrap(prop_cstruct)
308
+ attr << prop
309
+ prop_cstruct = prop.cstruct[:next]
310
+ end
311
+ attr
312
+ end
313
+ end
314
+
303
315
  private
304
316
 
305
- def self.reparent_node_with(node, other, &block) # :nodoc:
317
+ def self.reparent_node_with(node, other, &block)
306
318
  raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(Nokogiri::XML::Node)
307
319
 
320
+ # If a document fragment is added, we need to reparent all of it's
321
+ # children
322
+ if node.type == DOCUMENT_FRAG_NODE
323
+ node.children.each do |child|
324
+ reparent_node_with(child, other, &block)
325
+ end
326
+ return node
327
+ end
328
+
308
329
  if node.cstruct[:doc] == other.cstruct[:doc]
309
330
  LibXML.xmlUnlinkNode(node.cstruct)
310
331
  if node.type == TEXT_NODE && other.type == TEXT_NODE && Nokogiri.is_2_6_16?
@@ -320,7 +341,7 @@ module Nokogiri
320
341
  LibXML.xmlUnlinkNode(node.cstruct)
321
342
  node.cstruct.keep_reference_from_document!
322
343
  end
323
-
344
+
324
345
  reparented_struct = LibXML::XmlNode.new(reparented_struct)
325
346
 
326
347
  # the child was a text node that was coalesced. we need to have the object
@@ -336,7 +357,7 @@ module Nokogiri
336
357
  reparented
337
358
  end
338
359
 
339
- def self.relink_namespace(reparented_struct) # :nodoc:
360
+ def self.relink_namespace(reparented_struct)
340
361
  # Make sure that our reparented node has the correct namespaces
341
362
  if reparented_struct[:doc] != reparented_struct[:parent]
342
363
  LibXML.xmlSetNs(reparented_struct, LibXML::XmlNode.new(reparented_struct[:parent])[:ns])
@@ -365,18 +386,19 @@ module Nokogiri
365
386
  end
366
387
  end
367
388
 
368
- def cstruct_node_from(sym) # :nodoc:
389
+ def cstruct_node_from(sym)
369
390
  (val = cstruct[sym]).null? ? nil : Node.wrap(val)
370
391
  end
371
392
 
372
- def set_xml_indent_tree_output(value) # :nodoc:
393
+ def set_xml_indent_tree_output(value)
373
394
  LibXML.__xmlIndentTreeOutput.write_int(value)
374
395
  end
375
396
 
376
- def set_xml_tree_indent_string(value) # :nodoc:
397
+ def set_xml_tree_indent_string(value)
377
398
  LibXML.__xmlTreeIndentString.write_pointer(LibXML.xmlStrdup(value.to_s))
378
399
  end
379
400
 
401
+ # :startdoc:
380
402
  end
381
403
  end
382
404
  end