nokogiri 1.5.0.beta.3 → 1.5.0.beta.4

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 (87) hide show
  1. data/CHANGELOG.ja.rdoc +32 -16
  2. data/CHANGELOG.rdoc +18 -0
  3. data/Manifest.txt +1 -2
  4. data/README.rdoc +27 -3
  5. data/Rakefile +39 -83
  6. data/ext/java/nokogiri/EncodingHandler.java +1 -1
  7. data/ext/java/nokogiri/HtmlDocument.java +11 -14
  8. data/ext/java/nokogiri/HtmlElementDescription.java +1 -1
  9. data/ext/java/nokogiri/HtmlEntityLookup.java +1 -1
  10. data/ext/java/nokogiri/HtmlSaxParserContext.java +13 -10
  11. data/ext/java/nokogiri/NokogiriService.java +103 -34
  12. data/ext/java/nokogiri/XmlAttr.java +14 -6
  13. data/ext/java/nokogiri/XmlAttributeDecl.java +1 -1
  14. data/ext/java/nokogiri/XmlCdata.java +3 -1
  15. data/ext/java/nokogiri/XmlComment.java +3 -1
  16. data/ext/java/nokogiri/XmlDocument.java +29 -8
  17. data/ext/java/nokogiri/XmlDocumentFragment.java +14 -13
  18. data/ext/java/nokogiri/XmlDtd.java +5 -2
  19. data/ext/java/nokogiri/XmlElement.java +2 -1
  20. data/ext/java/nokogiri/XmlElementContent.java +1 -1
  21. data/ext/java/nokogiri/XmlElementDecl.java +2 -1
  22. data/ext/java/nokogiri/XmlEntityDecl.java +2 -1
  23. data/ext/java/nokogiri/XmlEntityReference.java +1 -1
  24. data/ext/java/nokogiri/XmlNamespace.java +3 -2
  25. data/ext/java/nokogiri/XmlNode.java +17 -10
  26. data/ext/java/nokogiri/XmlNodeSet.java +40 -13
  27. data/ext/java/nokogiri/XmlProcessingInstruction.java +1 -1
  28. data/ext/java/nokogiri/XmlReader.java +3 -1
  29. data/ext/java/nokogiri/XmlRelaxng.java +37 -92
  30. data/ext/java/nokogiri/XmlSaxParserContext.java +25 -11
  31. data/ext/java/nokogiri/XmlSaxPushParser.java +6 -4
  32. data/ext/java/nokogiri/XmlSchema.java +190 -46
  33. data/ext/java/nokogiri/XmlSyntaxError.java +42 -37
  34. data/ext/java/nokogiri/XmlText.java +3 -2
  35. data/ext/java/nokogiri/XmlXpathContext.java +8 -4
  36. data/ext/java/nokogiri/XsltStylesheet.java +12 -10
  37. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +8 -7
  38. data/ext/java/nokogiri/internals/NokogiriDocumentCache.java +1 -1
  39. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +11 -5
  40. data/ext/java/nokogiri/internals/NokogiriHandler.java +36 -9
  41. data/ext/java/nokogiri/internals/NokogiriHelpers.java +21 -22
  42. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +5 -4
  43. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +1 -1
  44. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +2 -1
  45. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +1 -1
  46. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +2 -1
  47. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +15 -9
  48. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +1 -1
  49. data/ext/java/nokogiri/internals/ParserContext.java +18 -7
  50. data/ext/java/nokogiri/internals/PushInputStream.java +1 -1
  51. data/ext/java/nokogiri/internals/ReaderNode.java +7 -6
  52. data/ext/java/nokogiri/internals/SaveContext.java +16 -10
  53. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +13 -5
  54. data/ext/java/nokogiri/internals/XmlDeclHandler.java +1 -1
  55. data/ext/java/nokogiri/internals/XmlDomParser.java +1 -1
  56. data/ext/java/nokogiri/internals/XmlDomParserContext.java +13 -8
  57. data/ext/java/nokogiri/internals/XmlSaxParser.java +1 -1
  58. data/ext/java/nokogiri/internals/XsltExtensionFunction.java +1 -1
  59. data/ext/nokogiri/extconf.rb +3 -3
  60. data/ext/nokogiri/xml_document.c +9 -0
  61. data/ext/nokogiri/xml_sax_parser.c +4 -2
  62. data/lib/nokogiri.rb +9 -6
  63. data/lib/nokogiri/css.rb +1 -3
  64. data/lib/nokogiri/css/parser.rb +665 -70
  65. data/lib/nokogiri/css/parser.y +3 -1
  66. data/lib/nokogiri/css/parser_extras.rb +91 -0
  67. data/lib/nokogiri/css/tokenizer.rb +148 -3
  68. data/lib/nokogiri/css/tokenizer.rex +1 -1
  69. data/lib/nokogiri/html/document.rb +138 -11
  70. data/lib/nokogiri/html/sax/parser.rb +6 -2
  71. data/lib/nokogiri/version.rb +1 -1
  72. data/lib/nokogiri/xml/node.rb +2 -2
  73. data/lib/nokogiri/xml/node/save_options.rb +3 -0
  74. data/lib/nokogiri/xml/node_set.rb +1 -1
  75. data/test/css/test_tokenizer.rb +8 -0
  76. data/test/helper.rb +2 -0
  77. data/test/html/sax/test_parser.rb +43 -0
  78. data/test/html/test_document.rb +59 -0
  79. data/test/html/test_document_encoding.rb +48 -0
  80. data/test/html/test_element_description.rb +1 -1
  81. data/test/xml/sax/test_parser.rb +16 -0
  82. data/test/xml/test_document.rb +3 -1
  83. data/test/xml/test_node.rb +4 -1
  84. data/test/xml/test_node_set.rb +10 -0
  85. metadata +90 -107
  86. data/lib/nokogiri/css/generated_parser.rb +0 -676
  87. data/lib/nokogiri/css/generated_tokenizer.rb +0 -145
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2010:
4
+ * Copyright (c) 2008 - 2011:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -32,11 +32,14 @@
32
32
 
33
33
  package nokogiri;
34
34
 
35
+ import java.util.Collections;
36
+ import java.util.HashMap;
37
+ import java.util.Map;
38
+
35
39
  import org.jruby.Ruby;
36
40
  import org.jruby.RubyArray;
37
41
  import org.jruby.RubyClass;
38
42
  import org.jruby.RubyFixnum;
39
- import org.jruby.RubyHash;
40
43
  import org.jruby.RubyModule;
41
44
  import org.jruby.runtime.ObjectAllocator;
42
45
  import org.jruby.runtime.builtin.IRubyObject;
@@ -47,9 +50,11 @@ import org.jruby.runtime.load.BasicLibraryService;
47
50
  * in JRuby. Also, this class holds a Ruby type cache and allocators of Ruby types.
48
51
  *
49
52
  * @author headius
53
+ * @author Yoko Harada <yokolet@gmail.com>
50
54
  */
51
55
  public class NokogiriService implements BasicLibraryService {
52
56
  public static final String nokogiriClassCacheGvarName = "$NOKOGIRI_CLASS_CACHE";
57
+ public static Map<String, RubyClass> nokogiriClassCache;
53
58
 
54
59
  public boolean basicLoad(Ruby ruby) {
55
60
  init(ruby);
@@ -57,9 +62,11 @@ public class NokogiriService implements BasicLibraryService {
57
62
  return true;
58
63
  }
59
64
 
60
- private void createNokogiriClassCahce(Ruby ruby) {
61
- RubyHash nokogiriClassCache = RubyHash.newHash(ruby);
65
+ private static void createNokogiriClassCahce(Ruby ruby) {
66
+ nokogiriClassCache = Collections.synchronizedMap(new HashMap<String, RubyClass>());
62
67
  nokogiriClassCache.put("Nokogiri::EncodingHandler", (RubyClass)ruby.getClassFromPath("Nokogiri::EncodingHandler"));
68
+ nokogiriClassCache.put("Nokogiri::HTML::Document", (RubyClass)ruby.getClassFromPath("Nokogiri::HTML::Document"));
69
+ nokogiriClassCache.put("Nokogiri::HTML::ElementDescription", (RubyClass)ruby.getClassFromPath("Nokogiri::HTML::ElementDescription"));
63
70
  nokogiriClassCache.put("Nokogiri::XML::Attr", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Attr"));
64
71
  nokogiriClassCache.put("Nokogiri::XML::Document", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Document"));
65
72
  nokogiriClassCache.put("Nokogiri::XML::DocumentFragment", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::DocumentFragment"));
@@ -74,13 +81,11 @@ public class NokogiriService implements BasicLibraryService {
74
81
  nokogiriClassCache.put("Nokogiri::XML::Node", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Node"));
75
82
  nokogiriClassCache.put("Nokogiri::XML::NodeSet", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::NodeSet"));
76
83
  nokogiriClassCache.put("Nokogiri::XML::Namespace", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Namespace"));
84
+ nokogiriClassCache.put("Nokogiri::XML::SyntaxError", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::SyntaxError"));
77
85
  nokogiriClassCache.put("Nokogiri::XML::RelaxNG", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::RelaxNG"));
78
- nokogiriClassCache.put("Nokogiri::HTML::Document", (RubyClass)ruby.getClassFromPath("Nokogiri::HTML::Document"));
79
- nokogiriClassCache.put("Nokogiri::HTML::ElementDescription", (RubyClass)ruby.getClassFromPath("Nokogiri::HTML::ElementDescription"));
86
+ nokogiriClassCache.put("Nokogiri::XML::Schema", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Schema"));
80
87
  nokogiriClassCache.put("Nokogiri::XML::AttributeDecl", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::AttributeDecl"));
81
88
  nokogiriClassCache.put("Nokogiri::XML::SAX::ParserContext", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::SAX::ParserContext"));
82
-
83
- ruby.getGlobalVariables().set(nokogiriClassCacheGvarName, nokogiriClassCache);
84
89
  }
85
90
 
86
91
  private void init(Ruby ruby) {
@@ -201,13 +206,13 @@ public class NokogiriService implements BasicLibraryService {
201
206
  }
202
207
 
203
208
  private void createSaxModule(Ruby ruby, RubyModule xmlSaxModule, RubyModule htmlSaxModule) {
204
- RubyClass xmlSaxParserContext = xmlSaxModule.defineClassUnder("ParserContext", ruby.getObject(), XML_SAXPARSER_ALLOCATOR);
209
+ RubyClass xmlSaxParserContext = xmlSaxModule.defineClassUnder("ParserContext", ruby.getObject(), XML_SAXPARSER_CONTEXT_ALLOCATOR);
205
210
  xmlSaxParserContext.defineAnnotatedMethods(XmlSaxParserContext.class);
206
211
 
207
212
  RubyClass xmlSaxPushParser = xmlSaxModule.defineClassUnder("PushParser", ruby.getObject(), XML_SAXPUSHPARSER_ALLOCATOR);
208
213
  xmlSaxPushParser.defineAnnotatedMethods(XmlSaxPushParser.class);
209
214
 
210
- RubyClass htmlSaxParserContext = htmlSaxModule.defineClassUnder("ParserContext", xmlSaxParserContext, HTML_SAXPARSER_ALLOCATOR);
215
+ RubyClass htmlSaxParserContext = htmlSaxModule.defineClassUnder("ParserContext", xmlSaxParserContext, HTML_SAXPARSER_CONTEXT_ALLOCATOR);
211
216
  htmlSaxParserContext.defineAnnotatedMethods(HtmlSaxParserContext.class);
212
217
  }
213
218
 
@@ -223,7 +228,7 @@ public class NokogiriService implements BasicLibraryService {
223
228
  }
224
229
  };
225
230
 
226
- private static ObjectAllocator HTML_DOCUMENT_ALLOCATOR = new ObjectAllocator() {
231
+ public static final ObjectAllocator HTML_DOCUMENT_ALLOCATOR = new ObjectAllocator() {
227
232
  private HtmlDocument htmlDocument = null;
228
233
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
229
234
  if (htmlDocument == null) htmlDocument = new HtmlDocument(runtime, klazz);
@@ -237,9 +242,17 @@ public class NokogiriService implements BasicLibraryService {
237
242
  }
238
243
  };
239
244
 
240
- private static ObjectAllocator HTML_SAXPARSER_ALLOCATOR = new ObjectAllocator() {
245
+ public static final ObjectAllocator HTML_SAXPARSER_CONTEXT_ALLOCATOR = new ObjectAllocator() {
246
+ private HtmlSaxParserContext htmlSaxParserContext = null;
241
247
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
242
- return new HtmlSaxParserContext(runtime, klazz);
248
+ if (htmlSaxParserContext == null) htmlSaxParserContext = new HtmlSaxParserContext(runtime, klazz);
249
+ try {
250
+ HtmlSaxParserContext clone = (HtmlSaxParserContext) htmlSaxParserContext.clone();
251
+ clone.setMetaClass(klazz);
252
+ return clone;
253
+ } catch (CloneNotSupportedException e) {
254
+ return new HtmlSaxParserContext(runtime, klazz);
255
+ }
243
256
  }
244
257
  };
245
258
 
@@ -257,7 +270,7 @@ public class NokogiriService implements BasicLibraryService {
257
270
  }
258
271
  };
259
272
 
260
- private static ObjectAllocator XML_ATTR_ALLOCATOR = new ObjectAllocator() {
273
+ public static final ObjectAllocator XML_ATTR_ALLOCATOR = new ObjectAllocator() {
261
274
  private XmlAttr xmlAttr = null;
262
275
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
263
276
  if (xmlAttr == null) xmlAttr = new XmlAttr(runtime, klazz);
@@ -271,7 +284,7 @@ public class NokogiriService implements BasicLibraryService {
271
284
  }
272
285
  };
273
286
 
274
- private static ObjectAllocator XML_CDATA_ALLOCATOR = new ObjectAllocator() {
287
+ public static final ObjectAllocator XML_CDATA_ALLOCATOR = new ObjectAllocator() {
275
288
  private XmlCdata xmlCdata = null;
276
289
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
277
290
  if (xmlCdata == null) xmlCdata = new XmlCdata(runtime, klazz);
@@ -285,7 +298,7 @@ public class NokogiriService implements BasicLibraryService {
285
298
  }
286
299
  };
287
300
 
288
- private static ObjectAllocator XML_COMMENT_ALLOCATOR = new ObjectAllocator() {
301
+ public static final ObjectAllocator XML_COMMENT_ALLOCATOR = new ObjectAllocator() {
289
302
  private XmlComment xmlComment = null;
290
303
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
291
304
  if (xmlComment == null) xmlComment = new XmlComment(runtime, klazz);
@@ -306,7 +319,7 @@ public class NokogiriService implements BasicLibraryService {
306
319
  }
307
320
  };
308
321
 
309
- private static ObjectAllocator XML_DOCUMENT_ALLOCATOR = new ObjectAllocator() {
322
+ public static final ObjectAllocator XML_DOCUMENT_ALLOCATOR = new ObjectAllocator() {
310
323
  private XmlDocument xmlDocument = null;
311
324
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
312
325
  if (xmlDocument == null) xmlDocument = new XmlDocument(runtime, klazz);
@@ -320,9 +333,17 @@ public class NokogiriService implements BasicLibraryService {
320
333
  }
321
334
  };
322
335
 
323
- private static ObjectAllocator XML_DOCUMENT_FRAGMENT_ALLOCATOR = new ObjectAllocator() {
336
+ public static final ObjectAllocator XML_DOCUMENT_FRAGMENT_ALLOCATOR = new ObjectAllocator() {
337
+ private XmlDocumentFragment xmlDocumentFragment = null;
324
338
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
325
- return new XmlDocumentFragment(runtime, klazz);
339
+ if (xmlDocumentFragment == null) xmlDocumentFragment = new XmlDocumentFragment(runtime, klazz);
340
+ try {
341
+ XmlDocumentFragment clone = (XmlDocumentFragment)xmlDocumentFragment.clone();
342
+ clone.setMetaClass(klazz);
343
+ return clone;
344
+ } catch (CloneNotSupportedException e) {
345
+ return new XmlDocumentFragment(runtime, klazz);
346
+ }
326
347
  }
327
348
  };
328
349
 
@@ -332,7 +353,7 @@ public class NokogiriService implements BasicLibraryService {
332
353
  }
333
354
  };
334
355
 
335
- private static ObjectAllocator XML_ELEMENT_ALLOCATOR = new ObjectAllocator() {
356
+ public static final ObjectAllocator XML_ELEMENT_ALLOCATOR = new ObjectAllocator() {
336
357
  private XmlElement xmlElement = null;
337
358
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
338
359
  if (xmlElement == null) xmlElement = new XmlElement(runtime, klazz);
@@ -352,7 +373,7 @@ public class NokogiriService implements BasicLibraryService {
352
373
  }
353
374
  };
354
375
 
355
- private static ObjectAllocator XML_NAMESPACE_ALLOCATOR = new ObjectAllocator() {
376
+ public static final ObjectAllocator XML_NAMESPACE_ALLOCATOR = new ObjectAllocator() {
356
377
  private XmlNamespace xmlNamespace = null;
357
378
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
358
379
  if (xmlNamespace == null) xmlNamespace = new XmlNamespace(runtime, klazz);
@@ -366,7 +387,7 @@ public class NokogiriService implements BasicLibraryService {
366
387
  }
367
388
  };
368
389
 
369
- private static ObjectAllocator XML_NODE_ALLOCATOR = new ObjectAllocator() {
390
+ public static final ObjectAllocator XML_NODE_ALLOCATOR = new ObjectAllocator() {
370
391
  private XmlNode xmlNode = null;
371
392
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
372
393
  if (xmlNode == null) xmlNode = new XmlNode(runtime, klazz);
@@ -380,9 +401,17 @@ public class NokogiriService implements BasicLibraryService {
380
401
  }
381
402
  };
382
403
 
383
- private static ObjectAllocator XML_NODESET_ALLOCATOR = new ObjectAllocator() {
404
+ public static final ObjectAllocator XML_NODESET_ALLOCATOR = new ObjectAllocator() {
405
+ private XmlNodeSet xmlNodeSet = null;
384
406
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
385
- return new XmlNodeSet(runtime, klazz, RubyArray.newEmptyArray(runtime));
407
+ if (xmlNodeSet == null) xmlNodeSet = new XmlNodeSet(runtime, klazz);
408
+ try {
409
+ XmlNodeSet clone = (XmlNodeSet) xmlNodeSet.clone();
410
+ clone.setMetaClass(klazz);
411
+ return clone;
412
+ } catch (CloneNotSupportedException e) {
413
+ return new XmlNodeSet(runtime, klazz, RubyArray.newEmptyArray(runtime));
414
+ }
386
415
  }
387
416
  };
388
417
 
@@ -416,15 +445,31 @@ public class NokogiriService implements BasicLibraryService {
416
445
  }
417
446
  };
418
447
 
419
- private static ObjectAllocator XML_RELAXNG_ALLOCATOR = new ObjectAllocator() {
448
+ public static final ObjectAllocator XML_RELAXNG_ALLOCATOR = new ObjectAllocator() {
449
+ private XmlRelaxng xmlRelaxng = null;
420
450
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
421
- return new XmlRelaxng(runtime, klazz);
451
+ if (xmlRelaxng == null) xmlRelaxng = new XmlRelaxng(runtime, klazz);
452
+ try {
453
+ XmlRelaxng clone = (XmlRelaxng) xmlRelaxng.clone();
454
+ clone.setMetaClass(klazz);
455
+ return clone;
456
+ } catch (CloneNotSupportedException e) {
457
+ return new XmlRelaxng(runtime, klazz);
458
+ }
422
459
  }
423
460
  };
424
461
 
425
- private static ObjectAllocator XML_SAXPARSER_ALLOCATOR = new ObjectAllocator() {
462
+ public static final ObjectAllocator XML_SAXPARSER_CONTEXT_ALLOCATOR = new ObjectAllocator() {
463
+ private XmlSaxParserContext xmlSaxParserContext = null;
426
464
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
427
- return new XmlSaxParserContext(runtime, klazz);
465
+ if (xmlSaxParserContext == null) xmlSaxParserContext = new XmlSaxParserContext(runtime, klazz);
466
+ try {
467
+ XmlSaxParserContext clone = (XmlSaxParserContext) xmlSaxParserContext.clone();
468
+ clone.setMetaClass(klazz);
469
+ return clone;
470
+ } catch (CloneNotSupportedException e) {
471
+ return new XmlSaxParserContext(runtime, klazz);
472
+ }
428
473
  }
429
474
  };
430
475
 
@@ -434,21 +479,45 @@ public class NokogiriService implements BasicLibraryService {
434
479
  }
435
480
  };
436
481
 
437
- private static ObjectAllocator XML_SCHEMA_ALLOCATOR = new ObjectAllocator() {
482
+ public static final ObjectAllocator XML_SCHEMA_ALLOCATOR = new ObjectAllocator() {
483
+ private XmlSchema xmlSchema = null;
438
484
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
439
- return new XmlSchema(runtime, klazz);
485
+ if (xmlSchema == null) xmlSchema = new XmlSchema(runtime, klazz);
486
+ try {
487
+ XmlSchema clone = (XmlSchema) xmlSchema.clone();
488
+ clone.setMetaClass(klazz);
489
+ return clone;
490
+ } catch (CloneNotSupportedException e) {
491
+ return new XmlSchema(runtime, klazz);
492
+ }
440
493
  }
441
494
  };
442
495
 
443
- private static ObjectAllocator XML_SYNTAXERROR_ALLOCATOR = new ObjectAllocator() {
496
+ public static final ObjectAllocator XML_SYNTAXERROR_ALLOCATOR = new ObjectAllocator() {
497
+ private XmlSyntaxError xmlSyntaxError = null;
444
498
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
445
- return new XmlSyntaxError(runtime, klazz);
499
+ if (xmlSyntaxError == null) xmlSyntaxError = new XmlSyntaxError(runtime, klazz);
500
+ try {
501
+ XmlSyntaxError clone = (XmlSyntaxError) xmlSyntaxError.clone();
502
+ clone.setMetaClass(klazz);
503
+ return clone;
504
+ } catch (CloneNotSupportedException e) {
505
+ return new XmlSyntaxError(runtime, klazz);
506
+ }
446
507
  }
447
508
  };
448
509
 
449
- private static ObjectAllocator XML_TEXT_ALLOCATOR = new ObjectAllocator() {
510
+ public static final ObjectAllocator XML_TEXT_ALLOCATOR = new ObjectAllocator() {
511
+ private XmlText xmlText = null;
450
512
  public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
451
- return new XmlText(runtime, klazz);
513
+ if (xmlText == null) xmlText = new XmlText(runtime, klazz);
514
+ try {
515
+ XmlText clone = (XmlText) xmlText.clone();
516
+ clone.setMetaClass(klazz);
517
+ return clone;
518
+ } catch (CloneNotSupportedException e) {
519
+ return new XmlText(runtime, klazz);
520
+ }
452
521
  }
453
522
  };
454
523
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2010:
4
+ * Copyright (c) 2008 - 2011:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -38,6 +38,7 @@ import nokogiri.internals.NokogiriHelpers;
38
38
  import nokogiri.internals.SaveContext;
39
39
 
40
40
  import org.jruby.Ruby;
41
+ import org.jruby.RubyBoolean;
41
42
  import org.jruby.RubyClass;
42
43
  import org.jruby.RubyString;
43
44
  import org.jruby.anno.JRubyClass;
@@ -51,6 +52,8 @@ import org.w3c.dom.Node;
51
52
  /**
52
53
  * Class for Nokogiri::XML::Attr
53
54
  *
55
+ * @author sergio
56
+ * @author Yoko Harada <yokolet@gmail.com>
54
57
  */
55
58
 
56
59
  @JRubyClass(name="Nokogiri::XML::Attr", parent="Nokogiri::XML::Node")
@@ -106,7 +109,7 @@ public class XmlAttr extends XmlNode{
106
109
  }
107
110
 
108
111
 
109
- private String serializeAttrTextContent(String s) {
112
+ private String serializeAttrTextContent(String s, boolean htmlDoc) {
110
113
  if (s == null) return "";
111
114
 
112
115
  char[] c = s.toCharArray();
@@ -117,9 +120,9 @@ public class XmlAttr extends XmlNode{
117
120
  case '\n': buffer.append("&#10;"); break;
118
121
  case '\r': buffer.append("&#13;"); break;
119
122
  case '\t': buffer.append("&#9;"); break;
120
- //case '"': buffer.append("&quot;"); break;
121
- // TODO: is replacing '"' with '%22' always correct?
122
- case '"': buffer.append("%22"); break;
123
+ case '"': if (htmlDoc) buffer.append("%22");
124
+ else buffer.append("&quot;");
125
+ break;
123
126
  case '<': buffer.append("&lt;"); break;
124
127
  case '>': buffer.append("&gt;"); break;
125
128
  case '&': buffer.append("&amp;"); break;
@@ -158,6 +161,7 @@ public class XmlAttr extends XmlNode{
158
161
 
159
162
  @Override
160
163
  public void saveContent(ThreadContext context, SaveContext ctx) {
164
+ boolean docType = isHtml(context);
161
165
  Attr attr = (Attr) node;
162
166
 
163
167
  ctx.maybeSpace();
@@ -166,10 +170,14 @@ public class XmlAttr extends XmlNode{
166
170
  if (!ctx.asHtml() || !isHtmlBooleanAttr()) {
167
171
  ctx.append("=");
168
172
  ctx.append("\"");
169
- ctx.append(serializeAttrTextContent(attr.getValue()));
173
+ ctx.append(serializeAttrTextContent(attr.getValue(), docType));
170
174
  ctx.append("\"");
171
175
  }
172
176
  }
177
+
178
+ private boolean isHtml(ThreadContext context) {
179
+ return document(context).getMetaClass().isKindOfModule(getNokogiriClass(context.getRuntime(), "Nokogiri::HTML::Document"));
180
+ }
173
181
 
174
182
  @Override
175
183
  public IRubyObject unlink(ThreadContext context) {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2010:
4
+ * Copyright (c) 2008 - 2011:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2010:
4
+ * Copyright (c) 2008 - 2011:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -48,6 +48,8 @@ import org.w3c.dom.Node;
48
48
  /**
49
49
  * Class for Nokogiri::XML::CDATA
50
50
  *
51
+ * @author sergio
52
+ * @author Yoko Harada <yokolet@gmail.com>
51
53
  */
52
54
 
53
55
  @JRubyClass(name="Nokogiri::XML::CDATA", parent="Nokogiri::XML::Text")
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2010:
4
+ * Copyright (c) 2008 - 2011:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -46,6 +46,8 @@ import org.w3c.dom.Node;
46
46
  /**
47
47
  * Class for Nokogiri::XML::Comment
48
48
  *
49
+ * @author sergio
50
+ * @author Yoko Harada <yokolet@gmail.com>
49
51
  */
50
52
 
51
53
  @JRubyClass(name="Nokogiri::XML::Comment", parent="Nokogiri::XML::CharacterData")
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2010:
4
+ * Copyright (c) 2008 - 2011:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -66,6 +66,8 @@ import org.w3c.dom.NodeList;
66
66
  /**
67
67
  * Class for Nokogiri::XML::Document
68
68
  *
69
+ * @author sergio
70
+ * @author Yoko Harada <yokolet@gmail.com>
69
71
  */
70
72
 
71
73
  @JRubyClass(name="Nokogiri::XML::Document", parent="Nokogiri::XML::Node")
@@ -76,6 +78,11 @@ public class XmlDocument extends XmlNode {
76
78
  public final static String DTD_RAW_DOCUMENT = "DTD_RAW_DOCUMENT";
77
79
  protected final static String DTD_INTERNAL_SUBSET = "DTD_INTERNAL_SUBSET";
78
80
  protected final static String DTD_EXTERNAL_SUBSET = "DTD_EXTERNAL_SUBSET";
81
+
82
+ /* DocumentBuilderFactory implementation class name. This needs to set a classloader into it.
83
+ * Setting an appropriate classloader resolves issue 380.
84
+ */
85
+ private static final String DOCUMENTBUILDERFACTORY_IMPLE_NAME = "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
79
86
 
80
87
  private static boolean substituteEntities = false;
81
88
  private static boolean loadExternalSubset = false; // TODO: Verify this.
@@ -86,7 +93,6 @@ public class XmlDocument extends XmlNode {
86
93
 
87
94
  public XmlDocument(Ruby ruby, RubyClass klazz) {
88
95
  super(ruby, klazz, createNewDocument());
89
- nsCache = new NokogiriNamespaceCache();
90
96
  }
91
97
 
92
98
  public XmlDocument(Ruby ruby, Document document) {
@@ -104,6 +110,7 @@ public class XmlDocument extends XmlNode {
104
110
  @Override
105
111
  public void setNode(ThreadContext context, Node node) {
106
112
  super.setNode(context, node);
113
+ if (nsCache == null) nsCache = new NokogiriNamespaceCache();
107
114
  Ruby runtime = context.getRuntime();
108
115
  if (node != null) {
109
116
  Document document = (Document)node;
@@ -210,7 +217,8 @@ public class XmlDocument extends XmlNode {
210
217
 
211
218
  protected static Document createNewDocument() {
212
219
  try {
213
- return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
220
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(DOCUMENTBUILDERFACTORY_IMPLE_NAME, NokogiriService.class.getClassLoader());
221
+ return factory.newDocumentBuilder().newDocument();
214
222
  } catch (ParserConfigurationException e) {
215
223
  return null; // this will end is disaster...
216
224
  }
@@ -223,18 +231,25 @@ public class XmlDocument extends XmlNode {
223
231
  * Create a new document with +version+ (defaults to "1.0")
224
232
  */
225
233
  @JRubyMethod(name="new", meta = true, rest = true, required=0)
226
- public static IRubyObject rbNew(ThreadContext context, IRubyObject cls, IRubyObject[] args) {
227
- XmlDocument doc = null;
234
+ public static IRubyObject rbNew(ThreadContext context, IRubyObject klazz, IRubyObject[] args) {
235
+ XmlDocument xmlDocument = null;
228
236
  try {
229
237
  Document docNode = createNewDocument();
230
- doc = new XmlDocument(context.getRuntime(), (RubyClass) cls, docNode);
238
+ if ("Nokogiri::HTML::Document".equals(((RubyClass)klazz).getName())) {
239
+ xmlDocument = (XmlDocument) NokogiriService.HTML_DOCUMENT_ALLOCATOR.allocate(context.getRuntime(), (RubyClass) klazz);
240
+ xmlDocument.setNode(context, docNode);
241
+ } else {
242
+ // XML::Document and sublass
243
+ xmlDocument = (XmlDocument) NokogiriService.XML_DOCUMENT_ALLOCATOR.allocate(context.getRuntime(), (RubyClass) klazz);
244
+ xmlDocument.setNode(context, docNode);
245
+ }
231
246
  } catch (Exception ex) {
232
247
  throw context.getRuntime().newRuntimeError("couldn't create document: "+ex.toString());
233
248
  }
234
249
 
235
- RuntimeHelpers.invoke(context, doc, "initialize", args);
250
+ RuntimeHelpers.invoke(context, xmlDocument, "initialize", args);
236
251
 
237
- return doc;
252
+ return xmlDocument;
238
253
  }
239
254
 
240
255
  @JRubyMethod(required=1, optional=4)
@@ -332,6 +347,12 @@ public class XmlDocument extends XmlNode {
332
347
  if (node.getNodeType() == Node.ELEMENT_NODE) {
333
348
  node.setPrefix(null);
334
349
  node.getOwnerDocument().renameNode(node, null, node.getLocalName());
350
+ NamedNodeMap attrs = node.getAttributes();
351
+ for (int i=0; i<attrs.getLength(); i++) {
352
+ Node attr = attrs.item(i);
353
+ attr.setPrefix(null);
354
+ attr.getOwnerDocument().renameNode(attr, null, attr.getLocalName());
355
+ }
335
356
  }
336
357
  XmlNodeSet nodeSet = (XmlNodeSet) xmlNode.children(context);
337
358
  for (long i=0; i < nodeSet.length(); i++) {