nokogiri 1.4.1 → 1.4.2

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 (107) hide show
  1. data/CHANGELOG.ja.rdoc +45 -0
  2. data/CHANGELOG.rdoc +53 -1
  3. data/Manifest.txt +3 -3
  4. data/README.ja.rdoc +1 -1
  5. data/README.rdoc +11 -5
  6. data/Rakefile +13 -79
  7. data/ext/nokogiri/extconf.rb +22 -74
  8. data/ext/nokogiri/html_document.c +17 -8
  9. data/ext/nokogiri/html_element_description.c +20 -16
  10. data/ext/nokogiri/html_entity_lookup.c +2 -2
  11. data/ext/nokogiri/html_sax_parser_context.c +10 -8
  12. data/ext/nokogiri/nokogiri.c +0 -1
  13. data/ext/nokogiri/nokogiri.h +33 -28
  14. data/ext/nokogiri/xml_attr.c +7 -5
  15. data/ext/nokogiri/xml_attribute_decl.c +5 -2
  16. data/ext/nokogiri/xml_cdata.c +4 -2
  17. data/ext/nokogiri/xml_comment.c +4 -2
  18. data/ext/nokogiri/xml_document.c +93 -15
  19. data/ext/nokogiri/xml_document.h +0 -1
  20. data/ext/nokogiri/xml_document_fragment.c +4 -2
  21. data/ext/nokogiri/xml_dtd.c +18 -8
  22. data/ext/nokogiri/xml_element_content.c +2 -2
  23. data/ext/nokogiri/xml_entity_decl.c +15 -2
  24. data/ext/nokogiri/xml_entity_reference.c +4 -2
  25. data/ext/nokogiri/xml_io.c +1 -1
  26. data/ext/nokogiri/xml_namespace.c +5 -3
  27. data/ext/nokogiri/xml_node.c +353 -114
  28. data/ext/nokogiri/xml_node_set.c +35 -22
  29. data/ext/nokogiri/xml_node_set.h +1 -1
  30. data/ext/nokogiri/xml_processing_instruction.c +4 -2
  31. data/ext/nokogiri/xml_reader.c +119 -47
  32. data/ext/nokogiri/xml_relax_ng.c +21 -12
  33. data/ext/nokogiri/xml_sax_parser.c +6 -3
  34. data/ext/nokogiri/xml_sax_parser.h +13 -17
  35. data/ext/nokogiri/xml_sax_parser_context.c +8 -6
  36. data/ext/nokogiri/xml_sax_push_parser.c +7 -6
  37. data/ext/nokogiri/xml_schema.c +62 -13
  38. data/ext/nokogiri/xml_syntax_error.c +18 -12
  39. data/ext/nokogiri/xml_syntax_error.h +1 -1
  40. data/ext/nokogiri/xml_text.c +4 -2
  41. data/ext/nokogiri/xml_xpath_context.c +60 -23
  42. data/ext/nokogiri/xslt_stylesheet.c +14 -3
  43. data/lib/nokogiri.rb +17 -0
  44. data/lib/nokogiri/css/generated_parser.rb +72 -62
  45. data/lib/nokogiri/css/generated_tokenizer.rb +23 -24
  46. data/lib/nokogiri/css/parser.y +3 -1
  47. data/lib/nokogiri/css/tokenizer.rex +3 -3
  48. data/lib/nokogiri/css/xpath_visitor.rb +8 -3
  49. data/lib/nokogiri/ffi/html/sax/parser_context.rb +3 -3
  50. data/lib/nokogiri/ffi/libxml.rb +16 -2
  51. data/lib/nokogiri/ffi/structs/common_node.rb +15 -3
  52. data/lib/nokogiri/ffi/structs/xml_document.rb +13 -4
  53. data/lib/nokogiri/ffi/structs/xml_xpath_context.rb +3 -2
  54. data/lib/nokogiri/ffi/weak_bucket.rb +40 -0
  55. data/lib/nokogiri/ffi/xml/document.rb +27 -0
  56. data/lib/nokogiri/ffi/xml/entity_decl.rb +9 -0
  57. data/lib/nokogiri/ffi/xml/node.rb +142 -61
  58. data/lib/nokogiri/ffi/xml/node_set.rb +15 -12
  59. data/lib/nokogiri/ffi/xml/reader.rb +5 -0
  60. data/lib/nokogiri/ffi/xml/schema.rb +17 -0
  61. data/lib/nokogiri/ffi/xml/syntax_error.rb +4 -4
  62. data/lib/nokogiri/ffi/xml/xpath.rb +0 -10
  63. data/lib/nokogiri/ffi/xml/xpath_context.rb +22 -9
  64. data/lib/nokogiri/ffi/xslt/stylesheet.rb +3 -0
  65. data/lib/nokogiri/html/document.rb +5 -3
  66. data/lib/nokogiri/html/document_fragment.rb +28 -7
  67. data/lib/nokogiri/version.rb +6 -2
  68. data/lib/nokogiri/version_warning.rb +6 -3
  69. data/lib/nokogiri/xml.rb +1 -1
  70. data/lib/nokogiri/xml/builder.rb +35 -22
  71. data/lib/nokogiri/xml/document.rb +44 -12
  72. data/lib/nokogiri/xml/document_fragment.rb +16 -12
  73. data/lib/nokogiri/xml/entity_decl.rb +4 -0
  74. data/lib/nokogiri/xml/node.rb +152 -95
  75. data/lib/nokogiri/xml/node_set.rb +2 -1
  76. data/lib/nokogiri/xml/sax/push_parser.rb +1 -1
  77. data/lib/nokogiri/xml/schema.rb +1 -5
  78. data/lib/nokogiri/xml/syntax_error.rb +4 -0
  79. data/lib/nokogiri/xml/text.rb +9 -0
  80. data/lib/nokogiri/xml/xpath/syntax_error.rb +3 -0
  81. data/tasks/cross_compile.rb +158 -0
  82. data/tasks/test.rb +0 -6
  83. data/test/css/test_xpath_visitor.rb +9 -0
  84. data/test/helper.rb +49 -11
  85. data/test/html/sax/test_parser.rb +11 -1
  86. data/test/html/test_document.rb +8 -0
  87. data/test/html/test_document_fragment.rb +14 -2
  88. data/test/html/test_element_description.rb +5 -1
  89. data/test/html/test_node.rb +5 -66
  90. data/test/test_reader.rb +28 -0
  91. data/test/test_xslt_transforms.rb +14 -0
  92. data/test/xml/test_builder.rb +43 -0
  93. data/test/xml/test_cdata.rb +12 -0
  94. data/test/xml/test_document.rb +74 -39
  95. data/test/xml/test_document_fragment.rb +36 -0
  96. data/test/xml/test_entity_decl.rb +37 -0
  97. data/test/xml/test_node.rb +192 -65
  98. data/test/xml/test_node_reparenting.rb +253 -236
  99. data/test/xml/test_node_set.rb +67 -0
  100. data/test/xml/test_text.rb +8 -0
  101. data/test/xml/test_xpath.rb +32 -0
  102. metadata +103 -48
  103. data.tar.gz.sig +0 -0
  104. data/ext/nokogiri/xml_xpath.c +0 -53
  105. data/ext/nokogiri/xml_xpath.h +0 -11
  106. data/lib/nokogiri/xml/fragment_handler.rb +0 -79
  107. metadata.gz.sig +0 -0
@@ -29,7 +29,6 @@ class GeneratedTokenizer < GeneratedParser
29
29
  scan_setup(str)
30
30
  do_parse
31
31
  end
32
- alias :scan :scan_str
33
32
 
34
33
  def load_file( filename )
35
34
  @filename = filename
@@ -52,79 +51,79 @@ class GeneratedTokenizer < GeneratedParser
52
51
  token = case @state
53
52
  when nil
54
53
  case
55
- when (text = @ss.scan(/has\([\s\r\n\f]*/))
54
+ when (text = @ss.scan(/has\([\s]*/))
56
55
  action { [:HAS, text] }
57
56
 
58
- 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\r\n\f]*/))
57
+ when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*\([\s]*/))
59
58
  action { [:FUNCTION, text] }
60
59
 
61
- 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
+ when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*/))
62
61
  action { [:IDENT, text] }
63
62
 
64
- 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
+ when (text = @ss.scan(/\#([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])+/))
65
64
  action { [:HASH, text] }
66
65
 
67
- when (text = @ss.scan(/[\s\r\n\f]*~=[\s\r\n\f]*/))
66
+ when (text = @ss.scan(/[\s]*~=[\s]*/))
68
67
  action { [:INCLUDES, text] }
69
68
 
70
- when (text = @ss.scan(/[\s\r\n\f]*\|=[\s\r\n\f]*/))
69
+ when (text = @ss.scan(/[\s]*\|=[\s]*/))
71
70
  action { [:DASHMATCH, text] }
72
71
 
73
- when (text = @ss.scan(/[\s\r\n\f]*\^=[\s\r\n\f]*/))
72
+ when (text = @ss.scan(/[\s]*\^=[\s]*/))
74
73
  action { [:PREFIXMATCH, text] }
75
74
 
76
- when (text = @ss.scan(/[\s\r\n\f]*\$=[\s\r\n\f]*/))
75
+ when (text = @ss.scan(/[\s]*\$=[\s]*/))
77
76
  action { [:SUFFIXMATCH, text] }
78
77
 
79
- when (text = @ss.scan(/[\s\r\n\f]*\*=[\s\r\n\f]*/))
78
+ when (text = @ss.scan(/[\s]*\*=[\s]*/))
80
79
  action { [:SUBSTRINGMATCH, text] }
81
80
 
82
- when (text = @ss.scan(/[\s\r\n\f]*!=[\s\r\n\f]*/))
81
+ when (text = @ss.scan(/[\s]*!=[\s]*/))
83
82
  action { [:NOT_EQUAL, text] }
84
83
 
85
- when (text = @ss.scan(/[\s\r\n\f]*=[\s\r\n\f]*/))
84
+ when (text = @ss.scan(/[\s]*=[\s]*/))
86
85
  action { [:EQUAL, text] }
87
86
 
88
- when (text = @ss.scan(/[\s\r\n\f]*\)/))
87
+ when (text = @ss.scan(/[\s]*\)/))
89
88
  action { [:RPAREN, text] }
90
89
 
91
- when (text = @ss.scan(/[\s\r\n\f]*\[[\s\r\n\f]*/))
90
+ when (text = @ss.scan(/[\s]*\[[\s]*/))
92
91
  action { [:LSQUARE, text] }
93
92
 
94
- when (text = @ss.scan(/[\s\r\n\f]*\]/))
93
+ when (text = @ss.scan(/[\s]*\]/))
95
94
  action { [:RSQUARE, text] }
96
95
 
97
- when (text = @ss.scan(/[\s\r\n\f]*\+[\s\r\n\f]*/))
96
+ when (text = @ss.scan(/[\s]*\+[\s]*/))
98
97
  action { [:PLUS, text] }
99
98
 
100
- when (text = @ss.scan(/[\s\r\n\f]*>[\s\r\n\f]*/))
99
+ when (text = @ss.scan(/[\s]*>[\s]*/))
101
100
  action { [:GREATER, text] }
102
101
 
103
- when (text = @ss.scan(/[\s\r\n\f]*,[\s\r\n\f]*/))
102
+ when (text = @ss.scan(/[\s]*,[\s]*/))
104
103
  action { [:COMMA, text] }
105
104
 
106
- when (text = @ss.scan(/[\s\r\n\f]*~[\s\r\n\f]*/))
105
+ when (text = @ss.scan(/[\s]*~[\s]*/))
107
106
  action { [:TILDE, text] }
108
107
 
109
- when (text = @ss.scan(/\:not\([\s\r\n\f]*/))
108
+ when (text = @ss.scan(/\:not\([\s]*/))
110
109
  action { [:NOT, text] }
111
110
 
112
111
  when (text = @ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)/))
113
112
  action { [:NUMBER, text] }
114
113
 
115
- when (text = @ss.scan(/[\s\r\n\f]*\/\/[\s\r\n\f]*/))
114
+ when (text = @ss.scan(/[\s]*\/\/[\s]*/))
116
115
  action { [:DOUBLESLASH, text] }
117
116
 
118
- when (text = @ss.scan(/[\s\r\n\f]*\/[\s\r\n\f]*/))
117
+ when (text = @ss.scan(/[\s]*\/[\s]*/))
119
118
  action { [:SLASH, text] }
120
119
 
121
120
  when (text = @ss.scan(/U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?/))
122
121
  action {[:UNICODE_RANGE, text] }
123
122
 
124
- when (text = @ss.scan(/[\s\t\r\n\f]+/))
123
+ when (text = @ss.scan(/[\s]+/))
125
124
  action { [:S, text] }
126
125
 
127
- 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
+ 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\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\f0-9A-Fa-f])*'/))
128
127
  action { [:STRING, text] }
129
128
 
130
129
  when (text = @ss.scan(/./))
@@ -222,7 +222,9 @@ rule
222
222
  }
223
223
  ;
224
224
  negation_arg
225
- : hcap_1toN
225
+ : element_name
226
+ | element_name hcap_1toN
227
+ | hcap_1toN
226
228
  ;
227
229
  end
228
230
 
@@ -4,10 +4,10 @@ class GeneratedTokenizer < GeneratedParser
4
4
 
5
5
  macro
6
6
  nl \n|\r\n|\r|\f
7
- w [\s\r\n\f]*
7
+ w [\s]*
8
8
  nonascii [^\0-\177]
9
9
  num -?([0-9]+|[0-9]*\.[0-9]+)
10
- unicode \\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?
10
+ unicode \\[0-9A-Fa-f]{1,6}(\r\n|[\s])?
11
11
 
12
12
  escape {unicode}|\\[^\n\r\f0-9A-Fa-f]
13
13
  nmchar [_A-Za-z0-9-]|{nonascii}|{escape}
@@ -47,7 +47,7 @@ rule
47
47
 
48
48
  U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})? {[:UNICODE_RANGE, text] }
49
49
 
50
- [\s\t\r\n\f]+ { [:S, text] }
50
+ [\s]+ { [:S, text] }
51
51
  {string} { [:STRING, text] }
52
52
  . { [text, text] }
53
53
  end
@@ -40,7 +40,12 @@ module Nokogiri
40
40
  end
41
41
 
42
42
  def visit_not node
43
- 'not(' + node.value.first.accept(self) + ')'
43
+ child = node.value.first
44
+ if :ELEMENT_NAME == child.type
45
+ "not(self::#{child.accept(self)})"
46
+ else
47
+ "not(#{child.accept(self)})"
48
+ end
44
49
  end
45
50
 
46
51
  def visit_preceding_selector node
@@ -100,8 +105,8 @@ module Nokogiri
100
105
  return self.send(msg, node) if self.respond_to?(msg)
101
106
 
102
107
  case node.value.first
103
- when "first" then "position() = 1"
104
- when "last" then "position() = last()"
108
+ when "first", "first-child" then "position() = 1"
109
+ when "last", "last-child" then "position() = last()"
105
110
  when "first-of-type" then "position() = 1"
106
111
  when "last-of-type" then "position() = last()"
107
112
  when "only-of-type" then "last() = 1"
@@ -20,9 +20,9 @@ module Nokogiri
20
20
  pc = allocate
21
21
  pc.cstruct = LibXML::XmlParserContext.new ctx
22
22
  if encoding
23
- enc = LibXML.xmlParseCharEncoding(encoding)
24
- if enc != LibXML::XML_CHAR_ENCODING_ERROR
25
- LibXML.xmlSwitchEncoding(ctx, enc)
23
+ enc = LibXML.xmlFindCharEncodingHandler(encoding)
24
+ if !enc.null?
25
+ LibXML.xmlSwitchToEncoding(ctx, enc)
26
26
  end
27
27
  end
28
28
  pc
@@ -2,7 +2,7 @@
2
2
  module Nokogiri
3
3
  module LibXML
4
4
  extend FFI::Library
5
- if RUBY_PLATFORM =~ /java/ && java.lang.System.getProperty('os.name') =~ /windows/i
5
+ if RUBY_PLATFORM =~ /java/ && RbConfig::CONFIG['host_os'] =~ /(mswin|mingw)/i
6
6
  raise(RuntimeError, "Nokogiri requires JRuby 1.4.0 or later on Windows") if JRUBY_VERSION < "1.4.0"
7
7
  dll_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "ext", "nokogiri"))
8
8
  libs = ["libxml2.dll", "libxslt.dll", "libexslt.dll"].collect do |lib|
@@ -80,6 +80,7 @@ module Nokogiri
80
80
  attach_function :htmlCreateMemoryParserCtxt, [:pointer, :int], :pointer
81
81
  attach_function :htmlCreateFileParserCtxt, [:pointer, :pointer], :pointer
82
82
  attach_function :htmlParseDocument, [:pointer], :int
83
+ attach_function :htmlHandleOmittedElem, [:int], :int
83
84
 
84
85
  # HTMLtree.c
85
86
  attach_function :htmlDocDumpMemory, [:pointer, :pointer, :pointer], :void
@@ -101,6 +102,7 @@ module Nokogiri
101
102
  attach_function :xmlCreatePushParserCtxt, [:pointer, :pointer, :string, :int, :string], :pointer
102
103
  attach_function :xmlParseChunk, [:pointer, :string, :int, :int], :int
103
104
  attach_function :xmlCtxtUseOptions, [:pointer, :int], :int
105
+ attach_function :xmlParseInNodeContext, [:pointer, :string, :int, :int, :pointer], :pointer
104
106
 
105
107
  # tree.c
106
108
  attach_function :xmlNewDoc, [:string], :pointer
@@ -111,6 +113,10 @@ module Nokogiri
111
113
  attach_function :xmlFreeDoc, [:pointer], :void
112
114
  attach_function :xmlSetTreeDoc, [:pointer, :pointer], :void
113
115
  attach_function :xmlNewReference, [:pointer, :string], :pointer
116
+ attach_function :xmlFirstElementChild, [:pointer], :pointer
117
+ attach_function :xmlLastElementChild, [:pointer], :pointer
118
+ attach_function :xmlNextElementSibling, [:pointer], :pointer
119
+ attach_function :xmlPreviousElementSibling, [:pointer], :pointer
114
120
  attach_function :xmlNewNode, [:pointer, :string], :pointer
115
121
  attach_function :xmlCopyNode, [:pointer, :int], :pointer
116
122
  attach_function :xmlDocCopyNode, [:pointer, :pointer, :int], :pointer
@@ -149,6 +155,8 @@ module Nokogiri
149
155
  attach_function :xmlFreePropList, [:pointer], :void
150
156
  attach_function :xmlCreateIntSubset, [:pointer] * 4, :pointer
151
157
  attach_function :xmlNewDtd, [:pointer] * 4, :pointer
158
+ attach_function :xmlGetNsList, [:pointer, :pointer], :pointer
159
+ attach_function :xmlTextMerge, [:pointer, :pointer], :pointer
152
160
 
153
161
  # valid.c
154
162
  attach_function :xmlNewValidCtxt, [], :pointer
@@ -165,6 +173,7 @@ module Nokogiri
165
173
 
166
174
  # entities.c
167
175
  attach_function :xmlEncodeSpecialChars, [:pointer, :string], :pointer # returns char* that must be freed
176
+ attach_function :xmlAddDocEntity, [:pointer, :string, :int, :string, :string, :string], :pointer
168
177
 
169
178
  # xpath.c
170
179
  attach_function :xmlXPathInit, [], :void
@@ -175,6 +184,7 @@ module Nokogiri
175
184
  attach_function :xmlXPathCmpNodes, [:pointer, :pointer], :int
176
185
  attach_function :xmlXPathNodeSetContains, [:pointer, :pointer], :int
177
186
  attach_function :xmlXPathNodeSetAdd, [:pointer, :pointer], :void
187
+ attach_function :xmlXPathNodeSetAddUnique, [:pointer, :pointer], :void
178
188
  attach_function :xmlXPathNodeSetRemove, [:pointer, :int], :void
179
189
  attach_function :xmlXPathNodeSetCreate, [:pointer], :pointer
180
190
  attach_function :xmlXPathNodeSetDel, [:pointer, :pointer], :void
@@ -248,6 +258,7 @@ module Nokogiri
248
258
  attach_function :xmlTextReaderConstPrefix, [:pointer], :pointer # returns a const char* that is deallocated with the reader
249
259
  attach_function :xmlTextReaderConstValue, [:pointer], :pointer # returns a const char* that is deallocated on the next read()
250
260
  attach_function :xmlTextReaderConstXmlVersion, [:pointer], :pointer # returns a const char* that is deallocated with the reader
261
+ attach_function :xmlTextReaderConstBaseUri, [:pointer], :pointer # returns a const char* that is deallocated with the reader
251
262
  attach_function :xmlTextReaderReadState, [:pointer], :int
252
263
  attach_function :xmlTextReaderHasValue, [:pointer], :int
253
264
  attach_function :xmlFreeTextReader, [:pointer], :void
@@ -274,6 +285,7 @@ module Nokogiri
274
285
  attach_function :xmlSchemaParse, [:pointer], :pointer
275
286
  attach_function :xmlSchemaFreeParserCtxt, [:pointer], :void
276
287
  attach_function :xmlSchemaNewDocParserCtxt, [:pointer], :pointer
288
+ attach_function :xmlSchemaValidateFile, [:pointer, :string, :int], :int
277
289
 
278
290
  # relaxng.c
279
291
  attach_function :xmlRelaxNGNewValidCtxt, [:pointer], :pointer
@@ -285,13 +297,14 @@ module Nokogiri
285
297
  attach_function :xmlRelaxNGParse, [:pointer], :pointer
286
298
  attach_function :xmlRelaxNGFreeParserCtxt, [:pointer], :void
287
299
  attach_function :xmlRelaxNGNewDocParserCtxt, [:pointer], :pointer
300
+ attach_function :xmlRelaxNGFree, [:pointer], :void
288
301
 
289
302
  # libc
290
303
  attach_function :calloc, [:int, :int], :pointer
291
304
  attach_function :free, [:pointer], :void
292
305
 
293
306
  attach_function :xmlParseCharEncoding, [:string], :int
294
- attach_function :xmlSwitchEncoding, [:pointer, :int], :void
307
+ attach_function :xmlSwitchToEncoding, [:pointer, :pointer], :void
295
308
 
296
309
  # helpers
297
310
  POINTER_SIZE = FFI.type_size(:pointer)
@@ -308,6 +321,7 @@ require 'nokogiri/xml/syntax_error'
308
321
 
309
322
  [ "io_callbacks",
310
323
  "encoding_handler",
324
+ "weak_bucket",
311
325
  "structs/common_node",
312
326
  "structs/xml_alloc",
313
327
  "structs/xml_char_encoding_handler",
@@ -1,18 +1,25 @@
1
1
  module Nokogiri
2
2
  module LibXML # :nodoc:
3
3
  module CommonNode # :nodoc:
4
-
5
4
  def document
6
5
  p = self[:doc]
7
6
  p.null? ? nil : LibXML::XmlDocumentCast.new(p)
8
7
  end
9
8
 
9
+ def ruby_node_pointer
10
+ self[:_private]
11
+ end
12
+
13
+ def ruby_node_pointer=(value)
14
+ self[:_private] = value
15
+ end
16
+
10
17
  def ruby_node
11
- self[:_private] != 0 ? ObjectSpace._id2ref(self[:_private]) : nil
18
+ Nokogiri::WeakBucket.get_object(self)
12
19
  end
13
20
 
14
21
  def ruby_node= object
15
- self[:_private] = object.object_id
22
+ Nokogiri::WeakBucket.set_object(self, object)
16
23
  end
17
24
 
18
25
  def keep_reference_from_document! # equivalent to NOKOGIRI_ROOT_NODE
@@ -20,6 +27,11 @@ module Nokogiri
20
27
  raise "no document to add reference to" unless doc
21
28
  LibXML.xmlXPathNodeSetAdd(doc.unlinked_nodes, self)
22
29
  end
30
+
31
+ def keep_reference_from!(document) # equivalent to NOKOGIRI_ROOT_NSDEF
32
+ raise "no document to add reference to" unless document
33
+ LibXML.xmlXPathNodeSetAdd(document.unlinked_nodes, self)
34
+ end
23
35
  end
24
36
  end
25
37
  end
@@ -36,14 +36,21 @@ module Nokogiri
36
36
  p.null? ? nil : LibXML::XmlDocumentCast.new(p)
37
37
  end
38
38
 
39
+ def ruby_node_pointer
40
+ tuple = self[:_private]
41
+ tuple.null? ? 0 : tuple.get_long(0)
42
+ end
43
+
44
+ def ruby_node_pointer=(value)
45
+ self[:_private].put_long(0, value)
46
+ end
47
+
39
48
  def ruby_doc
40
- ptr = self[:_private]
41
- return nil if ptr.null?
42
- ObjectSpace._id2ref(ptr.get_long(0))
49
+ Nokogiri::WeakBucket.get_object(self)
43
50
  end
44
51
 
45
52
  def ruby_doc=(object)
46
- self[:_private].put_long(0, object.object_id)
53
+ Nokogiri::WeakBucket.set_object(self, object)
47
54
  end
48
55
 
49
56
  def unlinked_nodes
@@ -78,6 +85,8 @@ module Nokogiri
78
85
  case node_cstruct[:type]
79
86
  when Nokogiri::XML::Node::ATTRIBUTE_NODE
80
87
  LibXML.xmlFreePropList(node_cstruct)
88
+ when Nokogiri::XML::Node::NAMESPACE_DECL
89
+ LibXML.xmlFree(node_cstruct)
81
90
  else
82
91
  LibXML.xmlAddChild(doc, node_cstruct) if node_cstruct[:parent].null?
83
92
  end
@@ -16,8 +16,9 @@ module Nokogiri
16
16
  LibXML::XmlNode.new(self[:node])
17
17
  end
18
18
 
19
- def doc
20
- LibXML::XmlDocumentCast.new(self[:doc])
19
+ def document
20
+ p = self[:doc]
21
+ p.null? ? nil : LibXML::XmlDocumentCast.new(p)
21
22
  end
22
23
  end
23
24
 
@@ -0,0 +1,40 @@
1
+ # :stopdoc:
2
+ if ENV['NOKOGIRI_ID2REF'] || RUBY_PLATFORM !~ /java/
3
+ Nokogiri::VERSION_INFO['refs'] = "id2ref"
4
+ else
5
+ require 'weakling'
6
+ Nokogiri::VERSION_INFO['refs'] = "weakling"
7
+ end
8
+ require 'singleton'
9
+
10
+ module Nokogiri
11
+ class WeakBucket
12
+ include Singleton
13
+
14
+ if Nokogiri::VERSION_INFO['refs'] == "weakling"
15
+ attr_accessor :bucket
16
+
17
+ def initialize
18
+ @bucket = Weakling::IdHash.new
19
+ end
20
+
21
+ def WeakBucket.get_object(cstruct)
22
+ instance.bucket[cstruct.ruby_node_pointer]
23
+ end
24
+
25
+ def WeakBucket.set_object(cstruct, object)
26
+ cstruct.ruby_node_pointer = instance.bucket.add(object)
27
+ end
28
+ else
29
+ def WeakBucket.get_object(cstruct)
30
+ ptr = cstruct.ruby_node_pointer
31
+ ptr != 0 ? ObjectSpace._id2ref(ptr) : nil
32
+ end
33
+
34
+ def WeakBucket.set_object(cstruct, object)
35
+ cstruct.ruby_node_pointer = object.object_id
36
+ end
37
+ end
38
+ end
39
+ end
40
+ # :startdoc:
@@ -11,6 +11,17 @@ module Nokogiri
11
11
 
12
12
  def root= new_root
13
13
  old_root = nil
14
+
15
+ if new_root.nil?
16
+ old_root_ptr = LibXML.xmlDocGetRootElement(cstruct)
17
+ if (! old_root_ptr.null?)
18
+ old_root = Node.wrap(old_root_ptr)
19
+ LibXML.xmlUnlinkNode(old_root.cstruct)
20
+ old_root.cstruct.keep_reference_from_document!
21
+ end
22
+ return new_root
23
+ end
24
+
14
25
  if new_root.cstruct[:doc] != cstruct[:doc]
15
26
  old_root_ptr = LibXML.xmlDocGetRootElement(cstruct)
16
27
  new_root_ptr = LibXML.xmlDocCopyNode(new_root.cstruct, cstruct, 1)
@@ -70,6 +81,22 @@ module Nokogiri
70
81
  self.class.recursively_remove_namespaces_from_node(root)
71
82
  end
72
83
 
84
+ def create_entity(name, entity_type=Nokogiri::XML::EntityDecl::INTERNAL_GENERAL,
85
+ external_id=nil, system_id=nil, content=nil)
86
+ LibXML.xmlResetLastError()
87
+ ptr = LibXML.xmlAddDocEntity(cstruct, name, entity_type, external_id, system_id, content)
88
+ if ptr.null?
89
+ error = LibXML.xmlGetLastError()
90
+ if error
91
+ raise SyntaxError.wrap(error)
92
+ else
93
+ raise RuntimeError, "Could not create entity"
94
+ end
95
+ end
96
+
97
+ Node.wrap(LibXML::XmlEntity.new(ptr))
98
+ end
99
+
73
100
  class << self
74
101
  def new(*args)
75
102
  version = args.first || "1.0"