nokogiri 1.11.0.rc3-java → 1.11.4-java

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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/LICENSE-DEPENDENCIES.md +1015 -947
  4. data/LICENSE.md +1 -1
  5. data/README.md +168 -91
  6. data/dependencies.yml +12 -12
  7. data/ext/java/nokogiri/EncodingHandler.java +76 -89
  8. data/ext/java/nokogiri/HtmlDocument.java +135 -144
  9. data/ext/java/nokogiri/HtmlElementDescription.java +102 -117
  10. data/ext/java/nokogiri/HtmlEntityLookup.java +33 -60
  11. data/ext/java/nokogiri/HtmlSaxParserContext.java +218 -222
  12. data/ext/java/nokogiri/HtmlSaxPushParser.java +162 -169
  13. data/ext/java/nokogiri/NokogiriService.java +595 -556
  14. data/ext/java/nokogiri/XmlAttr.java +118 -126
  15. data/ext/java/nokogiri/XmlAttributeDecl.java +95 -106
  16. data/ext/java/nokogiri/XmlCdata.java +35 -58
  17. data/ext/java/nokogiri/XmlComment.java +46 -67
  18. data/ext/java/nokogiri/XmlDocument.java +645 -572
  19. data/ext/java/nokogiri/XmlDocumentFragment.java +125 -137
  20. data/ext/java/nokogiri/XmlDtd.java +448 -414
  21. data/ext/java/nokogiri/XmlElement.java +23 -48
  22. data/ext/java/nokogiri/XmlElementContent.java +343 -316
  23. data/ext/java/nokogiri/XmlElementDecl.java +124 -125
  24. data/ext/java/nokogiri/XmlEntityDecl.java +119 -127
  25. data/ext/java/nokogiri/XmlEntityReference.java +49 -72
  26. data/ext/java/nokogiri/XmlNamespace.java +175 -175
  27. data/ext/java/nokogiri/XmlNode.java +1843 -1622
  28. data/ext/java/nokogiri/XmlNodeSet.java +361 -331
  29. data/ext/java/nokogiri/XmlProcessingInstruction.java +47 -69
  30. data/ext/java/nokogiri/XmlReader.java +513 -450
  31. data/ext/java/nokogiri/XmlRelaxng.java +89 -101
  32. data/ext/java/nokogiri/XmlSaxParserContext.java +328 -310
  33. data/ext/java/nokogiri/XmlSaxPushParser.java +227 -220
  34. data/ext/java/nokogiri/XmlSchema.java +335 -242
  35. data/ext/java/nokogiri/XmlSyntaxError.java +113 -119
  36. data/ext/java/nokogiri/XmlText.java +55 -76
  37. data/ext/java/nokogiri/XmlXpathContext.java +242 -210
  38. data/ext/java/nokogiri/XsltStylesheet.java +280 -269
  39. data/ext/java/nokogiri/internals/ClosedStreamException.java +5 -2
  40. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +201 -190
  41. data/ext/java/nokogiri/internals/IgnoreSchemaErrorsErrorHandler.java +17 -10
  42. data/ext/java/nokogiri/internals/NokogiriBlockingQueueInputStream.java +43 -16
  43. data/ext/java/nokogiri/internals/NokogiriDomParser.java +63 -80
  44. data/ext/java/nokogiri/internals/NokogiriEntityResolver.java +107 -88
  45. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +27 -52
  46. data/ext/java/nokogiri/internals/NokogiriHandler.java +316 -286
  47. data/ext/java/nokogiri/internals/NokogiriHelpers.java +736 -652
  48. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +184 -173
  49. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +79 -89
  50. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +64 -79
  51. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +84 -99
  52. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +48 -65
  53. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +119 -78
  54. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +34 -54
  55. data/ext/java/nokogiri/internals/NokogiriXPathVariableResolver.java +23 -46
  56. data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +55 -72
  57. data/ext/java/nokogiri/internals/ParserContext.java +206 -211
  58. data/ext/java/nokogiri/internals/ReaderNode.java +478 -403
  59. data/ext/java/nokogiri/internals/SaveContextVisitor.java +822 -739
  60. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +31 -54
  61. data/ext/java/nokogiri/internals/XalanDTMManagerPatch.java +129 -123
  62. data/ext/java/nokogiri/internals/XmlDeclHandler.java +3 -34
  63. data/ext/java/nokogiri/internals/XmlDomParserContext.java +206 -207
  64. data/ext/java/nokogiri/internals/XmlSaxParser.java +22 -47
  65. data/ext/java/nokogiri/internals/c14n/AttrCompare.java +71 -68
  66. data/ext/java/nokogiri/internals/c14n/C14nHelper.java +137 -118
  67. data/ext/java/nokogiri/internals/c14n/CanonicalFilter.java +27 -21
  68. data/ext/java/nokogiri/internals/c14n/CanonicalizationException.java +74 -61
  69. data/ext/java/nokogiri/internals/c14n/Canonicalizer.java +230 -205
  70. data/ext/java/nokogiri/internals/c14n/Canonicalizer11.java +572 -547
  71. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_OmitComments.java +17 -10
  72. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_WithComments.java +17 -10
  73. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315.java +323 -302
  74. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315Excl.java +232 -219
  75. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclOmitComments.java +22 -15
  76. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclWithComments.java +23 -16
  77. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315OmitComments.java +23 -16
  78. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315WithComments.java +22 -15
  79. data/ext/java/nokogiri/internals/c14n/CanonicalizerBase.java +575 -545
  80. data/ext/java/nokogiri/internals/c14n/CanonicalizerPhysical.java +141 -120
  81. data/ext/java/nokogiri/internals/c14n/CanonicalizerSpi.java +39 -38
  82. data/ext/java/nokogiri/internals/c14n/Constants.java +13 -10
  83. data/ext/java/nokogiri/internals/c14n/ElementProxy.java +279 -247
  84. data/ext/java/nokogiri/internals/c14n/HelperNodeList.java +66 -53
  85. data/ext/java/nokogiri/internals/c14n/IgnoreAllErrorHandler.java +44 -37
  86. data/ext/java/nokogiri/internals/c14n/InclusiveNamespaces.java +135 -120
  87. data/ext/java/nokogiri/internals/c14n/InvalidCanonicalizerException.java +59 -48
  88. data/ext/java/nokogiri/internals/c14n/NameSpaceSymbTable.java +384 -334
  89. data/ext/java/nokogiri/internals/c14n/NodeFilter.java +25 -24
  90. data/ext/java/nokogiri/internals/c14n/UtfHelpper.java +151 -140
  91. data/ext/java/nokogiri/internals/c14n/XMLUtils.java +456 -423
  92. data/ext/java/nokogiri/internals/dom2dtm/DOM2DTM.java +1466 -1500
  93. data/ext/java/nokogiri/internals/dom2dtm/DOM2DTMdefaultNamespaceDeclarationNode.java +626 -574
  94. data/ext/nokogiri/depend +37 -358
  95. data/ext/nokogiri/extconf.rb +581 -374
  96. data/ext/nokogiri/html_document.c +78 -82
  97. data/ext/nokogiri/html_element_description.c +84 -71
  98. data/ext/nokogiri/html_entity_lookup.c +21 -16
  99. data/ext/nokogiri/html_sax_parser_context.c +69 -66
  100. data/ext/nokogiri/html_sax_push_parser.c +42 -34
  101. data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
  102. data/ext/nokogiri/nokogiri.c +192 -93
  103. data/ext/nokogiri/test_global_handlers.c +40 -0
  104. data/ext/nokogiri/xml_attr.c +15 -15
  105. data/ext/nokogiri/xml_attribute_decl.c +18 -18
  106. data/ext/nokogiri/xml_cdata.c +13 -18
  107. data/ext/nokogiri/xml_comment.c +19 -26
  108. data/ext/nokogiri/xml_document.c +246 -188
  109. data/ext/nokogiri/xml_document_fragment.c +13 -15
  110. data/ext/nokogiri/xml_dtd.c +54 -48
  111. data/ext/nokogiri/xml_element_content.c +30 -27
  112. data/ext/nokogiri/xml_element_decl.c +22 -22
  113. data/ext/nokogiri/xml_encoding_handler.c +17 -11
  114. data/ext/nokogiri/xml_entity_decl.c +32 -30
  115. data/ext/nokogiri/xml_entity_reference.c +16 -18
  116. data/ext/nokogiri/xml_namespace.c +56 -49
  117. data/ext/nokogiri/xml_node.c +371 -320
  118. data/ext/nokogiri/xml_node_set.c +168 -156
  119. data/ext/nokogiri/xml_processing_instruction.c +17 -19
  120. data/ext/nokogiri/xml_reader.c +191 -157
  121. data/ext/nokogiri/xml_relax_ng.c +52 -28
  122. data/ext/nokogiri/xml_sax_parser.c +118 -118
  123. data/ext/nokogiri/xml_sax_parser_context.c +103 -86
  124. data/ext/nokogiri/xml_sax_push_parser.c +36 -27
  125. data/ext/nokogiri/xml_schema.c +95 -47
  126. data/ext/nokogiri/xml_syntax_error.c +42 -21
  127. data/ext/nokogiri/xml_text.c +13 -17
  128. data/ext/nokogiri/xml_xpath_context.c +206 -123
  129. data/ext/nokogiri/xslt_stylesheet.c +158 -161
  130. data/lib/nokogiri.rb +3 -7
  131. data/lib/nokogiri/css/parser.rb +3 -3
  132. data/lib/nokogiri/css/parser.y +2 -2
  133. data/lib/nokogiri/css/xpath_visitor.rb +70 -42
  134. data/lib/nokogiri/extension.rb +26 -0
  135. data/lib/nokogiri/html/document.rb +12 -26
  136. data/lib/nokogiri/html/document_fragment.rb +15 -15
  137. data/lib/nokogiri/nokogiri.jar +0 -0
  138. data/lib/nokogiri/version.rb +2 -149
  139. data/lib/nokogiri/version/constant.rb +5 -0
  140. data/lib/nokogiri/version/info.rb +205 -0
  141. data/lib/nokogiri/xml/document.rb +91 -35
  142. data/lib/nokogiri/xml/document_fragment.rb +4 -6
  143. data/lib/nokogiri/xml/node.rb +89 -69
  144. data/lib/nokogiri/xml/parse_options.rb +6 -0
  145. data/lib/nokogiri/xml/reader.rb +2 -9
  146. data/lib/nokogiri/xml/relax_ng.rb +6 -2
  147. data/lib/nokogiri/xml/schema.rb +12 -4
  148. data/lib/nokogiri/xml/searchable.rb +3 -1
  149. data/lib/nokogiri/xml/xpath.rb +1 -3
  150. data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -1
  151. metadata +86 -177
  152. data/ext/nokogiri/html_document.h +0 -10
  153. data/ext/nokogiri/html_element_description.h +0 -10
  154. data/ext/nokogiri/html_entity_lookup.h +0 -8
  155. data/ext/nokogiri/html_sax_parser_context.h +0 -11
  156. data/ext/nokogiri/html_sax_push_parser.h +0 -9
  157. data/ext/nokogiri/nokogiri.h +0 -134
  158. data/ext/nokogiri/xml_attr.h +0 -9
  159. data/ext/nokogiri/xml_attribute_decl.h +0 -9
  160. data/ext/nokogiri/xml_cdata.h +0 -9
  161. data/ext/nokogiri/xml_comment.h +0 -9
  162. data/ext/nokogiri/xml_document.h +0 -23
  163. data/ext/nokogiri/xml_document_fragment.h +0 -10
  164. data/ext/nokogiri/xml_dtd.h +0 -10
  165. data/ext/nokogiri/xml_element_content.h +0 -10
  166. data/ext/nokogiri/xml_element_decl.h +0 -9
  167. data/ext/nokogiri/xml_encoding_handler.h +0 -8
  168. data/ext/nokogiri/xml_entity_decl.h +0 -10
  169. data/ext/nokogiri/xml_entity_reference.h +0 -9
  170. data/ext/nokogiri/xml_io.c +0 -63
  171. data/ext/nokogiri/xml_io.h +0 -11
  172. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
  173. data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
  174. data/ext/nokogiri/xml_namespace.h +0 -14
  175. data/ext/nokogiri/xml_node.h +0 -13
  176. data/ext/nokogiri/xml_node_set.h +0 -12
  177. data/ext/nokogiri/xml_processing_instruction.h +0 -9
  178. data/ext/nokogiri/xml_reader.h +0 -10
  179. data/ext/nokogiri/xml_relax_ng.h +0 -9
  180. data/ext/nokogiri/xml_sax_parser.h +0 -39
  181. data/ext/nokogiri/xml_sax_parser_context.h +0 -10
  182. data/ext/nokogiri/xml_sax_push_parser.h +0 -9
  183. data/ext/nokogiri/xml_schema.h +0 -9
  184. data/ext/nokogiri/xml_syntax_error.h +0 -13
  185. data/ext/nokogiri/xml_text.h +0 -9
  186. data/ext/nokogiri/xml_xpath_context.h +0 -10
  187. data/ext/nokogiri/xslt_stylesheet.h +0 -14
@@ -1,35 +1,3 @@
1
- /**
2
- * (The MIT License)
3
- *
4
- * Copyright (c) 2008 - 2011:
5
- *
6
- * * {Aaron Patterson}[http://tenderlovemaking.com]
7
- * * {Mike Dalessio}[http://mike.daless.io]
8
- * * {Charles Nutter}[http://blog.headius.com]
9
- * * {Sergio Arbeo}[http://www.serabe.com]
10
- * * {Patrick Mahoney}[http://polycrystal.org]
11
- * * {Yoko Harada}[http://yokolet.blogspot.com]
12
- *
13
- * Permission is hereby granted, free of charge, to any person obtaining
14
- * a copy of this software and associated documentation files (the
15
- * 'Software'), to deal in the Software without restriction, including
16
- * without limitation the rights to use, copy, modify, merge, publish,
17
- * distribute, sublicense, and/or sell copies of the Software, and to
18
- * permit persons to whom the Software is furnished to do so, subject to
19
- * the following conditions:
20
- *
21
- * The above copyright notice and this permission notice shall be
22
- * included in all copies or substantial portions of the Software.
23
- *
24
- * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
25
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
28
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
- */
32
-
33
1
  package nokogiri;
34
2
 
35
3
  import static nokogiri.internals.NokogiriHelpers.rubyStringToString;
@@ -52,31 +20,40 @@ import org.w3c.dom.Node;
52
20
  * @author Yoko Harada <yokolet@gmail.com>
53
21
  */
54
22
 
55
- @JRubyClass(name="Nokogiri::XML::CDATA", parent="Nokogiri::XML::Text")
56
- public class XmlCdata extends XmlText {
57
- public XmlCdata(Ruby ruby, RubyClass rubyClass) {
58
- super(ruby, rubyClass);
59
- }
60
-
61
- public XmlCdata(Ruby ruby, RubyClass rubyClass, Node node) {
62
- super(ruby, rubyClass, node);
63
- }
64
-
65
- @Override
66
- protected void init(ThreadContext context, IRubyObject[] args) {
67
- if (args.length < 2) {
68
- throw getRuntime().newArgumentError(args.length, 2);
69
- }
70
- IRubyObject doc = args[0];
71
- content = args[1];
72
- Document document = ((XmlNode) doc).getOwnerDocument();
73
- Node node = document.createCDATASection(rubyStringToString(content));
74
- setNode(context.runtime, node);
75
- }
76
-
77
- @Override
78
- public void accept(ThreadContext context, SaveContextVisitor visitor) {
79
- visitor.enter((CDATASection)node);
80
- visitor.leave((CDATASection)node);
23
+ @JRubyClass(name = "Nokogiri::XML::CDATA", parent = "Nokogiri::XML::Text")
24
+ public class XmlCdata extends XmlText
25
+ {
26
+ public
27
+ XmlCdata(Ruby ruby, RubyClass rubyClass)
28
+ {
29
+ super(ruby, rubyClass);
30
+ }
31
+
32
+ public
33
+ XmlCdata(Ruby ruby, RubyClass rubyClass, Node node)
34
+ {
35
+ super(ruby, rubyClass, node);
36
+ }
37
+
38
+ @Override
39
+ protected void
40
+ init(ThreadContext context, IRubyObject[] args)
41
+ {
42
+ if (args.length < 2) {
43
+ throw getRuntime().newArgumentError(args.length, 2);
81
44
  }
45
+ IRubyObject doc = args[0];
46
+ content = args[1];
47
+ Document document = ((XmlNode) doc).getOwnerDocument();
48
+ Node node = document.createCDATASection(rubyStringToString(content));
49
+ setNode(context.runtime, node);
50
+ }
51
+
52
+ @Override
53
+ public void
54
+ accept(ThreadContext context, SaveContextVisitor visitor)
55
+ {
56
+ visitor.enter((CDATASection)node);
57
+ visitor.leave((CDATASection)node);
58
+ }
82
59
  }
@@ -1,35 +1,3 @@
1
- /**
2
- * (The MIT License)
3
- *
4
- * Copyright (c) 2008 - 2012:
5
- *
6
- * * {Aaron Patterson}[http://tenderlovemaking.com]
7
- * * {Mike Dalessio}[http://mike.daless.io]
8
- * * {Charles Nutter}[http://blog.headius.com]
9
- * * {Sergio Arbeo}[http://www.serabe.com]
10
- * * {Patrick Mahoney}[http://polycrystal.org]
11
- * * {Yoko Harada}[http://yokolet.blogspot.com]
12
- *
13
- * Permission is hereby granted, free of charge, to any person obtaining
14
- * a copy of this software and associated documentation files (the
15
- * 'Software'), to deal in the Software without restriction, including
16
- * without limitation the rights to use, copy, modify, merge, publish,
17
- * distribute, sublicense, and/or sell copies of the Software, and to
18
- * permit persons to whom the Software is furnished to do so, subject to
19
- * the following conditions:
20
- *
21
- * The above copyright notice and this permission notice shall be
22
- * included in all copies or substantial portions of the Software.
23
- *
24
- * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
25
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
28
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
- */
32
-
33
1
  package nokogiri;
34
2
 
35
3
  import static nokogiri.internals.NokogiriHelpers.rubyStringToString;
@@ -51,47 +19,58 @@ import org.w3c.dom.Node;
51
19
  * @author Yoko Harada <yokolet@gmail.com>
52
20
  */
53
21
 
54
- @JRubyClass(name="Nokogiri::XML::Comment", parent="Nokogiri::XML::CharacterData")
55
- public class XmlComment extends XmlNode {
56
- public XmlComment(Ruby ruby, RubyClass rubyClass, Node node) {
57
- super(ruby, rubyClass, node);
58
- }
22
+ @JRubyClass(name = "Nokogiri::XML::Comment", parent = "Nokogiri::XML::CharacterData")
23
+ public class XmlComment extends XmlNode
24
+ {
25
+ public
26
+ XmlComment(Ruby ruby, RubyClass rubyClass, Node node)
27
+ {
28
+ super(ruby, rubyClass, node);
29
+ }
30
+
31
+ public
32
+ XmlComment(Ruby runtime, RubyClass klass)
33
+ {
34
+ super(runtime, klass);
35
+ }
59
36
 
60
- public XmlComment(Ruby runtime, RubyClass klass) {
61
- super(runtime, klass);
37
+ @Override
38
+ protected void
39
+ init(ThreadContext context, IRubyObject[] args)
40
+ {
41
+ if (args.length < 2) {
42
+ throw getRuntime().newArgumentError(args.length, 2);
62
43
  }
63
44
 
64
- @Override
65
- protected void init(ThreadContext context, IRubyObject[] args) {
66
- if (args.length < 2)
67
- throw getRuntime().newArgumentError(args.length, 2);
45
+ IRubyObject doc = args[0];
46
+ IRubyObject text = args[1];
68
47
 
69
- IRubyObject doc = args[0];
70
- IRubyObject text = args[1];
48
+ XmlDocument xmlDoc;
49
+ if (doc instanceof XmlDocument) {
50
+ xmlDoc = (XmlDocument) doc;
71
51
 
72
- XmlDocument xmlDoc;
73
- if (doc instanceof XmlDocument) {
74
- xmlDoc = (XmlDocument) doc;
75
-
76
- } else if (doc instanceof XmlNode) {
77
- XmlNode xmlNode = (XmlNode) doc;
78
- xmlDoc = (XmlDocument)xmlNode.document(context);
79
- } else {
80
- throw getRuntime().newArgumentError("first argument must be a XML::Document or XML::Node");
81
- }
82
- if (xmlDoc != null) {
83
- Document document = xmlDoc.getDocument();
84
- Node node = document.createComment(rubyStringToString(text));
85
- setNode(context.runtime, node);
86
- }
52
+ } else if (doc instanceof XmlNode) {
53
+ XmlNode xmlNode = (XmlNode) doc;
54
+ xmlDoc = (XmlDocument)xmlNode.document(context);
55
+ } else {
56
+ throw getRuntime().newArgumentError("first argument must be a XML::Document or XML::Node");
87
57
  }
58
+ if (xmlDoc != null) {
59
+ Document document = xmlDoc.getDocument();
60
+ Node node = document.createComment(rubyStringToString(text));
61
+ setNode(context.runtime, node);
62
+ }
63
+ }
88
64
 
89
- @Override
90
- public boolean isComment() { return true; }
65
+ @Override
66
+ public boolean
67
+ isComment() { return true; }
91
68
 
92
- @Override
93
- public void accept(ThreadContext context, SaveContextVisitor visitor) {
94
- visitor.enter((Comment)node);
95
- visitor.leave((Comment)node);
96
- }
69
+ @Override
70
+ public void
71
+ accept(ThreadContext context, SaveContextVisitor visitor)
72
+ {
73
+ visitor.enter((Comment)node);
74
+ visitor.leave((Comment)node);
75
+ }
97
76
  }
@@ -1,35 +1,3 @@
1
- /**
2
- * (The MIT License)
3
- *
4
- * Copyright (c) 2008 - 2014:
5
- *
6
- * * {Aaron Patterson}[http://tenderlovemaking.com]
7
- * * {Mike Dalessio}[http://mike.daless.io]
8
- * * {Charles Nutter}[http://blog.headius.com]
9
- * * {Sergio Arbeo}[http://www.serabe.com]
10
- * * {Patrick Mahoney}[http://polycrystal.org]
11
- * * {Yoko Harada}[http://yokolet.blogspot.com]
12
- *
13
- * Permission is hereby granted, free of charge, to any person obtaining
14
- * a copy of this software and associated documentation files (the
15
- * 'Software'), to deal in the Software without restriction, including
16
- * without limitation the rights to use, copy, modify, merge, publish,
17
- * distribute, sublicense, and/or sell copies of the Software, and to
18
- * permit persons to whom the Software is furnished to do so, subject to
19
- * the following conditions:
20
- *
21
- * The above copyright notice and this permission notice shall be
22
- * included in all copies or substantial portions of the Software.
23
- *
24
- * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
25
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
28
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
- */
32
-
33
1
  package nokogiri;
34
2
 
35
3
  import static nokogiri.internals.NokogiriHelpers.clearXpathContext;
@@ -84,550 +52,655 @@ import nokogiri.internals.c14n.Canonicalizer;
84
52
  * @author John Shahid <jvshahid@gmail.com>
85
53
  */
86
54
 
87
- @JRubyClass(name="Nokogiri::XML::Document", parent="Nokogiri::XML::Node")
88
- public class XmlDocument extends XmlNode {
89
- private NokogiriNamespaceCache nsCache;
90
-
91
- /* UserData keys for storing extra info in the document node. */
92
- public final static String DTD_RAW_DOCUMENT = "DTD_RAW_DOCUMENT";
93
- public final static String DTD_INTERNAL_SUBSET = "DTD_INTERNAL_SUBSET";
94
- public final static String DTD_EXTERNAL_SUBSET = "DTD_EXTERNAL_SUBSET";
95
-
96
- /* DocumentBuilderFactory implementation class name. This needs to set a classloader into it.
97
- * Setting an appropriate classloader resolves issue 380.
98
- */
99
- private static final String DOCUMENTBUILDERFACTORY_IMPLE_NAME = "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
100
-
101
- private static final ByteList DOCUMENT = ByteList.create("document");
102
- static { DOCUMENT.setEncoding(USASCIIEncoding.INSTANCE); }
103
-
104
- private static boolean substituteEntities = false;
105
- private static boolean loadExternalSubset = false; // TODO: Verify this.
106
-
107
- /** cache variables */
108
- protected IRubyObject encoding;
109
- protected IRubyObject url;
110
-
111
- public XmlDocument(Ruby runtime, RubyClass klazz) {
112
- super(runtime, klazz, createNewDocument(runtime));
113
- }
114
-
115
- public XmlDocument(Ruby runtime, Document document) {
116
- this(runtime, getNokogiriClass(runtime, "Nokogiri::XML::Document"), document);
117
- }
118
-
119
- public XmlDocument(Ruby runtime, RubyClass klass, Document document) {
120
- super(runtime, klass, document);
121
- init(runtime, document);
122
- }
123
-
124
- void init(Ruby runtime, Document document) {
125
- stabilizeTextContent(document);
126
- if (document.getDocumentElement() != null) {
127
- createAndCacheNamespaces(runtime, document.getDocumentElement());
128
- }
129
- setInstanceVariable("@decorators", runtime.getNil());
130
- }
131
-
132
- public final void setDocumentNode(Ruby runtime, Document node) {
133
- super.setNode(runtime, node);
134
- if (node != null) init(runtime, node);
135
- else setInstanceVariable("@decorators", runtime.getNil());
136
- }
137
-
138
- public void setEncoding(IRubyObject encoding) {
139
- this.encoding = encoding;
140
- }
141
-
142
- public IRubyObject getEncoding() {
143
- return encoding;
144
- }
145
-
146
- // not sure, but like attribute values, text value will be lost
147
- // unless it is referred once before this document is used.
148
- // this seems to happen only when the fragment is parsed from Node#in_context.
149
- protected static void stabilizeTextContent(Document document) {
150
- if (document.getDocumentElement() != null) document.getDocumentElement().getTextContent();
151
- }
152
-
153
- private static void createAndCacheNamespaces(Ruby runtime, Node node) {
154
- if (node.hasAttributes()) {
155
- NamedNodeMap nodeMap = node.getAttributes();
156
- for (int i=0; i<nodeMap.getLength(); i++) {
157
- Node n = nodeMap.item(i);
158
- if (n instanceof Attr) {
159
- Attr attr = (Attr) n;
160
- stabilizeAttr(attr);
161
- if (isNamespace(attr.getName())) {
162
- // create and cache
163
- XmlNamespace.createFromAttr(runtime, attr);
164
- }
165
- }
166
- }
167
- }
168
- NodeList children = node.getChildNodes();
169
- for (int i=0; i<children.getLength(); i++) {
170
- createAndCacheNamespaces(runtime, children.item(i));
171
- }
172
- }
173
-
174
- static void stabilizeAttr(final Attr attr) {
175
- // TODO not sure, but need to get value always before document is referred or lose attribute value
176
- attr.getValue(); // don't delete this line
177
- }
178
-
179
- // When a document is created from fragment with a context (reference) document,
180
- // namespace should be resolved based on the context document.
181
- public XmlDocument(Ruby ruby, RubyClass klass, Document document, XmlDocument contextDoc) {
182
- super(ruby, klass, document);
183
- nsCache = contextDoc.getNamespaceCache();
184
- String default_href = nsCache.getDefault().getHref();
185
- resolveNamespaceIfNecessary(document.getDocumentElement(), default_href);
186
- }
187
-
188
- private void resolveNamespaceIfNecessary(Node node, String default_href) {
189
- if (node == null) return;
190
- String nodePrefix = node.getPrefix();
191
- if (nodePrefix == null) { // default namespace
192
- NokogiriHelpers.renameNode(node, default_href, node.getNodeName());
193
- } else {
194
- String href = getNamespaceCache().get(node, nodePrefix).getHref();
195
- NokogiriHelpers.renameNode(node, href, node.getNodeName());
196
- }
197
- resolveNamespaceIfNecessary(node.getNextSibling(), default_href);
198
- NodeList children = node.getChildNodes();
199
- for (int i=0; i<children.getLength(); i++) {
200
- resolveNamespaceIfNecessary(children.item(i), default_href);
201
- }
202
- }
203
-
204
- public NokogiriNamespaceCache getNamespaceCache() {
205
- if (nsCache == null) nsCache = new NokogiriNamespaceCache();
206
- return nsCache;
207
- }
208
-
209
- public Document getDocument() {
210
- return (Document) node;
211
- }
212
-
213
- @Override
214
- protected IRubyObject getNodeName(ThreadContext context) {
215
- if (name == null) name = RubyString.newStringShared(context.runtime, DOCUMENT);
216
- return name;
217
- }
218
-
219
- public void setUrl(IRubyObject url) {
220
- this.url = url;
221
- }
222
-
223
- protected IRubyObject getUrl() {
224
- return this.url;
225
- }
226
-
227
- @JRubyMethod
228
- public IRubyObject url(ThreadContext context) {
229
- return getUrl();
230
- }
231
-
232
- public static Document createNewDocument(final Ruby runtime) {
233
- try {
234
- return DocumentBuilderFactoryHolder.INSTANCE.newDocumentBuilder().newDocument();
235
- } catch (ParserConfigurationException e) {
236
- throw asRuntimeError(runtime, null, e);
237
- }
238
- }
239
-
240
- private static class DocumentBuilderFactoryHolder {
241
- static final DocumentBuilderFactory INSTANCE;
242
- static {
243
- INSTANCE = DocumentBuilderFactory.newInstance(DOCUMENTBUILDERFACTORY_IMPLE_NAME, NokogiriService.class.getClassLoader());
244
- }
245
- }
246
-
247
- static RaiseException asRuntimeError(Ruby runtime, String message, Exception cause) {
248
- if (cause instanceof RaiseException) return (RaiseException) cause;
249
-
250
- if (message == null) message = cause.toString();
251
- else message = message + '(' + cause.toString() + ')';
252
- RaiseException ex = runtime.newRuntimeError(message);
253
- ex.initCause(cause);
254
- return ex;
255
- }
256
-
257
- /*
258
- * call-seq:
259
- * new(version = default)
260
- *
261
- * Create a new document with +version+ (defaults to "1.0")
262
- */
263
- @JRubyMethod(name="new", meta = true, rest = true, required=0)
264
- public static IRubyObject rbNew(ThreadContext context, IRubyObject klazz, IRubyObject[] args) {
265
- final Ruby runtime = context.runtime;
266
- XmlDocument xmlDocument;
267
- try {
268
- Document docNode = createNewDocument(runtime);
269
- if ("Nokogiri::HTML::Document".equals(((RubyClass)klazz).getName())) {
270
- xmlDocument = new HtmlDocument(context.runtime, (RubyClass) klazz, docNode);
271
- } else {
272
- xmlDocument = new XmlDocument(context.runtime, (RubyClass) klazz, docNode);
273
- }
274
- } catch (Exception ex) {
275
- throw asRuntimeError(runtime, "couldn't create document: ", ex);
276
- }
277
-
278
- Helpers.invoke(context, xmlDocument, "initialize", args);
279
-
280
- return xmlDocument;
281
- }
282
-
283
- @JRubyMethod(required=1, optional=4)
284
- public IRubyObject create_entity(ThreadContext context, IRubyObject[] argv) {
285
- // FIXME: Entity node should be create by some right way.
286
- // this impl passes tests, but entity doesn't exists in DTD, which
287
- // would cause validation failure.
288
- if (argv.length == 0) throw context.runtime.newRuntimeError("Could not create entity");
289
- String tagName = rubyStringToString(argv[0]);
290
- Node node = getOwnerDocument().createElement(tagName);
291
- return XmlEntityDecl.create(context, node, argv);
292
- }
293
-
294
- @Override
295
- XmlDocument document(Ruby runtime) {
296
- return this;
297
- }
298
-
299
- @JRubyMethod(name="encoding=")
300
- public IRubyObject encoding_set(IRubyObject encoding) {
301
- this.encoding = encoding;
302
- return this;
303
- }
304
-
305
- @JRubyMethod
306
- public IRubyObject encoding(ThreadContext context) {
307
- if (this.encoding == null || this.encoding.isNil()) {
308
- final String enc = getDocument().getXmlEncoding();
309
- if (enc == null) {
310
- this.encoding = context.nil;
311
- } else {
312
- this.encoding = context.runtime.newString(enc);
313
- }
55
+ @JRubyClass(name = "Nokogiri::XML::Document", parent = "Nokogiri::XML::Node")
56
+ public class XmlDocument extends XmlNode
57
+ {
58
+ private NokogiriNamespaceCache nsCache;
59
+
60
+ /* UserData keys for storing extra info in the document node. */
61
+ public final static String DTD_RAW_DOCUMENT = "DTD_RAW_DOCUMENT";
62
+ public final static String DTD_INTERNAL_SUBSET = "DTD_INTERNAL_SUBSET";
63
+ public final static String DTD_EXTERNAL_SUBSET = "DTD_EXTERNAL_SUBSET";
64
+
65
+ /* DocumentBuilderFactory implementation class name. This needs to set a classloader into it.
66
+ * Setting an appropriate classloader resolves issue 380.
67
+ */
68
+ private static final String DOCUMENTBUILDERFACTORY_IMPLE_NAME = "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
69
+
70
+ private static final ByteList DOCUMENT = ByteList.create("document");
71
+ static { DOCUMENT.setEncoding(USASCIIEncoding.INSTANCE); }
72
+
73
+ private static boolean substituteEntities = false;
74
+ private static boolean loadExternalSubset = false; // TODO: Verify this.
75
+
76
+ /** cache variables */
77
+ protected IRubyObject encoding;
78
+ protected IRubyObject url;
79
+
80
+ public
81
+ XmlDocument(Ruby runtime, RubyClass klazz)
82
+ {
83
+ super(runtime, klazz, createNewDocument(runtime));
84
+ }
85
+
86
+ public
87
+ XmlDocument(Ruby runtime, Document document)
88
+ {
89
+ this(runtime, getNokogiriClass(runtime, "Nokogiri::XML::Document"), document);
90
+ }
91
+
92
+ public
93
+ XmlDocument(Ruby runtime, RubyClass klass, Document document)
94
+ {
95
+ super(runtime, klass, document);
96
+ init(runtime, document);
97
+ }
98
+
99
+ void
100
+ init(Ruby runtime, Document document)
101
+ {
102
+ stabilizeTextContent(document);
103
+ if (document.getDocumentElement() != null) {
104
+ createAndCacheNamespaces(runtime, document.getDocumentElement());
105
+ }
106
+ setInstanceVariable("@decorators", runtime.getNil());
107
+ }
108
+
109
+ public final void
110
+ setDocumentNode(Ruby runtime, Document node)
111
+ {
112
+ super.setNode(runtime, node);
113
+ if (node != null) { init(runtime, node); }
114
+ else { setInstanceVariable("@decorators", runtime.getNil()); }
115
+ }
116
+
117
+ public void
118
+ setEncoding(IRubyObject encoding)
119
+ {
120
+ this.encoding = encoding;
121
+ }
122
+
123
+ public IRubyObject
124
+ getEncoding()
125
+ {
126
+ return encoding;
127
+ }
128
+
129
+ // not sure, but like attribute values, text value will be lost
130
+ // unless it is referred once before this document is used.
131
+ // this seems to happen only when the fragment is parsed from Node#in_context.
132
+ protected static void
133
+ stabilizeTextContent(Document document)
134
+ {
135
+ if (document.getDocumentElement() != null) { document.getDocumentElement().getTextContent(); }
136
+ }
137
+
138
+ private static void
139
+ createAndCacheNamespaces(Ruby runtime, Node node)
140
+ {
141
+ if (node.hasAttributes()) {
142
+ NamedNodeMap nodeMap = node.getAttributes();
143
+ for (int i = 0; i < nodeMap.getLength(); i++) {
144
+ Node n = nodeMap.item(i);
145
+ if (n instanceof Attr) {
146
+ Attr attr = (Attr) n;
147
+ stabilizeAttr(attr);
148
+ if (isNamespace(attr.getName())) {
149
+ // create and cache
150
+ XmlNamespace.createFromAttr(runtime, attr);
151
+ }
314
152
  }
315
-
316
- return this.encoding.isNil() ? this.encoding : this.encoding.asString().encode(context, context.getRuntime().newString("UTF-8"));
317
- }
318
-
319
- @JRubyMethod(meta = true)
320
- public static IRubyObject load_external_subsets_set(ThreadContext context, IRubyObject cls, IRubyObject value) {
321
- XmlDocument.loadExternalSubset = value.isTrue();
322
- return context.nil;
323
- }
324
-
325
- @JRubyMethod(meta = true, required = 4)
326
- public static IRubyObject read_io(ThreadContext context, IRubyObject klass, IRubyObject[] args) {
327
- XmlDomParserContext ctx = new XmlDomParserContext(context.runtime, args[2], args[3]);
328
- ctx.setIOInputSource(context, args[0], args[1]);
329
- return ctx.parse(context, (RubyClass) klass, args[1]);
330
- }
331
-
332
- @JRubyMethod(meta = true, required = 4)
333
- public static IRubyObject read_memory(ThreadContext context, IRubyObject klass, IRubyObject[] args) {
334
- XmlDomParserContext ctx = new XmlDomParserContext(context.runtime, args[2], args[3]);
335
- ctx.setStringInputSource(context, args[0], args[1]);
336
- return ctx.parse(context, (RubyClass) klass, args[1]);
337
- }
338
-
339
- @JRubyMethod(name="remove_namespaces!")
340
- public IRubyObject remove_namespaces(ThreadContext context) {
341
- removeNamespaceRecursively(this);
342
- if (nsCache != null) nsCache.clear();
343
- clearXpathContext(getNode());
344
- return this;
345
- }
346
-
347
- private void removeNamespaceRecursively(XmlNode xmlNode) {
348
- Node node = xmlNode.node;
349
- if (node.getNodeType() == Node.ELEMENT_NODE) {
350
- node.setPrefix(null);
351
- NokogiriHelpers.renameNode(node, null, node.getLocalName());
352
- NamedNodeMap attrs = node.getAttributes();
353
- for (int i=0; i<attrs.getLength(); i++) {
354
- Attr attr = (Attr) attrs.item(i);
355
- if (isNamespace(attr.getNodeName())) {
356
- ((org.w3c.dom.Element) node).removeAttributeNode(attr);
357
- } else {
358
- attr.setPrefix(null);
359
- NokogiriHelpers.renameNode(attr, null, attr.getLocalName());
360
- }
361
- }
362
- }
363
- IRubyObject[] nodes = xmlNode.getChildren();
364
- for (int i=0; i < nodes.length; i++) {
365
- XmlNode childNode = (XmlNode) nodes[i];
366
- removeNamespaceRecursively(childNode);
367
- }
368
- }
369
-
370
- @JRubyMethod
371
- public IRubyObject root(ThreadContext context) {
372
- Node rootNode = getDocument().getDocumentElement();
373
- if (rootNode == null) return context.nil;
374
-
375
- Object invalid = rootNode.getUserData(NokogiriHelpers.ROOT_NODE_INVALID);
376
- if (invalid != null && ((Boolean) invalid)) return context.nil;
377
-
378
- return getCachedNodeOrCreate(context.runtime, rootNode);
379
- }
380
-
381
- protected IRubyObject dup_implementation(Ruby runtime, boolean deep) {
382
- XmlDocument doc = (XmlDocument) super.dup_implementation(runtime, deep);
383
- // Avoid creating a new XmlDocument since we cloned one
384
- // already. Otherwise the following test will fail:
385
- //
386
- // dup = doc.dup
387
- // dup.equal?(dup.children[0].document)
388
- //
389
- // Since `dup.children[0].document' will end up creating a new
390
- // XmlDocument. See #1060.
391
- doc.resetCache();
392
- return doc;
393
- }
394
-
395
- @JRubyMethod(name="root=")
396
- public IRubyObject root_set(ThreadContext context, IRubyObject new_root) {
397
- // in case of document fragment, temporary root node should be deleted.
398
-
399
- // Java can't have a root whose value is null. Instead of setting null,
400
- // the method sets user data so that other methods are able to know the root
401
- // should be nil.
402
- if (new_root == context.nil) {
403
- getDocument().getDocumentElement().setUserData(NokogiriHelpers.ROOT_NODE_INVALID, Boolean.TRUE, null);
404
- return new_root;
405
- }
406
- XmlNode newRoot = asXmlNode(context, new_root);
407
-
408
- IRubyObject root = root(context);
409
- if (root.isNil()) {
410
- Node newRootNode;
411
- if (getDocument() == newRoot.getOwnerDocument()) {
412
- newRootNode = newRoot.node;
413
- } else {
414
- // must copy otherwise newRoot may exist in two places
415
- // with different owner document.
416
- newRootNode = getDocument().importNode(newRoot.node, true);
417
- }
418
- add_child_node(context, getCachedNodeOrCreate(context.runtime, newRootNode));
153
+ }
154
+ }
155
+ NodeList children = node.getChildNodes();
156
+ for (int i = 0; i < children.getLength(); i++) {
157
+ createAndCacheNamespaces(runtime, children.item(i));
158
+ }
159
+ }
160
+
161
+ static void
162
+ stabilizeAttr(final Attr attr)
163
+ {
164
+ // TODO not sure, but need to get value always before document is referred or lose attribute value
165
+ attr.getValue(); // don't delete this line
166
+ }
167
+
168
+ // When a document is created from fragment with a context (reference) document,
169
+ // namespace should be resolved based on the context document.
170
+ public
171
+ XmlDocument(Ruby ruby, RubyClass klass, Document document, XmlDocument contextDoc)
172
+ {
173
+ super(ruby, klass, document);
174
+ nsCache = contextDoc.getNamespaceCache();
175
+ String default_href = nsCache.getDefault().getHref();
176
+ resolveNamespaceIfNecessary(document.getDocumentElement(), default_href);
177
+ }
178
+
179
+ private void
180
+ resolveNamespaceIfNecessary(Node node, String default_href)
181
+ {
182
+ if (node == null) { return; }
183
+ String nodePrefix = node.getPrefix();
184
+ if (nodePrefix == null) { // default namespace
185
+ NokogiriHelpers.renameNode(node, default_href, node.getNodeName());
186
+ } else {
187
+ String href = getNamespaceCache().get(node, nodePrefix).getHref();
188
+ NokogiriHelpers.renameNode(node, href, node.getNodeName());
189
+ }
190
+ resolveNamespaceIfNecessary(node.getNextSibling(), default_href);
191
+ NodeList children = node.getChildNodes();
192
+ for (int i = 0; i < children.getLength(); i++) {
193
+ resolveNamespaceIfNecessary(children.item(i), default_href);
194
+ }
195
+ }
196
+
197
+ public NokogiriNamespaceCache
198
+ getNamespaceCache()
199
+ {
200
+ if (nsCache == null) { nsCache = new NokogiriNamespaceCache(); }
201
+ return nsCache;
202
+ }
203
+
204
+ public Document
205
+ getDocument()
206
+ {
207
+ return (Document) node;
208
+ }
209
+
210
+ @Override
211
+ protected IRubyObject
212
+ getNodeName(ThreadContext context)
213
+ {
214
+ if (name == null) { name = RubyString.newStringShared(context.runtime, DOCUMENT); }
215
+ return name;
216
+ }
217
+
218
+ public void
219
+ setUrl(IRubyObject url)
220
+ {
221
+ this.url = url;
222
+ }
223
+
224
+ protected IRubyObject
225
+ getUrl()
226
+ {
227
+ return this.url;
228
+ }
229
+
230
+ @JRubyMethod
231
+ public IRubyObject
232
+ url(ThreadContext context)
233
+ {
234
+ return getUrl();
235
+ }
236
+
237
+ public static Document
238
+ createNewDocument(final Ruby runtime)
239
+ {
240
+ try {
241
+ return DocumentBuilderFactoryHolder.INSTANCE.newDocumentBuilder().newDocument();
242
+ } catch (ParserConfigurationException e) {
243
+ throw asRuntimeError(runtime, null, e);
244
+ }
245
+ }
246
+
247
+ private static class DocumentBuilderFactoryHolder
248
+ {
249
+ static final DocumentBuilderFactory INSTANCE;
250
+ static
251
+ {
252
+ INSTANCE = DocumentBuilderFactory.newInstance(DOCUMENTBUILDERFACTORY_IMPLE_NAME,
253
+ NokogiriService.class.getClassLoader());
254
+ }
255
+ }
256
+
257
+ static RaiseException
258
+ asRuntimeError(Ruby runtime, String message, Exception cause)
259
+ {
260
+ if (cause instanceof RaiseException) { return (RaiseException) cause; }
261
+
262
+ if (message == null) { message = cause.toString(); }
263
+ else { message = message + '(' + cause.toString() + ')'; }
264
+ RaiseException ex = runtime.newRuntimeError(message);
265
+ ex.initCause(cause);
266
+ return ex;
267
+ }
268
+
269
+ /*
270
+ * call-seq:
271
+ * new(version = default)
272
+ *
273
+ * Create a new document with +version+ (defaults to "1.0")
274
+ */
275
+ @JRubyMethod(name = "new", meta = true, rest = true, required = 0)
276
+ public static IRubyObject
277
+ rbNew(ThreadContext context, IRubyObject klazz, IRubyObject[] args)
278
+ {
279
+ final Ruby runtime = context.runtime;
280
+ XmlDocument xmlDocument;
281
+ try {
282
+ Document docNode = createNewDocument(runtime);
283
+ if ("Nokogiri::HTML::Document".equals(((RubyClass)klazz).getName())) {
284
+ xmlDocument = new HtmlDocument(context.runtime, (RubyClass) klazz, docNode);
285
+ } else {
286
+ xmlDocument = new XmlDocument(context.runtime, (RubyClass) klazz, docNode);
287
+ }
288
+ } catch (Exception ex) {
289
+ throw asRuntimeError(runtime, "couldn't create document: ", ex);
290
+ }
291
+
292
+ Helpers.invoke(context, xmlDocument, "initialize", args);
293
+
294
+ return xmlDocument;
295
+ }
296
+
297
+ @JRubyMethod(required = 1, optional = 4)
298
+ public IRubyObject
299
+ create_entity(ThreadContext context, IRubyObject[] argv)
300
+ {
301
+ // FIXME: Entity node should be create by some right way.
302
+ // this impl passes tests, but entity doesn't exists in DTD, which
303
+ // would cause validation failure.
304
+ if (argv.length == 0) { throw context.runtime.newRuntimeError("Could not create entity"); }
305
+ String tagName = rubyStringToString(argv[0]);
306
+ Node node = getOwnerDocument().createElement(tagName);
307
+ return XmlEntityDecl.create(context, node, argv);
308
+ }
309
+
310
+ @Override
311
+ XmlDocument
312
+ document(Ruby runtime)
313
+ {
314
+ return this;
315
+ }
316
+
317
+ @JRubyMethod(name = "encoding=")
318
+ public IRubyObject
319
+ encoding_set(IRubyObject encoding)
320
+ {
321
+ this.encoding = encoding;
322
+ return this;
323
+ }
324
+
325
+ @JRubyMethod
326
+ public IRubyObject
327
+ encoding(ThreadContext context)
328
+ {
329
+ if (this.encoding == null || this.encoding.isNil()) {
330
+ final String enc = getDocument().getXmlEncoding();
331
+ if (enc == null) {
332
+ this.encoding = context.nil;
333
+ } else {
334
+ this.encoding = context.runtime.newString(enc);
335
+ }
336
+ }
337
+
338
+ return this.encoding.isNil() ? this.encoding : this.encoding.asString().encode(context,
339
+ context.getRuntime().newString("UTF-8"));
340
+ }
341
+
342
+ @JRubyMethod(meta = true)
343
+ public static IRubyObject
344
+ load_external_subsets_set(ThreadContext context, IRubyObject cls, IRubyObject value)
345
+ {
346
+ XmlDocument.loadExternalSubset = value.isTrue();
347
+ return context.nil;
348
+ }
349
+
350
+ @JRubyMethod(meta = true, required = 4)
351
+ public static IRubyObject
352
+ read_io(ThreadContext context, IRubyObject klass, IRubyObject[] args)
353
+ {
354
+ XmlDomParserContext ctx = new XmlDomParserContext(context.runtime, args[2], args[3]);
355
+ ctx.setIOInputSource(context, args[0], args[1]);
356
+ return ctx.parse(context, (RubyClass) klass, args[1]);
357
+ }
358
+
359
+ @JRubyMethod(meta = true, required = 4)
360
+ public static IRubyObject
361
+ read_memory(ThreadContext context, IRubyObject klass, IRubyObject[] args)
362
+ {
363
+ XmlDomParserContext ctx = new XmlDomParserContext(context.runtime, args[2], args[3]);
364
+ ctx.setStringInputSource(context, args[0], args[1]);
365
+ return ctx.parse(context, (RubyClass) klass, args[1]);
366
+ }
367
+
368
+ @JRubyMethod(name = "remove_namespaces!")
369
+ public IRubyObject
370
+ remove_namespaces(ThreadContext context)
371
+ {
372
+ removeNamespaceRecursively(this);
373
+ if (nsCache != null) { nsCache.clear(); }
374
+ clearXpathContext(getNode());
375
+ return this;
376
+ }
377
+
378
+ private void
379
+ removeNamespaceRecursively(XmlNode xmlNode)
380
+ {
381
+ Node node = xmlNode.node;
382
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
383
+ node.setPrefix(null);
384
+ NokogiriHelpers.renameNode(node, null, node.getLocalName());
385
+ NamedNodeMap attrs = node.getAttributes();
386
+ for (int i = 0; i < attrs.getLength(); i++) {
387
+ Attr attr = (Attr) attrs.item(i);
388
+ if (isNamespace(attr.getNodeName())) {
389
+ ((org.w3c.dom.Element) node).removeAttributeNode(attr);
419
390
  } else {
420
- Node rootNode = asXmlNode(context, root).node;
421
- ((XmlNode) getCachedNodeOrCreate(context.runtime, rootNode)).replace_node(context, newRoot);
391
+ attr.setPrefix(null);
392
+ NokogiriHelpers.renameNode(attr, null, attr.getLocalName());
422
393
  }
423
-
424
- return newRoot;
425
- }
426
-
427
- @JRubyMethod
428
- public IRubyObject version(ThreadContext context) {
429
- return stringOrNil(context.runtime, getDocument().getXmlVersion());
430
- }
431
-
432
- @JRubyMethod(meta = true)
433
- public static IRubyObject substitute_entities_set(ThreadContext context, IRubyObject cls, IRubyObject value) {
434
- XmlDocument.substituteEntities = value.isTrue();
435
- return context.nil;
436
- }
437
-
438
- public IRubyObject getInternalSubset(ThreadContext context) {
439
- IRubyObject dtd = (IRubyObject) node.getUserData(DTD_INTERNAL_SUBSET);
440
-
441
- if (dtd == null) {
442
- Document document = getDocument();
443
- if (document.getUserData(XmlDocument.DTD_RAW_DOCUMENT) != null) {
444
- dtd = XmlDtd.newFromInternalSubset(context.runtime, document);
445
- } else if (document.getDoctype() != null) {
446
- DocumentType docType = document.getDoctype();
447
- IRubyObject name, publicId, systemId;
448
- name = publicId = systemId = context.nil;
449
- if (docType.getName() != null) {
450
- name = context.runtime.newString(docType.getName());
451
- }
452
- if (docType.getPublicId() != null) {
453
- publicId = context.runtime.newString(docType.getPublicId());
454
- }
455
- if (docType.getSystemId() != null) {
456
- systemId = context.runtime.newString(docType.getSystemId());
457
- }
458
- dtd = XmlDtd.newEmpty(context.runtime, document, name, publicId, systemId);
459
- } else {
460
- dtd = context.nil;
461
- }
462
-
463
- setInternalSubset(dtd);
464
- }
465
-
466
- return dtd;
467
- }
468
-
469
- /**
470
- * Assumes XmlNode#internal_subset() has returned nil. (i.e. there
471
- * is not already an internal subset).
472
- */
473
- public IRubyObject createInternalSubset(ThreadContext context,
474
- IRubyObject name,
475
- IRubyObject external_id,
476
- IRubyObject system_id) {
477
- XmlDtd dtd = XmlDtd.newEmpty(context.runtime, getDocument(), name, external_id, system_id);
478
- setInternalSubset(dtd);
479
- return dtd;
480
- }
481
-
482
- protected void setInternalSubset(IRubyObject data) {
483
- node.setUserData(DTD_INTERNAL_SUBSET, data, null);
484
- }
485
-
486
- public IRubyObject getExternalSubset(ThreadContext context) {
487
- IRubyObject dtd = (IRubyObject) node.getUserData(DTD_EXTERNAL_SUBSET);
488
-
489
- if (dtd == null) return context.nil;
490
- return dtd;
491
- }
492
-
493
- /**
494
- * Assumes XmlNode#external_subset() has returned nil. (i.e. there
495
- * is not already an external subset).
496
- */
497
- public IRubyObject createExternalSubset(ThreadContext context,
498
- IRubyObject name,
499
- IRubyObject external_id,
500
- IRubyObject system_id) {
501
- XmlDtd dtd = XmlDtd.newEmpty(context.runtime, getDocument(), name, external_id, system_id);
502
- setExternalSubset(dtd);
503
- return dtd;
504
- }
505
-
506
- protected void setExternalSubset(IRubyObject data) {
507
- node.setUserData(DTD_EXTERNAL_SUBSET, data, null);
508
- }
509
-
510
- @Override
511
- public void accept(ThreadContext context, SaveContextVisitor visitor) {
512
- Document document = getDocument();
513
- visitor.enter(document);
514
- NodeList children = document.getChildNodes();
515
- for (int i=0; i<children.getLength(); i++) {
516
- Node child = children.item(i);
517
- short type = child.getNodeType();
518
- if (type == Node.COMMENT_NODE) {
519
- XmlComment xmlComment = (XmlComment) getCachedNodeOrCreate(context.runtime, child);
520
- xmlComment.accept(context, visitor);
521
- } else if (type == Node.DOCUMENT_TYPE_NODE) {
522
- XmlDtd xmlDtd = (XmlDtd) getCachedNodeOrCreate(context.runtime, child);
523
- xmlDtd.accept(context, visitor);
524
- } else if (type == Node.PROCESSING_INSTRUCTION_NODE) {
525
- XmlProcessingInstruction xmlProcessingInstruction = (XmlProcessingInstruction) getCachedNodeOrCreate(context.runtime, child);
526
- xmlProcessingInstruction.accept(context, visitor);
527
- } else if (type == Node.TEXT_NODE) {
528
- XmlText xmlText = (XmlText) getCachedNodeOrCreate(context.runtime, child);
529
- xmlText.accept(context, visitor);
530
- } else if (type == Node.ELEMENT_NODE) {
531
- XmlElement xmlElement = (XmlElement) getCachedNodeOrCreate(context.runtime, child);
532
- xmlElement.accept(context, visitor);
533
- }
394
+ }
395
+ }
396
+ IRubyObject[] nodes = xmlNode.getChildren();
397
+ for (int i = 0; i < nodes.length; i++) {
398
+ XmlNode childNode = (XmlNode) nodes[i];
399
+ removeNamespaceRecursively(childNode);
400
+ }
401
+ }
402
+
403
+ @JRubyMethod
404
+ public IRubyObject
405
+ root(ThreadContext context)
406
+ {
407
+ Node rootNode = getDocument().getDocumentElement();
408
+ if (rootNode == null) { return context.nil; }
409
+
410
+ Object invalid = rootNode.getUserData(NokogiriHelpers.ROOT_NODE_INVALID);
411
+ if (invalid != null && ((Boolean) invalid)) { return context.nil; }
412
+
413
+ return getCachedNodeOrCreate(context.runtime, rootNode);
414
+ }
415
+
416
+ protected IRubyObject
417
+ dup_implementation(Ruby runtime, boolean deep)
418
+ {
419
+ XmlDocument doc = (XmlDocument) super.dup_implementation(runtime, deep);
420
+ // Avoid creating a new XmlDocument since we cloned one
421
+ // already. Otherwise the following test will fail:
422
+ //
423
+ // dup = doc.dup
424
+ // dup.equal?(dup.children[0].document)
425
+ //
426
+ // Since `dup.children[0].document' will end up creating a new
427
+ // XmlDocument. See #1060.
428
+ doc.resetCache();
429
+ return doc;
430
+ }
431
+
432
+ @JRubyMethod(name = "root=")
433
+ public IRubyObject
434
+ root_set(ThreadContext context, IRubyObject new_root)
435
+ {
436
+ // in case of document fragment, temporary root node should be deleted.
437
+
438
+ // Java can't have a root whose value is null. Instead of setting null,
439
+ // the method sets user data so that other methods are able to know the root
440
+ // should be nil.
441
+ if (new_root == context.nil) {
442
+ getDocument().getDocumentElement().setUserData(NokogiriHelpers.ROOT_NODE_INVALID, Boolean.TRUE, null);
443
+ return new_root;
444
+ }
445
+ if (!(new_root instanceof XmlNode)) {
446
+ throw context.runtime.newArgumentError("expected Nokogiri::XML::Node but received " + new_root.getType());
447
+ }
448
+ XmlNode newRoot = asXmlNode(context, new_root);
449
+
450
+ IRubyObject root = root(context);
451
+ if (root.isNil()) {
452
+ Node newRootNode;
453
+ if (getDocument() == newRoot.getOwnerDocument()) {
454
+ newRootNode = newRoot.node;
455
+ } else {
456
+ // must copy otherwise newRoot may exist in two places
457
+ // with different owner document.
458
+ newRootNode = getDocument().importNode(newRoot.node, true);
459
+ }
460
+ add_child_node(context, getCachedNodeOrCreate(context.runtime, newRootNode));
461
+ } else {
462
+ Node rootNode = asXmlNode(context, root).node;
463
+ ((XmlNode) getCachedNodeOrCreate(context.runtime, rootNode)).replace_node(context, newRoot);
464
+ }
465
+
466
+ return newRoot;
467
+ }
468
+
469
+ @JRubyMethod
470
+ public IRubyObject
471
+ version(ThreadContext context)
472
+ {
473
+ return stringOrNil(context.runtime, getDocument().getXmlVersion());
474
+ }
475
+
476
+ @JRubyMethod(meta = true)
477
+ public static IRubyObject
478
+ substitute_entities_set(ThreadContext context, IRubyObject cls, IRubyObject value)
479
+ {
480
+ XmlDocument.substituteEntities = value.isTrue();
481
+ return context.nil;
482
+ }
483
+
484
+ public IRubyObject
485
+ getInternalSubset(ThreadContext context)
486
+ {
487
+ IRubyObject dtd = (IRubyObject) node.getUserData(DTD_INTERNAL_SUBSET);
488
+
489
+ if (dtd == null) {
490
+ Document document = getDocument();
491
+ if (document.getUserData(XmlDocument.DTD_RAW_DOCUMENT) != null) {
492
+ dtd = XmlDtd.newFromInternalSubset(context.runtime, document);
493
+ } else if (document.getDoctype() != null) {
494
+ DocumentType docType = document.getDoctype();
495
+ IRubyObject name, publicId, systemId;
496
+ name = publicId = systemId = context.nil;
497
+ if (docType.getName() != null) {
498
+ name = context.runtime.newString(docType.getName());
534
499
  }
535
- visitor.leave(document);
536
- }
537
-
538
- @JRubyMethod(meta = true)
539
- public static IRubyObject wrap(ThreadContext context, IRubyObject klass, IRubyObject arg) {
540
- XmlDocument xmlDocument = new XmlDocument(context.runtime, (RubyClass) klass, (Document) arg.toJava(Document.class));
541
- Helpers.invoke(context, xmlDocument, "initialize");
542
- return xmlDocument;
543
- }
544
-
545
- @Deprecated
546
- @JRubyMethod(meta = true, visibility = Visibility.PRIVATE)
547
- public static IRubyObject wrapJavaDocument(ThreadContext context, IRubyObject klass, IRubyObject arg) {
548
- return wrap(context, klass, arg);
549
- }
550
-
551
- @Deprecated // default to_java works (due inherited from XmlNode#toJava)
552
- @JRubyMethod(visibility = Visibility.PRIVATE)
553
- public IRubyObject toJavaDocument(ThreadContext context) {
554
- return JavaUtil.convertJavaToUsableRubyObject(context.getRuntime(), node);
555
- }
556
-
557
- /* call-seq:
558
- * doc.canonicalize(mode=XML_C14N_1_0,inclusive_namespaces=nil,with_comments=false)
559
- * doc.canonicalize { |obj, parent| ... }
560
- *
561
- * Canonicalize a document and return the results. Takes an optional block
562
- * that takes two parameters: the +obj+ and that node's +parent+.
563
- * The +obj+ will be either a Nokogiri::XML::Node, or a Nokogiri::XML::Namespace
564
- * The block must return a non-nil, non-false value if the +obj+ passed in
565
- * should be included in the canonicalized document.
566
- */
567
- @JRubyMethod(optional=3)
568
- public IRubyObject canonicalize(ThreadContext context, IRubyObject[] args, Block block) {
569
- int mode = 0;
570
- String inclusive_namespace = null;
571
- Boolean with_comments = false;
572
- if (args.length > 0 && !(args[0].isNil())) {
573
- mode = RubyFixnum.fix2int(args[0]);
574
- }
575
- if (args.length > 1 ) {
576
- if (!args[1].isNil() && !(args[1] instanceof List)) {
577
- throw context.runtime.newTypeError("Expected array");
578
- }
579
- if (!args[1].isNil()) {
580
- inclusive_namespace = ((RubyArray)args[1])
581
- .join(context, context.runtime.newString(" "))
582
- .asString()
583
- .asJavaString(); // OMG I wish I knew JRuby better, this is ugly
584
- }
500
+ if (docType.getPublicId() != null) {
501
+ publicId = context.runtime.newString(docType.getPublicId());
585
502
  }
586
- if (args.length > 2) {
587
- with_comments = args[2].isTrue();
503
+ if (docType.getSystemId() != null) {
504
+ systemId = context.runtime.newString(docType.getSystemId());
588
505
  }
589
- String algorithmURI = null;
590
- switch(mode) {
591
- case 0: // XML_C14N_1_0
592
- if (with_comments) algorithmURI = Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS;
593
- else algorithmURI = Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS;
594
- break;
595
- case 1: // XML_C14N_EXCLUSIVE_1_0
596
- if (with_comments) algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS;
597
- else algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
598
- break;
599
- case 2: // XML_C14N_1_1 = 2
600
- if (with_comments) algorithmURI = Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS;
601
- else algorithmURI = Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS;
602
- }
603
- try {
604
- Canonicalizer canonicalizer = Canonicalizer.getInstance(algorithmURI);
605
- XmlNode startingNode = getStartingNode(block);
606
- byte[] result;
607
- CanonicalFilter filter = new CanonicalFilter(context, block);
608
- if (inclusive_namespace == null) {
609
- result = canonicalizer.canonicalizeSubtree(startingNode.getNode(), filter);
610
- } else {
611
- result = canonicalizer.canonicalizeSubtree(startingNode.getNode(), inclusive_namespace, filter);
612
- }
613
- return RubyString.newString(context.runtime, new ByteList(result, UTF8Encoding.INSTANCE));
614
- } catch (CanonicalizationException e) {
615
- // TODO Auto-generated catch block
616
- e.printStackTrace();
617
- }
618
- return context.nil;
619
- }
620
-
621
- private XmlNode getStartingNode(Block block) {
622
- if (block.isGiven()) {
623
- IRubyObject boundSelf = block.getBinding().getSelf();
624
- if (boundSelf instanceof XmlNode) return (XmlNode) boundSelf;
625
- }
626
- return this;
627
- }
628
-
629
- public void resetNamespaceCache(ThreadContext context) {
630
- nsCache = new NokogiriNamespaceCache();
631
- createAndCacheNamespaces(context.runtime, node);
632
- }
506
+ dtd = XmlDtd.newEmpty(context.runtime, document, name, publicId, systemId);
507
+ } else {
508
+ dtd = context.nil;
509
+ }
510
+
511
+ setInternalSubset(dtd);
512
+ }
513
+
514
+ return dtd;
515
+ }
516
+
517
+ /**
518
+ * Assumes XmlNode#internal_subset() has returned nil. (i.e. there
519
+ * is not already an internal subset).
520
+ */
521
+ public IRubyObject
522
+ createInternalSubset(ThreadContext context,
523
+ IRubyObject name,
524
+ IRubyObject external_id,
525
+ IRubyObject system_id)
526
+ {
527
+ XmlDtd dtd = XmlDtd.newEmpty(context.runtime, getDocument(), name, external_id, system_id);
528
+ setInternalSubset(dtd);
529
+ return dtd;
530
+ }
531
+
532
+ protected void
533
+ setInternalSubset(IRubyObject data)
534
+ {
535
+ node.setUserData(DTD_INTERNAL_SUBSET, data, null);
536
+ }
537
+
538
+ public IRubyObject
539
+ getExternalSubset(ThreadContext context)
540
+ {
541
+ IRubyObject dtd = (IRubyObject) node.getUserData(DTD_EXTERNAL_SUBSET);
542
+
543
+ if (dtd == null) { return context.nil; }
544
+ return dtd;
545
+ }
546
+
547
+ /**
548
+ * Assumes XmlNode#external_subset() has returned nil. (i.e. there
549
+ * is not already an external subset).
550
+ */
551
+ public IRubyObject
552
+ createExternalSubset(ThreadContext context,
553
+ IRubyObject name,
554
+ IRubyObject external_id,
555
+ IRubyObject system_id)
556
+ {
557
+ XmlDtd dtd = XmlDtd.newEmpty(context.runtime, getDocument(), name, external_id, system_id);
558
+ setExternalSubset(dtd);
559
+ return dtd;
560
+ }
561
+
562
+ protected void
563
+ setExternalSubset(IRubyObject data)
564
+ {
565
+ node.setUserData(DTD_EXTERNAL_SUBSET, data, null);
566
+ }
567
+
568
+ @Override
569
+ public void
570
+ accept(ThreadContext context, SaveContextVisitor visitor)
571
+ {
572
+ Document document = getDocument();
573
+ visitor.enter(document);
574
+ NodeList children = document.getChildNodes();
575
+ for (int i = 0; i < children.getLength(); i++) {
576
+ Node child = children.item(i);
577
+ short type = child.getNodeType();
578
+ if (type == Node.COMMENT_NODE) {
579
+ XmlComment xmlComment = (XmlComment) getCachedNodeOrCreate(context.runtime, child);
580
+ xmlComment.accept(context, visitor);
581
+ } else if (type == Node.DOCUMENT_TYPE_NODE) {
582
+ XmlDtd xmlDtd = (XmlDtd) getCachedNodeOrCreate(context.runtime, child);
583
+ xmlDtd.accept(context, visitor);
584
+ } else if (type == Node.PROCESSING_INSTRUCTION_NODE) {
585
+ XmlProcessingInstruction xmlProcessingInstruction = (XmlProcessingInstruction) getCachedNodeOrCreate(context.runtime,
586
+ child);
587
+ xmlProcessingInstruction.accept(context, visitor);
588
+ } else if (type == Node.TEXT_NODE) {
589
+ XmlText xmlText = (XmlText) getCachedNodeOrCreate(context.runtime, child);
590
+ xmlText.accept(context, visitor);
591
+ } else if (type == Node.ELEMENT_NODE) {
592
+ XmlElement xmlElement = (XmlElement) getCachedNodeOrCreate(context.runtime, child);
593
+ xmlElement.accept(context, visitor);
594
+ }
595
+ }
596
+ visitor.leave(document);
597
+ }
598
+
599
+ @JRubyMethod(meta = true)
600
+ public static IRubyObject
601
+ wrap(ThreadContext context, IRubyObject klass, IRubyObject arg)
602
+ {
603
+ XmlDocument xmlDocument = new XmlDocument(context.runtime, (RubyClass) klass, (Document) arg.toJava(Document.class));
604
+ Helpers.invoke(context, xmlDocument, "initialize");
605
+ return xmlDocument;
606
+ }
607
+
608
+ @Deprecated
609
+ @JRubyMethod(meta = true, visibility = Visibility.PRIVATE)
610
+ public static IRubyObject
611
+ wrapJavaDocument(ThreadContext context, IRubyObject klass, IRubyObject arg)
612
+ {
613
+ return wrap(context, klass, arg);
614
+ }
615
+
616
+ @Deprecated // default to_java works (due inherited from XmlNode#toJava)
617
+ @JRubyMethod(visibility = Visibility.PRIVATE)
618
+ public IRubyObject
619
+ toJavaDocument(ThreadContext context)
620
+ {
621
+ return JavaUtil.convertJavaToUsableRubyObject(context.getRuntime(), node);
622
+ }
623
+
624
+ /* call-seq:
625
+ * doc.canonicalize(mode=XML_C14N_1_0,inclusive_namespaces=nil,with_comments=false)
626
+ * doc.canonicalize { |obj, parent| ... }
627
+ *
628
+ * Canonicalize a document and return the results. Takes an optional block
629
+ * that takes two parameters: the +obj+ and that node's +parent+.
630
+ * The +obj+ will be either a Nokogiri::XML::Node, or a Nokogiri::XML::Namespace
631
+ * The block must return a non-nil, non-false value if the +obj+ passed in
632
+ * should be included in the canonicalized document.
633
+ */
634
+ @JRubyMethod(optional = 3)
635
+ public IRubyObject
636
+ canonicalize(ThreadContext context, IRubyObject[] args, Block block)
637
+ {
638
+ int mode = 0;
639
+ String inclusive_namespace = null;
640
+ Boolean with_comments = false;
641
+ if (args.length > 0 && !(args[0].isNil())) {
642
+ mode = RubyFixnum.fix2int(args[0]);
643
+ }
644
+ if (args.length > 1) {
645
+ if (!args[1].isNil() && !(args[1] instanceof List)) {
646
+ throw context.runtime.newTypeError("Expected array");
647
+ }
648
+ if (!args[1].isNil()) {
649
+ inclusive_namespace = ((RubyArray)args[1])
650
+ .join(context, context.runtime.newString(" "))
651
+ .asString()
652
+ .asJavaString(); // OMG I wish I knew JRuby better, this is ugly
653
+ }
654
+ }
655
+ if (args.length > 2) {
656
+ with_comments = args[2].isTrue();
657
+ }
658
+ String algorithmURI = null;
659
+ switch (mode) {
660
+ case 0: // XML_C14N_1_0
661
+ if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS; }
662
+ else { algorithmURI = Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS; }
663
+ break;
664
+ case 1: // XML_C14N_EXCLUSIVE_1_0
665
+ if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS; }
666
+ else { algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; }
667
+ break;
668
+ case 2: // XML_C14N_1_1 = 2
669
+ if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS; }
670
+ else { algorithmURI = Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS; }
671
+ }
672
+ try {
673
+ Canonicalizer canonicalizer = Canonicalizer.getInstance(algorithmURI);
674
+ XmlNode startingNode = getStartingNode(block);
675
+ byte[] result;
676
+ CanonicalFilter filter = new CanonicalFilter(context, block);
677
+ if (inclusive_namespace == null) {
678
+ result = canonicalizer.canonicalizeSubtree(startingNode.getNode(), filter);
679
+ } else {
680
+ result = canonicalizer.canonicalizeSubtree(startingNode.getNode(), inclusive_namespace, filter);
681
+ }
682
+ return RubyString.newString(context.runtime, new ByteList(result, UTF8Encoding.INSTANCE));
683
+ } catch (CanonicalizationException e) {
684
+ // TODO Auto-generated catch block
685
+ e.printStackTrace();
686
+ }
687
+ return context.nil;
688
+ }
689
+
690
+ private XmlNode
691
+ getStartingNode(Block block)
692
+ {
693
+ if (block.isGiven()) {
694
+ IRubyObject boundSelf = block.getBinding().getSelf();
695
+ if (boundSelf instanceof XmlNode) { return (XmlNode) boundSelf; }
696
+ }
697
+ return this;
698
+ }
699
+
700
+ public void
701
+ resetNamespaceCache(ThreadContext context)
702
+ {
703
+ nsCache = new NokogiriNamespaceCache();
704
+ createAndCacheNamespaces(context.runtime, node);
705
+ }
633
706
  }