nokogiri 1.10.10-java → 1.11.0-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 (159) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/LICENSE-DEPENDENCIES.md +1015 -947
  4. data/README.md +165 -91
  5. data/ext/java/nokogiri/HtmlDocument.java +34 -46
  6. data/ext/java/nokogiri/HtmlSaxParserContext.java +88 -58
  7. data/ext/java/nokogiri/HtmlSaxPushParser.java +1 -1
  8. data/ext/java/nokogiri/NokogiriService.java +1 -1
  9. data/ext/java/nokogiri/XmlAttr.java +13 -20
  10. data/ext/java/nokogiri/XmlAttributeDecl.java +11 -12
  11. data/ext/java/nokogiri/XmlCdata.java +3 -4
  12. data/ext/java/nokogiri/XmlComment.java +1 -1
  13. data/ext/java/nokogiri/XmlDocument.java +148 -175
  14. data/ext/java/nokogiri/XmlDocumentFragment.java +13 -31
  15. data/ext/java/nokogiri/XmlDtd.java +5 -8
  16. data/ext/java/nokogiri/XmlElement.java +1 -20
  17. data/ext/java/nokogiri/XmlElementDecl.java +23 -28
  18. data/ext/java/nokogiri/XmlEntityDecl.java +23 -27
  19. data/ext/java/nokogiri/XmlEntityReference.java +2 -2
  20. data/ext/java/nokogiri/XmlNamespace.java +72 -89
  21. data/ext/java/nokogiri/XmlNode.java +303 -406
  22. data/ext/java/nokogiri/XmlNodeSet.java +70 -76
  23. data/ext/java/nokogiri/XmlReader.java +12 -13
  24. data/ext/java/nokogiri/XmlRelaxng.java +10 -3
  25. data/ext/java/nokogiri/XmlSaxParserContext.java +15 -10
  26. data/ext/java/nokogiri/XmlSchema.java +87 -27
  27. data/ext/java/nokogiri/XmlSyntaxError.java +2 -6
  28. data/ext/java/nokogiri/XmlText.java +12 -9
  29. data/ext/java/nokogiri/XmlXpathContext.java +55 -25
  30. data/ext/java/nokogiri/XsltStylesheet.java +7 -15
  31. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +52 -46
  32. data/ext/java/nokogiri/internals/NokogiriHandler.java +1 -1
  33. data/ext/java/nokogiri/internals/NokogiriHelpers.java +71 -135
  34. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +90 -58
  35. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +9 -2
  36. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +67 -10
  37. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +4 -2
  38. data/ext/java/nokogiri/internals/ParserContext.java +27 -73
  39. data/ext/java/nokogiri/internals/ReaderNode.java +2 -4
  40. data/ext/java/nokogiri/internals/XmlDomParserContext.java +18 -33
  41. data/ext/nokogiri/depend +476 -357
  42. data/ext/nokogiri/extconf.rb +507 -357
  43. data/ext/nokogiri/html_document.c +79 -78
  44. data/ext/nokogiri/html_sax_parser_context.c +2 -2
  45. data/ext/nokogiri/nokogiri.c +34 -40
  46. data/ext/nokogiri/xml_document.c +18 -4
  47. data/ext/nokogiri/xml_io.c +8 -6
  48. data/ext/nokogiri/xml_node.c +21 -1
  49. data/ext/nokogiri/xml_node_set.c +1 -1
  50. data/ext/nokogiri/xml_reader.c +6 -17
  51. data/ext/nokogiri/xml_relax_ng.c +29 -11
  52. data/ext/nokogiri/xml_sax_parser.c +2 -7
  53. data/ext/nokogiri/xml_sax_parser_context.c +2 -2
  54. data/ext/nokogiri/xml_schema.c +55 -13
  55. data/ext/nokogiri/xml_xpath_context.c +80 -4
  56. data/ext/nokogiri/xslt_stylesheet.c +1 -8
  57. data/lib/nokogiri.rb +22 -22
  58. data/lib/nokogiri/css.rb +1 -0
  59. data/lib/nokogiri/css/node.rb +1 -0
  60. data/lib/nokogiri/css/parser.rb +63 -62
  61. data/lib/nokogiri/css/parser.y +2 -2
  62. data/lib/nokogiri/css/parser_extras.rb +39 -36
  63. data/lib/nokogiri/css/syntax_error.rb +1 -0
  64. data/lib/nokogiri/css/tokenizer.rb +1 -0
  65. data/lib/nokogiri/css/xpath_visitor.rb +73 -43
  66. data/lib/nokogiri/decorators/slop.rb +1 -0
  67. data/lib/nokogiri/html.rb +1 -0
  68. data/lib/nokogiri/html/builder.rb +1 -0
  69. data/lib/nokogiri/html/document.rb +13 -26
  70. data/lib/nokogiri/html/document_fragment.rb +1 -0
  71. data/lib/nokogiri/html/element_description.rb +1 -0
  72. data/lib/nokogiri/html/element_description_defaults.rb +1 -0
  73. data/lib/nokogiri/html/entity_lookup.rb +1 -0
  74. data/lib/nokogiri/html/sax/parser.rb +1 -0
  75. data/lib/nokogiri/html/sax/parser_context.rb +1 -0
  76. data/lib/nokogiri/html/sax/push_parser.rb +1 -0
  77. data/lib/nokogiri/jruby/dependencies.rb +20 -0
  78. data/lib/nokogiri/nokogiri.jar +0 -0
  79. data/lib/nokogiri/syntax_error.rb +1 -0
  80. data/lib/nokogiri/version.rb +3 -109
  81. data/lib/nokogiri/version/constant.rb +5 -0
  82. data/lib/nokogiri/version/info.rb +182 -0
  83. data/lib/nokogiri/xml.rb +1 -0
  84. data/lib/nokogiri/xml/attr.rb +1 -0
  85. data/lib/nokogiri/xml/attribute_decl.rb +1 -0
  86. data/lib/nokogiri/xml/builder.rb +3 -2
  87. data/lib/nokogiri/xml/cdata.rb +1 -0
  88. data/lib/nokogiri/xml/character_data.rb +1 -0
  89. data/lib/nokogiri/xml/document.rb +20 -15
  90. data/lib/nokogiri/xml/document_fragment.rb +5 -6
  91. data/lib/nokogiri/xml/dtd.rb +1 -0
  92. data/lib/nokogiri/xml/element_content.rb +1 -0
  93. data/lib/nokogiri/xml/element_decl.rb +1 -0
  94. data/lib/nokogiri/xml/entity_decl.rb +1 -0
  95. data/lib/nokogiri/xml/entity_reference.rb +1 -0
  96. data/lib/nokogiri/xml/namespace.rb +1 -0
  97. data/lib/nokogiri/xml/node.rb +587 -249
  98. data/lib/nokogiri/xml/node/save_options.rb +1 -0
  99. data/lib/nokogiri/xml/node_set.rb +1 -0
  100. data/lib/nokogiri/xml/notation.rb +1 -0
  101. data/lib/nokogiri/xml/parse_options.rb +10 -3
  102. data/lib/nokogiri/xml/pp.rb +1 -0
  103. data/lib/nokogiri/xml/pp/character_data.rb +1 -0
  104. data/lib/nokogiri/xml/pp/node.rb +1 -0
  105. data/lib/nokogiri/xml/processing_instruction.rb +1 -0
  106. data/lib/nokogiri/xml/reader.rb +7 -3
  107. data/lib/nokogiri/xml/relax_ng.rb +7 -2
  108. data/lib/nokogiri/xml/sax.rb +1 -0
  109. data/lib/nokogiri/xml/sax/document.rb +1 -0
  110. data/lib/nokogiri/xml/sax/parser.rb +1 -0
  111. data/lib/nokogiri/xml/sax/parser_context.rb +1 -0
  112. data/lib/nokogiri/xml/sax/push_parser.rb +1 -0
  113. data/lib/nokogiri/xml/schema.rb +13 -4
  114. data/lib/nokogiri/xml/searchable.rb +25 -16
  115. data/lib/nokogiri/xml/syntax_error.rb +1 -0
  116. data/lib/nokogiri/xml/text.rb +1 -0
  117. data/lib/nokogiri/xml/xpath.rb +1 -0
  118. data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -0
  119. data/lib/nokogiri/xml/xpath_context.rb +1 -0
  120. data/lib/nokogiri/xslt.rb +1 -0
  121. data/lib/nokogiri/xslt/stylesheet.rb +1 -0
  122. data/lib/xsd/xmlparser/nokogiri.rb +1 -0
  123. metadata +86 -159
  124. data/ext/java/nokogiri/internals/NokogiriEncodingReaderWrapper.java +0 -107
  125. data/ext/java/nokogiri/internals/UncloseableInputStream.java +0 -102
  126. data/ext/nokogiri/html_document.h +0 -10
  127. data/ext/nokogiri/html_element_description.h +0 -10
  128. data/ext/nokogiri/html_entity_lookup.h +0 -8
  129. data/ext/nokogiri/html_sax_parser_context.h +0 -11
  130. data/ext/nokogiri/html_sax_push_parser.h +0 -9
  131. data/ext/nokogiri/nokogiri.h +0 -121
  132. data/ext/nokogiri/xml_attr.h +0 -9
  133. data/ext/nokogiri/xml_attribute_decl.h +0 -9
  134. data/ext/nokogiri/xml_cdata.h +0 -9
  135. data/ext/nokogiri/xml_comment.h +0 -9
  136. data/ext/nokogiri/xml_document.h +0 -23
  137. data/ext/nokogiri/xml_document_fragment.h +0 -10
  138. data/ext/nokogiri/xml_dtd.h +0 -10
  139. data/ext/nokogiri/xml_element_content.h +0 -10
  140. data/ext/nokogiri/xml_element_decl.h +0 -9
  141. data/ext/nokogiri/xml_encoding_handler.h +0 -8
  142. data/ext/nokogiri/xml_entity_decl.h +0 -10
  143. data/ext/nokogiri/xml_entity_reference.h +0 -9
  144. data/ext/nokogiri/xml_io.h +0 -11
  145. data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
  146. data/ext/nokogiri/xml_namespace.h +0 -14
  147. data/ext/nokogiri/xml_node.h +0 -13
  148. data/ext/nokogiri/xml_node_set.h +0 -12
  149. data/ext/nokogiri/xml_processing_instruction.h +0 -9
  150. data/ext/nokogiri/xml_reader.h +0 -10
  151. data/ext/nokogiri/xml_relax_ng.h +0 -9
  152. data/ext/nokogiri/xml_sax_parser.h +0 -39
  153. data/ext/nokogiri/xml_sax_parser_context.h +0 -10
  154. data/ext/nokogiri/xml_sax_push_parser.h +0 -9
  155. data/ext/nokogiri/xml_schema.h +0 -9
  156. data/ext/nokogiri/xml_syntax_error.h +0 -13
  157. data/ext/nokogiri/xml_text.h +0 -9
  158. data/ext/nokogiri/xml_xpath_context.h +0 -10
  159. data/ext/nokogiri/xslt_stylesheet.h +0 -14
@@ -51,6 +51,8 @@ import javax.xml.validation.Validator;
51
51
  import nokogiri.internals.IgnoreSchemaErrorsErrorHandler;
52
52
  import nokogiri.internals.SchemaErrorHandler;
53
53
  import nokogiri.internals.XmlDomParserContext;
54
+ import nokogiri.internals.ParserContext;
55
+ import nokogiri.internals.ParserContext.Options;
54
56
 
55
57
  import org.jruby.Ruby;
56
58
  import org.jruby.RubyArray;
@@ -63,11 +65,13 @@ import org.jruby.exceptions.RaiseException;
63
65
  import org.jruby.runtime.ThreadContext;
64
66
  import org.jruby.runtime.Visibility;
65
67
  import org.jruby.runtime.builtin.IRubyObject;
68
+ import org.jruby.runtime.Helpers;
66
69
  import org.w3c.dom.Document;
67
70
  import org.w3c.dom.ls.LSInput;
68
71
  import org.w3c.dom.ls.LSResourceResolver;
69
72
  import org.xml.sax.ErrorHandler;
70
73
  import org.xml.sax.SAXException;
74
+ import org.xml.sax.SAXParseException;
71
75
 
72
76
  /**
73
77
  * Class for Nokogiri::XML::Schema
@@ -93,11 +97,20 @@ public class XmlSchema extends RubyObject {
93
97
  return super.clone();
94
98
  }
95
99
 
96
- private Schema getSchema(Source source, String currentDir, String scriptFileName) throws SAXException {
100
+ private Schema getSchema(Source source,
101
+ String currentDir,
102
+ String scriptFileName,
103
+ SchemaErrorHandler errorHandler,
104
+ long parseOptions) throws SAXException {
105
+ boolean noNet = new ParserContext.Options(parseOptions).noNet;
106
+
97
107
  SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
98
- SchemaResourceResolver resourceResolver = new SchemaResourceResolver(currentDir, scriptFileName, null);
108
+ SchemaResourceResolver resourceResolver =
109
+ new SchemaResourceResolver(currentDir, scriptFileName, null, errorHandler, noNet);
110
+
99
111
  schemaFactory.setResourceResolver(resourceResolver);
100
- schemaFactory.setErrorHandler(new IgnoreSchemaErrorsErrorHandler());
112
+ schemaFactory.setErrorHandler(errorHandler);
113
+
101
114
  return schemaFactory.newSchema(source);
102
115
  }
103
116
 
@@ -105,13 +118,27 @@ public class XmlSchema extends RubyObject {
105
118
  this.validator = validator;
106
119
  }
107
120
 
108
- static XmlSchema createSchemaInstance(ThreadContext context, RubyClass klazz, Source source) {
121
+ static XmlSchema createSchemaInstance(ThreadContext context, RubyClass klazz, Source source, IRubyObject parseOptions) {
109
122
  Ruby runtime = context.getRuntime();
110
123
  XmlSchema xmlSchema = (XmlSchema) NokogiriService.XML_SCHEMA_ALLOCATOR.allocate(runtime, klazz);
124
+
125
+ if (parseOptions == null) {
126
+ parseOptions = defaultParseOptions(context.getRuntime());
127
+ }
128
+ long intParseOptions = RubyFixnum.fix2long(Helpers.invoke(context, parseOptions, "to_i"));
129
+
111
130
  xmlSchema.setInstanceVariable("@errors", runtime.newEmptyArray());
131
+ xmlSchema.setInstanceVariable("@parse_options", parseOptions);
112
132
 
113
133
  try {
114
- Schema schema = xmlSchema.getSchema(source, context.getRuntime().getCurrentDirectory(), context.getRuntime().getInstanceConfig().getScriptFileName());
134
+ SchemaErrorHandler errorHandler =
135
+ new SchemaErrorHandler(context.getRuntime(), (RubyArray)xmlSchema.getInstanceVariable("@errors"));
136
+ Schema schema =
137
+ xmlSchema.getSchema(source,
138
+ context.getRuntime().getCurrentDirectory(),
139
+ context.getRuntime().getInstanceConfig().getScriptFileName(),
140
+ errorHandler,
141
+ intParseOptions);
115
142
  xmlSchema.setValidator(schema.newValidator());
116
143
  return xmlSchema;
117
144
  } catch (SAXException ex) {
@@ -119,19 +146,29 @@ public class XmlSchema extends RubyObject {
119
146
  }
120
147
  }
121
148
 
149
+ protected static IRubyObject defaultParseOptions(Ruby runtime) {
150
+ return ((RubyClass)runtime.getClassFromPath("Nokogiri::XML::ParseOptions")).getConstant("DEFAULT_SCHEMA");
151
+ }
152
+
122
153
  /*
123
154
  * call-seq:
124
155
  * from_document(doc)
125
156
  *
126
157
  * Create a new Schema from the Nokogiri::XML::Document +doc+
127
158
  */
128
- @JRubyMethod(meta=true)
129
- public static IRubyObject from_document(ThreadContext context, IRubyObject klazz, IRubyObject document) {
159
+ @JRubyMethod(meta=true, required=1, optional=1)
160
+ public static IRubyObject from_document(ThreadContext context, IRubyObject klazz, IRubyObject[] args) {
161
+ IRubyObject document = args[0];
162
+ IRubyObject parseOptions = null;
163
+ if (args.length > 1) {
164
+ parseOptions = args[1];
165
+ }
166
+
130
167
  XmlDocument doc = ((XmlDocument) ((XmlNode) document).document(context));
131
168
 
132
169
  RubyArray errors = (RubyArray) doc.getInstanceVariable("@errors");
133
170
  if (!errors.isEmpty()) {
134
- throw new RaiseException((XmlSyntaxError) errors.first());
171
+ throw ((XmlSyntaxError) errors.first()).toThrowable();
135
172
  }
136
173
 
137
174
  DOMSource source = new DOMSource(doc.getDocument());
@@ -142,25 +179,30 @@ public class XmlSchema extends RubyObject {
142
179
  source.setSystemId(uri.convertToString().asJavaString());
143
180
  }
144
181
 
145
- return getSchema(context, (RubyClass)klazz, source);
182
+ return getSchema(context, (RubyClass)klazz, source, parseOptions);
183
+ }
184
+
185
+ @JRubyMethod(meta=true, required=1, optional=1)
186
+ public static IRubyObject read_memory(ThreadContext context, IRubyObject klazz, IRubyObject[] args) {
187
+ IRubyObject content = args[0];
188
+ IRubyObject parseOptions = null;
189
+ if (args.length > 1) {
190
+ parseOptions = args[1];
191
+ }
192
+ String data = content.convertToString().asJavaString();
193
+ return getSchema(context, (RubyClass) klazz, new StreamSource(new StringReader(data)), parseOptions);
146
194
  }
147
195
 
148
- private static IRubyObject getSchema(ThreadContext context, RubyClass klazz, Source source) {
196
+ private static IRubyObject getSchema(ThreadContext context, RubyClass klazz, Source source, IRubyObject parseOptions) {
149
197
  String moduleName = klazz.getName();
150
198
  if ("Nokogiri::XML::Schema".equals(moduleName)) {
151
- return XmlSchema.createSchemaInstance(context, klazz, source);
199
+ return XmlSchema.createSchemaInstance(context, klazz, source, parseOptions);
152
200
  } else if ("Nokogiri::XML::RelaxNG".equals(moduleName)) {
153
- return XmlRelaxng.createSchemaInstance(context, klazz, source);
201
+ return XmlRelaxng.createSchemaInstance(context, klazz, source, parseOptions);
154
202
  }
155
203
  return context.getRuntime().getNil();
156
204
  }
157
205
 
158
- @JRubyMethod(meta=true)
159
- public static IRubyObject read_memory(ThreadContext context, IRubyObject klazz, IRubyObject content) {
160
- String data = content.convertToString().asJavaString();
161
- return getSchema(context, (RubyClass) klazz, new StreamSource(new StringReader(data)));
162
- }
163
-
164
206
  @JRubyMethod(visibility=Visibility.PRIVATE)
165
207
  public IRubyObject validate_document(ThreadContext context, IRubyObject document) {
166
208
  return validate_document_or_file(context, (XmlDocument)document);
@@ -168,11 +210,11 @@ public class XmlSchema extends RubyObject {
168
210
 
169
211
  @JRubyMethod(visibility=Visibility.PRIVATE)
170
212
  public IRubyObject validate_file(ThreadContext context, IRubyObject file) {
171
- Ruby ruby = context.getRuntime();
213
+ Ruby runtime = context.runtime;
172
214
 
173
- XmlDomParserContext ctx = new XmlDomParserContext(ruby, RubyFixnum.newFixnum(ruby, 1L));
215
+ XmlDomParserContext ctx = new XmlDomParserContext(runtime, RubyFixnum.newFixnum(runtime, 1L));
174
216
  ctx.setInputSourceFile(context, file);
175
- XmlDocument xmlDocument = ctx.parse(context, getNokogiriClass(ruby, "Nokogiri::XML::Document"), ruby.getNil());
217
+ XmlDocument xmlDocument = ctx.parse(context, getNokogiriClass(runtime, "Nokogiri::XML::Document"), context.nil);
176
218
  return validate_document_or_file(context, xmlDocument);
177
219
  }
178
220
 
@@ -209,11 +251,15 @@ public class XmlSchema extends RubyObject {
209
251
  SchemaLSInput lsInput = new SchemaLSInput();
210
252
  String currentDir;
211
253
  String scriptFileName;
254
+ SchemaErrorHandler errorHandler;
255
+ boolean noNet;
212
256
  //String defaultURI;
213
257
 
214
- SchemaResourceResolver(String currentDir, String scriptFileName, Object input) {
258
+ SchemaResourceResolver(String currentDir, String scriptFileName, Object input, SchemaErrorHandler errorHandler, boolean noNet) {
215
259
  this.currentDir = currentDir;
216
260
  this.scriptFileName = scriptFileName;
261
+ this.errorHandler = errorHandler;
262
+ this.noNet = noNet;
217
263
  if (input == null) return;
218
264
  if (input instanceof String) {
219
265
  lsInput.setStringData((String)input);
@@ -225,11 +271,25 @@ public class XmlSchema extends RubyObject {
225
271
  }
226
272
 
227
273
  @Override
228
- public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
229
- String adjusted = adjustSystemIdIfNecessary(currentDir, scriptFileName, baseURI, systemId);
230
- lsInput.setPublicId(publicId);
231
- lsInput.setSystemId(adjusted != null? adjusted : systemId);
232
- lsInput.setBaseURI(baseURI);
274
+ public LSInput resolveResource(String type,
275
+ String namespaceURI,
276
+ String publicId,
277
+ String systemId,
278
+ String baseURI) {
279
+ if (noNet && (systemId.startsWith("http://") || systemId.startsWith("ftp://"))) {
280
+ if (systemId.startsWith(XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
281
+ return null; // use default resolver
282
+ }
283
+ try {
284
+ this.errorHandler.warning(new SAXParseException(String.format("Attempt to load network entity '%s'", systemId), null));
285
+ } catch (SAXException ex) {
286
+ }
287
+ } else {
288
+ String adjusted = adjustSystemIdIfNecessary(currentDir, scriptFileName, baseURI, systemId);
289
+ lsInput.setPublicId(publicId);
290
+ lsInput.setSystemId(adjusted != null? adjusted : systemId);
291
+ lsInput.setBaseURI(baseURI);
292
+ }
233
293
  return lsInput;
234
294
  }
235
295
  }
@@ -120,13 +120,9 @@ public class XmlSyntaxError extends RubyException {
120
120
  setInstanceVariable("@file", stringOrNil(runtime, exception.getSystemId()));
121
121
  }
122
122
 
123
- // NOTE: special care - due JRuby 1.7.x
124
-
125
- @Override
126
- public IRubyObject to_s(ThreadContext context) { return to_s19(context); }
127
-
128
123
  @JRubyMethod(name = "to_s")
129
- public RubyString to_s19(ThreadContext context) {
124
+ @Override
125
+ public IRubyObject to_s(ThreadContext context) {
130
126
  RubyString msg = msg(context.runtime);
131
127
  return msg != null ? msg : super.to_s(context).asString();
132
128
  }
@@ -36,11 +36,14 @@ import static nokogiri.internals.NokogiriHelpers.getCachedNodeOrCreate;
36
36
  import static nokogiri.internals.NokogiriHelpers.rubyStringToString;
37
37
  import nokogiri.internals.SaveContextVisitor;
38
38
 
39
+ import org.jcodings.specific.USASCIIEncoding;
39
40
  import org.jruby.Ruby;
40
41
  import org.jruby.RubyClass;
42
+ import org.jruby.RubyString;
41
43
  import org.jruby.anno.JRubyClass;
42
44
  import org.jruby.runtime.ThreadContext;
43
45
  import org.jruby.runtime.builtin.IRubyObject;
46
+ import org.jruby.util.ByteList;
44
47
  import org.w3c.dom.Document;
45
48
  import org.w3c.dom.Node;
46
49
  import org.w3c.dom.Text;
@@ -54,6 +57,9 @@ import org.w3c.dom.Text;
54
57
  @JRubyClass(name="Nokogiri::XML::Text", parent="Nokogiri::XML::CharacterData")
55
58
  public class XmlText extends XmlNode {
56
59
 
60
+ private static final ByteList TEXT = ByteList.create("text");
61
+ static { TEXT.setEncoding(USASCIIEncoding.INSTANCE); }
62
+
57
63
  public XmlText(Ruby runtime, RubyClass rubyClass, Node node) {
58
64
  super(runtime, rubyClass, node);
59
65
  }
@@ -65,34 +71,31 @@ public class XmlText extends XmlNode {
65
71
  @Override
66
72
  protected void init(ThreadContext context, IRubyObject[] args) {
67
73
  if (args.length < 2) {
68
- throw getRuntime().newArgumentError(args.length, 2);
74
+ throw context.runtime.newArgumentError(args.length, 2);
69
75
  }
70
76
 
71
77
  content = args[0];
72
78
  IRubyObject xNode = args[1];
73
79
 
74
- XmlNode xmlNode = asXmlNode(context, xNode);
75
- XmlDocument xmlDoc = (XmlDocument)xmlNode.document(context);
76
- doc = xmlDoc;
77
- Document document = xmlDoc.getDocument();
80
+ Document document = asXmlNode(context, xNode).getOwnerDocument();
78
81
  // text node content should not be encoded when it is created by Text node.
79
82
  // while content should be encoded when it is created by Element node.
80
83
  Node node = document.createTextNode(rubyStringToString(content));
81
- setNode(context, node);
84
+ setNode(context.runtime, node);
82
85
  }
83
86
 
84
87
  @Override
85
88
  protected IRubyObject getNodeName(ThreadContext context) {
86
- if (name == null) name = context.getRuntime().newString("text");
89
+ if (name == null) name = RubyString.newStringShared(context.runtime, TEXT);
87
90
  return name;
88
91
  }
89
92
 
90
93
  @Override
91
94
  public void accept(ThreadContext context, SaveContextVisitor visitor) {
92
- visitor.enter((Text)node);
95
+ visitor.enter((Text) node);
93
96
  Node child = node.getFirstChild();
94
97
  while (child != null) {
95
- IRubyObject nokoNode = getCachedNodeOrCreate(context.getRuntime(), child);
98
+ IRubyObject nokoNode = getCachedNodeOrCreate(context.runtime, child);
96
99
  if (nokoNode instanceof XmlNode) {
97
100
  XmlNode cur = (XmlNode) nokoNode;
98
101
  cur.accept(context, visitor);
@@ -33,6 +33,8 @@
33
33
  package nokogiri;
34
34
 
35
35
  import java.util.Set;
36
+ import java.util.regex.Matcher;
37
+ import java.util.regex.Pattern;
36
38
 
37
39
  import javax.xml.transform.TransformerException;
38
40
 
@@ -57,6 +59,8 @@ import nokogiri.internals.NokogiriNamespaceContext;
57
59
  import nokogiri.internals.NokogiriXPathFunctionResolver;
58
60
  import nokogiri.internals.NokogiriXPathVariableResolver;
59
61
 
62
+ import static nokogiri.internals.NokogiriHelpers.nodeListToRubyArray;
63
+
60
64
  /**
61
65
  * Class for Nokogiri::XML::XpathContext
62
66
  *
@@ -66,7 +70,6 @@ import nokogiri.internals.NokogiriXPathVariableResolver;
66
70
  */
67
71
  @JRubyClass(name="Nokogiri::XML::XPathContext")
68
72
  public class XmlXpathContext extends RubyObject {
69
-
70
73
  static {
71
74
  final String DTMManager = "org.apache.xml.dtm.DTMManager";
72
75
  if (SafePropertyAccessor.getProperty(DTMManager) == null) {
@@ -107,25 +110,53 @@ public class XmlXpathContext extends RubyObject {
107
110
  }
108
111
  }
109
112
 
113
+
114
+ // see https://en.wikipedia.org/wiki/QName
115
+ private static final String NameStartCharStr = "[_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]" ;
116
+ private static final String NameCharStr = "[-\\.0-9\u00B7\u0300-\u036F\u203F-\u2040]|" + NameStartCharStr ;
117
+ private static final String NCNameStr = "(?:" + NameStartCharStr + ")(?:" + NameCharStr + ")*";
118
+ private static final String XPathFunctionCaptureStr = "(" + NCNameStr + "(?=\\())";
119
+ private static final Pattern XPathFunctionCaptureRE = Pattern.compile(XPathFunctionCaptureStr);
120
+
110
121
  @JRubyMethod
111
- public IRubyObject evaluate(ThreadContext context, IRubyObject expr, IRubyObject handler) {
112
-
113
- String src = expr.convertToString().asJavaString();
114
- if (!handler.isNil()) {
115
- if (!isContainsPrefix(src)) {
116
- StringBuilder replacement = new StringBuilder();
117
- Set<String> methodNames = handler.getMetaClass().getMethods().keySet();
118
- final String PREFIX = NokogiriNamespaceContext.NOKOGIRI_PREFIX;
119
- for (String name : methodNames) {
120
- replacement.setLength(0);
121
- replacement.ensureCapacity(PREFIX.length() + 1 + name.length());
122
- replacement.append(PREFIX).append(':').append(name);
123
- src = src.replace(name, replacement); // replace(name, NOKOGIRI_PREFIX + ':' + name)
122
+ public IRubyObject evaluate(ThreadContext context, IRubyObject rbQuery, IRubyObject handler) {
123
+ String query = rbQuery.convertToString().asJavaString();
124
+
125
+ if (!handler.isNil() && !isContainsPrefix(query)) {
126
+ //
127
+ // The user has passed in a handler, but isn't using the `nokogiri:` prefix as
128
+ // instructed in JRuby land, so let's try to be clever and rewrite the query, inserting
129
+ // the nokogiri namespace where appropriate.
130
+ //
131
+ StringBuilder namespacedQuery = new StringBuilder();
132
+ int jchar = 0;
133
+
134
+ // Find the methods on the handler object
135
+ Set<String> methodNames = handler.getMetaClass().getMethods().keySet();
136
+
137
+ // Find the function calls in the xpath query
138
+ Matcher xpathFunctionCalls = XPathFunctionCaptureRE.matcher(query);
139
+
140
+ while (xpathFunctionCalls.find()) {
141
+ namespacedQuery.append(query.subSequence(jchar, xpathFunctionCalls.start()));
142
+ jchar = xpathFunctionCalls.start();
143
+
144
+ if (methodNames.contains(xpathFunctionCalls.group())) {
145
+ namespacedQuery.append(NokogiriNamespaceContext.NOKOGIRI_PREFIX);
146
+ namespacedQuery.append(":");
124
147
  }
148
+
149
+ namespacedQuery.append(query.subSequence(xpathFunctionCalls.start(), xpathFunctionCalls.end()));
150
+ jchar = xpathFunctionCalls.end();
151
+ }
152
+
153
+ if (jchar < query.length()-1) {
154
+ namespacedQuery.append(query.subSequence(jchar, query.length()));
125
155
  }
156
+ query = namespacedQuery.toString();
126
157
  }
127
158
 
128
- return node_set(context, src, handler);
159
+ return node_set(context, query, handler);
129
160
  }
130
161
 
131
162
  @JRubyMethod
@@ -155,13 +186,14 @@ public class XmlXpathContext extends RubyObject {
155
186
  }
156
187
 
157
188
  private IRubyObject node_set(ThreadContext context, String expr, IRubyObject handler) {
158
- final NokogiriXPathFunctionResolver fnResolver =
159
- handler.isNil() ? null : NokogiriXPathFunctionResolver.create(handler);
189
+ final NokogiriXPathFunctionResolver fnResolver = NokogiriXPathFunctionResolver.create(handler);
160
190
  try {
161
191
  return tryGetNodeSet(context, expr, fnResolver);
162
192
  }
163
193
  catch (TransformerException ex) {
164
- throw new RaiseException(XmlSyntaxError.createXMLXPathSyntaxError(context.runtime, expr, ex)); // Nokogiri::XML::XPath::SyntaxError
194
+ throw XmlSyntaxError.createXMLXPathSyntaxError(context.runtime,
195
+ (expr + ": " + ex.toString()),
196
+ ex).toThrowable();
165
197
  }
166
198
  }
167
199
 
@@ -181,14 +213,12 @@ public class XmlXpathContext extends RubyObject {
181
213
  xobj = xpathInternal.execute(getXPathContext(fnResolver), contextNode, prefixResolver);
182
214
 
183
215
  switch (xobj.getType()) {
184
- case XObject.CLASS_BOOLEAN : return context.getRuntime().newBoolean(xobj.bool());
185
- case XObject.CLASS_NUMBER : return context.getRuntime().newFloat(xobj.num());
216
+ case XObject.CLASS_BOOLEAN : return context.runtime.newBoolean(xobj.bool());
217
+ case XObject.CLASS_NUMBER : return context.runtime.newFloat(xobj.num());
186
218
  case XObject.CLASS_NODESET :
187
- XmlNodeSet xmlNodeSet = XmlNodeSet.newEmptyNodeSet(context);
188
- xmlNodeSet.setNodeList(xobj.nodelist());
189
- xmlNodeSet.initialize(context.getRuntime(), this.context);
190
- return xmlNodeSet;
191
- default : return context.getRuntime().newString(xobj.str());
219
+ IRubyObject[] nodes = nodeListToRubyArray(context.runtime, xobj.nodelist());
220
+ return XmlNodeSet.newNodeSet(context.runtime, nodes, this.context);
221
+ default : return context.runtime.newString(xobj.str());
192
222
  }
193
223
  }
194
224
 
@@ -130,12 +130,11 @@ public class XsltStylesheet extends RubyObject {
130
130
  }
131
131
  }
132
132
 
133
- private Pattern p = Pattern.compile("'.{1,}'");
133
+ private static final Pattern QUOTED = Pattern.compile("'.{1,}'");
134
134
 
135
135
  private String unparseValue(String orig) {
136
- Matcher m = p.matcher(orig);
137
- if ((orig.startsWith("\"") && orig.endsWith("\"")) || m.matches()) {
138
- orig = orig.substring(1, orig.length()-1);
136
+ if ((orig.startsWith("\"") && orig.endsWith("\"")) || QUOTED.matcher(orig).matches()) {
137
+ orig = orig.substring(1, orig.length() - 1);
139
138
  }
140
139
 
141
140
  return orig;
@@ -174,11 +173,8 @@ public class XsltStylesheet extends RubyObject {
174
173
  }
175
174
 
176
175
  private static void ensureFirstArgIsDocument(Ruby runtime, IRubyObject arg) {
177
- if (arg instanceof XmlDocument) {
178
- return;
179
- } else {
180
- throw runtime.newArgumentError("doc must be a Nokogiri::XML::Document instance");
181
- }
176
+ if (arg instanceof XmlDocument) return;
177
+ throw runtime.newArgumentError("doc must be a Nokogiri::XML::Document instance");
182
178
  }
183
179
 
184
180
  private static void ensureDocumentHasNoError(ThreadContext context, XmlDocument xmlDoc) {
@@ -289,13 +285,9 @@ public class XsltStylesheet extends RubyObject {
289
285
 
290
286
  private IRubyObject createDocumentFromDomResult(ThreadContext context, Ruby runtime, DOMResult domResult) {
291
287
  if ("html".equals(domResult.getNode().getFirstChild().getNodeName())) {
292
- HtmlDocument htmlDocument = (HtmlDocument) getNokogiriClass(runtime, "Nokogiri::HTML::Document").allocate();
293
- htmlDocument.setDocumentNode(context, (Document) domResult.getNode());
294
- return htmlDocument;
288
+ return new HtmlDocument(context.runtime, (Document) domResult.getNode());
295
289
  } else {
296
- XmlDocument xmlDocument = (XmlDocument) NokogiriService.XML_DOCUMENT_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime, "Nokogiri::XML::Document"));
297
- xmlDocument.setDocumentNode(context, (Document) domResult.getNode());
298
- return xmlDocument;
290
+ return new XmlDocument(context.runtime, (Document) domResult.getNode());
299
291
  }
300
292
  }
301
293