nokogiri 1.8.2-java → 1.8.3-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 (65) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +14 -14
  3. data/CHANGELOG.md +43 -1
  4. data/LICENSE.md +2 -1
  5. data/Manifest.txt +3 -0
  6. data/README.md +20 -21
  7. data/Rakefile +3 -9
  8. data/SECURITY.md +19 -0
  9. data/build_all +1 -1
  10. data/dependencies.yml +11 -11
  11. data/ext/java/nokogiri/HtmlSaxParserContext.java +7 -13
  12. data/ext/java/nokogiri/HtmlSaxPushParser.java +72 -90
  13. data/ext/java/nokogiri/NokogiriService.java +0 -19
  14. data/ext/java/nokogiri/XmlNode.java +2 -23
  15. data/ext/java/nokogiri/XmlSaxParserContext.java +81 -101
  16. data/ext/java/nokogiri/XmlSaxPushParser.java +117 -89
  17. data/ext/java/nokogiri/XmlSyntaxError.java +9 -17
  18. data/ext/java/nokogiri/internals/NokogiriHandler.java +100 -108
  19. data/ext/java/nokogiri/internals/NokogiriHelpers.java +11 -14
  20. data/ext/java/nokogiri/internals/ParserContext.java +34 -19
  21. data/ext/java/nokogiri/internals/ReaderNode.java +6 -10
  22. data/ext/java/nokogiri/internals/SaveContextVisitor.java +4 -3
  23. data/ext/java/nokogiri/internals/XmlDomParserContext.java +6 -3
  24. data/ext/java/nokogiri/internals/c14n/InclusiveNamespaces.java +4 -3
  25. data/ext/nokogiri/extconf.rb +1 -1
  26. data/ext/nokogiri/html_element_description.c +14 -14
  27. data/ext/nokogiri/xml_cdata.c +6 -4
  28. data/ext/nokogiri/xml_document.c +2 -3
  29. data/ext/nokogiri/xml_dtd.c +2 -2
  30. data/ext/nokogiri/xml_io.c +1 -0
  31. data/ext/nokogiri/xml_namespace.c +3 -9
  32. data/ext/nokogiri/xml_namespace.h +2 -0
  33. data/ext/nokogiri/xml_node.c +23 -15
  34. data/ext/nokogiri/xml_node_set.c +5 -4
  35. data/ext/nokogiri/xml_node_set.h +0 -1
  36. data/ext/nokogiri/xslt_stylesheet.c +2 -2
  37. data/lib/nokogiri/css/parser.rb +108 -90
  38. data/lib/nokogiri/css/parser.y +13 -2
  39. data/lib/nokogiri/css/tokenizer.rb +1 -1
  40. data/lib/nokogiri/css/tokenizer.rex +4 -4
  41. data/lib/nokogiri/css/xpath_visitor.rb +10 -3
  42. data/lib/nokogiri/html/document_fragment.rb +11 -1
  43. data/lib/nokogiri/nokogiri.jar +0 -0
  44. data/lib/nokogiri/version.rb +1 -1
  45. data/lib/nokogiri/xml/node.rb +58 -0
  46. data/lib/nokogiri/xml/node_set.rb +32 -18
  47. data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +78 -0
  48. data/test/css/test_nthiness.rb +21 -21
  49. data/test/css/test_parser.rb +17 -0
  50. data/test/html/test_attributes.rb +85 -0
  51. data/test/html/test_document_fragment.rb +7 -1
  52. data/test/test_css_cache.rb +5 -3
  53. data/test/xml/sax/test_parser.rb +9 -1
  54. data/test/xml/sax/test_push_parser.rb +60 -0
  55. data/test/xml/test_cdata.rb +1 -1
  56. data/test/xml/test_document.rb +5 -5
  57. data/test/xml/test_dtd.rb +4 -4
  58. data/test/xml/test_node.rb +89 -6
  59. data/test/xml/test_node_attributes.rb +3 -3
  60. data/test/xml/test_node_reparenting.rb +18 -0
  61. data/test/xml/test_node_set.rb +31 -4
  62. data/test/xml/test_reader.rb +13 -1
  63. data/test/xml/test_syntax_error.rb +3 -3
  64. data/test/xml/test_xpath.rb +8 -0
  65. metadata +25 -4
@@ -36,7 +36,6 @@ import java.util.Collections;
36
36
  import java.util.HashMap;
37
37
  import java.util.Map;
38
38
 
39
- import org.cyberneko.html.HTMLElements;
40
39
  import org.jruby.Ruby;
41
40
  import org.jruby.RubyArray;
42
41
  import org.jruby.RubyClass;
@@ -54,24 +53,6 @@ import org.jruby.runtime.load.BasicLibraryService;
54
53
  * @author Yoko Harada <yokolet@gmail.com>
55
54
  */
56
55
  public class NokogiriService implements BasicLibraryService {
57
-
58
- // nekohtml from version 1.9.13 they autocomplete tbody around
59
- // tr tags of a table - http://sourceforge.net/p/nekohtml/code/241/
60
- // this monkey patch undoes this autocompletion
61
- static class MonkeyPatchHTMLElements extends HTMLElements {
62
- static void patchIt() {
63
- Element[] array = ELEMENTS_ARRAY['T'-'A'];
64
- for(int i = 0; i < array.length; i++) {
65
- if (array[i].name.equals("TR")) {
66
- array[i] = new Element(TR, "TR", Element.BLOCK, TABLE, new short[]{TD,TH,TR,COLGROUP,DIV});
67
- }
68
- }
69
- }
70
- }
71
- static {
72
- MonkeyPatchHTMLElements.patchIt();
73
- }
74
-
75
56
  public boolean basicLoad(Ruby ruby) {
76
57
  init(ruby);
77
58
  return true;
@@ -33,21 +33,11 @@
33
33
  package nokogiri;
34
34
 
35
35
  import static java.lang.Math.max;
36
- import static nokogiri.internals.NokogiriHelpers.getCachedNodeOrCreate;
37
- import static nokogiri.internals.NokogiriHelpers.clearCachedNode;
38
- import static nokogiri.internals.NokogiriHelpers.clearXpathContext;
39
- import static nokogiri.internals.NokogiriHelpers.convertEncoding;
40
- import static nokogiri.internals.NokogiriHelpers.convertString;
41
- import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
42
- import static nokogiri.internals.NokogiriHelpers.nodeArrayToRubyArray;
43
- import static nokogiri.internals.NokogiriHelpers.nonEmptyStringOrNil;
44
- import static nokogiri.internals.NokogiriHelpers.rubyStringToString;
45
- import static nokogiri.internals.NokogiriHelpers.stringOrNil;
36
+ import static nokogiri.internals.NokogiriHelpers.*;
46
37
 
47
38
  import java.io.ByteArrayInputStream;
48
39
  import java.io.InputStream;
49
40
  import java.nio.ByteBuffer;
50
- import java.nio.charset.CharacterCodingException;
51
41
  import java.nio.charset.Charset;
52
42
  import java.util.ArrayList;
53
43
  import java.util.Iterator;
@@ -447,9 +437,6 @@ public class XmlNode extends RubyObject {
447
437
  return value.length() == 0 ? null : value;
448
438
  }
449
439
 
450
- public void post_add_child(ThreadContext context, XmlNode current, XmlNode child) {
451
- }
452
-
453
440
  /**
454
441
  * This method should be called after a node has been adopted in a new
455
442
  * document. This method will ensure that the node is renamed with the
@@ -464,9 +451,6 @@ public class XmlNode extends RubyObject {
464
451
  return;
465
452
  }
466
453
 
467
- // TODO: this feels kind of weird, why are we clearing the XmlNode
468
- // cache here !!!
469
- clearCachedNode(node);
470
454
  Element e = (Element) node;
471
455
 
472
456
  // disable error checking to prevent lines like the following
@@ -512,7 +496,6 @@ public class XmlNode extends RubyObject {
512
496
  // TODO: why do we need the namespace cache ?
513
497
  XmlNamespace.createFromAttr(context.getRuntime(), attr);
514
498
  }
515
- clearCachedNode(attr);
516
499
  NokogiriHelpers.renameNode(attr, nsUri, nodeName);
517
500
  }
518
501
  }
@@ -700,7 +683,7 @@ public class XmlNode extends RubyObject {
700
683
  // a node is blank if if it is a Text or CDATA node consisting of whitespace only
701
684
  if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.CDATA_SECTION_NODE) {
702
685
  String data = node.getTextContent();
703
- return context.runtime.newBoolean(data == null || data.isEmpty() || data.trim().isEmpty());
686
+ return context.runtime.newBoolean(data == null || isBlank(data));
704
687
  }
705
688
  return context.runtime.getFalse();
706
689
  }
@@ -1605,7 +1588,6 @@ public class XmlNode extends RubyObject {
1605
1588
  }
1606
1589
 
1607
1590
  other.relink_namespace(context);
1608
- // post_add_child(context, this, other);
1609
1591
 
1610
1592
  return nodeOrTags;
1611
1593
  }
@@ -1705,9 +1687,6 @@ public class XmlNode extends RubyObject {
1705
1687
 
1706
1688
  try {
1707
1689
  parentNode.replaceChild(otherNode, thisNode);
1708
- if (otherNode.getNodeType() != Node.TEXT_NODE) {
1709
- NokogiriHelpers.renameNode(otherNode, thisNode.getNamespaceURI(), otherNode.getNodeName());
1710
- }
1711
1690
  } catch (Exception e) {
1712
1691
  String prefix = "could not replace child: ";
1713
1692
  throw context.getRuntime().newRuntimeError(prefix + e.toString());
@@ -32,13 +32,13 @@
32
32
 
33
33
  package nokogiri;
34
34
 
35
- import static nokogiri.internals.NokogiriHelpers.isWhitespaceText;
36
35
  import static org.jruby.javasupport.util.RuntimeHelpers.invoke;
37
36
 
38
37
  import java.io.IOException;
39
38
  import java.io.InputStream;
40
39
 
41
40
  import nokogiri.internals.NokogiriHandler;
41
+ import nokogiri.internals.NokogiriHelpers;
42
42
  import nokogiri.internals.ParserContext;
43
43
  import nokogiri.internals.XmlSaxParser;
44
44
 
@@ -69,6 +69,7 @@ import org.xml.sax.SAXParseException;
69
69
  */
70
70
  @JRubyClass(name="Nokogiri::XML::SAX::ParserContext")
71
71
  public class XmlSaxParserContext extends ParserContext {
72
+
72
73
  protected static final String FEATURE_NAMESPACES =
73
74
  "http://xml.org/sax/features/namespaces";
74
75
  protected static final String FEATURE_NAMESPACE_PREFIXES =
@@ -80,20 +81,19 @@ public class XmlSaxParserContext extends ParserContext {
80
81
 
81
82
  protected AbstractSAXParser parser;
82
83
 
83
- protected NokogiriHandler handler = null;
84
- private IRubyObject replaceEntities;
85
- private IRubyObject recovery;
84
+ protected NokogiriHandler handler;
85
+ private boolean replaceEntities = true;
86
+ private boolean recovery = false;
86
87
 
87
88
  public XmlSaxParserContext(final Ruby ruby, RubyClass rubyClass) {
88
89
  super(ruby, rubyClass);
89
90
  }
90
91
 
91
92
  protected void initialize(Ruby runtime) {
92
- replaceEntities = runtime.getTrue();
93
- recovery = runtime.getFalse();
94
93
  try {
95
94
  parser = createParser();
96
- } catch (SAXException se) {
95
+ }
96
+ catch (SAXException se) {
97
97
  throw RaiseException.createNativeRaiseException(runtime, se);
98
98
  }
99
99
  }
@@ -123,9 +123,10 @@ public class XmlSaxParserContext extends ParserContext {
123
123
  public static IRubyObject parse_memory(ThreadContext context,
124
124
  IRubyObject klazz,
125
125
  IRubyObject data) {
126
- XmlSaxParserContext ctx = (XmlSaxParserContext) NokogiriService.XML_SAXPARSER_CONTEXT_ALLOCATOR.allocate(context.getRuntime(), (RubyClass) klazz);
127
- ctx.initialize(context.getRuntime());
128
- ctx.setInputSource(context, data, context.getRuntime().getNil());
126
+ final Ruby runtime = context.runtime;
127
+ XmlSaxParserContext ctx = newInstance(runtime, (RubyClass) klazz);
128
+ ctx.initialize(runtime);
129
+ ctx.setInputSource(context, data, runtime.getNil());
129
130
  return ctx;
130
131
  }
131
132
 
@@ -137,7 +138,8 @@ public class XmlSaxParserContext extends ParserContext {
137
138
  public static IRubyObject parse_file(ThreadContext context,
138
139
  IRubyObject klazz,
139
140
  IRubyObject data) {
140
- XmlSaxParserContext ctx = (XmlSaxParserContext) NokogiriService.XML_SAXPARSER_CONTEXT_ALLOCATOR.allocate(context.getRuntime(), (RubyClass) klazz);
141
+ final Ruby runtime = context.runtime;
142
+ XmlSaxParserContext ctx = newInstance(runtime, (RubyClass) klazz);
141
143
  ctx.initialize(context.getRuntime());
142
144
  ctx.setInputSourceFile(context, data);
143
145
  return ctx;
@@ -155,26 +157,28 @@ public class XmlSaxParserContext extends ParserContext {
155
157
  IRubyObject data,
156
158
  IRubyObject enc) {
157
159
  //int encoding = (int)enc.convertToInteger().getLongValue();
158
- XmlSaxParserContext ctx = (XmlSaxParserContext) NokogiriService.XML_SAXPARSER_CONTEXT_ALLOCATOR.allocate(context.getRuntime(), (RubyClass) klazz);
159
- ctx.initialize(context.getRuntime());
160
- ctx.setInputSource(context, data, context.getRuntime().getNil());
160
+ final Ruby runtime = context.runtime;
161
+ XmlSaxParserContext ctx = newInstance(runtime, (RubyClass) klazz);
162
+ ctx.initialize(runtime);
163
+ ctx.setInputSource(context, data, runtime.getNil());
161
164
  return ctx;
162
165
  }
163
166
 
164
167
  /**
165
- * Create a new parser context that will read from a raw input
166
- * stream. Not a JRuby method. Meant to be run in a separate
167
- * thread by XmlSaxPushParser.
168
+ * Create a new parser context that will read from a raw input stream.
169
+ * Meant to be run in a separate thread by XmlSaxPushParser.
168
170
  */
169
- public static IRubyObject parse_stream(ThreadContext context,
170
- IRubyObject klazz,
171
- InputStream stream) {
172
- XmlSaxParserContext ctx = (XmlSaxParserContext) NokogiriService.XML_SAXPARSER_CONTEXT_ALLOCATOR.allocate(context.getRuntime(), (RubyClass) klazz);
173
- ctx.initialize(context.getRuntime());
171
+ static XmlSaxParserContext parse_stream(final Ruby runtime, RubyClass klazz, InputStream stream) {
172
+ XmlSaxParserContext ctx = newInstance(runtime, klazz);
173
+ ctx.initialize(runtime);
174
174
  ctx.setInputSource(stream);
175
175
  return ctx;
176
176
  }
177
177
 
178
+ private static XmlSaxParserContext newInstance(final Ruby runtime, final RubyClass klazz) {
179
+ return (XmlSaxParserContext) NokogiriService.XML_SAXPARSER_CONTEXT_ALLOCATOR.allocate(runtime, klazz);
180
+ }
181
+
178
182
  /**
179
183
  * Set a property of the underlying parser.
180
184
  */
@@ -191,30 +195,25 @@ public class XmlSaxParserContext extends ParserContext {
191
195
  parser.setErrorHandler(handler);
192
196
  }
193
197
 
194
- public NokogiriHandler getNokogiriHandler() {
195
- return handler;
196
- }
198
+ public final NokogiriHandler getNokogiriHandler() { return handler; }
197
199
 
198
200
  /**
199
201
  * Perform any initialization prior to parsing with the handler
200
202
  * <code>handlerRuby</code>. Convenience hook for subclasses.
201
203
  */
202
- protected void preParse(ThreadContext context,
203
- IRubyObject handlerRuby,
204
- NokogiriHandler handler) {
204
+ protected void preParse(Ruby runtime, IRubyObject handlerRuby, NokogiriHandler handler) {
205
205
  ((XmlSaxParser) parser).setXmlDeclHandler(handler);
206
- if(recovery.isTrue()) {
207
- try {
208
- ((XmlSaxParser) parser).setFeature(FEATURE_CONTINUE_AFTER_FATAL_ERROR, true);
209
- } catch(Exception e) {
210
- throw RaiseException.createNativeRaiseException(context.getRuntime(), e);
211
- }
206
+ if (recovery) {
207
+ try {
208
+ parser.setFeature(FEATURE_CONTINUE_AFTER_FATAL_ERROR, true);
209
+ }
210
+ catch (Exception e) {
211
+ throw RaiseException.createNativeRaiseException(runtime, e);
212
+ }
212
213
  }
213
214
  }
214
215
 
215
- protected void postParse(ThreadContext context,
216
- IRubyObject handlerRuby,
217
- NokogiriHandler handler) {
216
+ protected void postParse(Ruby runtime, IRubyObject handlerRuby, NokogiriHandler handler) {
218
217
  // noop
219
218
  }
220
219
 
@@ -223,61 +222,56 @@ public class XmlSaxParserContext extends ParserContext {
223
222
  }
224
223
 
225
224
  @JRubyMethod
226
- public IRubyObject parse_with(ThreadContext context,
227
- IRubyObject handlerRuby) {
228
- Ruby ruby = context.getRuntime();
229
-
230
- if(!invoke(context, handlerRuby, "respond_to?",
231
- ruby.newSymbol("document")).isTrue()) {
232
- String msg = "argument must respond_to document";
233
- throw ruby.newArgumentError(msg);
225
+ public IRubyObject parse_with(ThreadContext context, IRubyObject handlerRuby) {
226
+ final Ruby runtime = context.getRuntime();
227
+
228
+ if(!invoke(context, handlerRuby, "respond_to?", runtime.newSymbol("document")).isTrue()) {
229
+ throw runtime.newArgumentError("argument must respond_to document");
234
230
  }
235
231
 
236
- handler = new NokogiriHandler(ruby, handlerRuby);
237
- preParse(context, handlerRuby, handler);
232
+ NokogiriHandler handler = this.handler = new NokogiriHandler(runtime, handlerRuby);
233
+ preParse(runtime, handlerRuby, handler);
238
234
 
239
235
  setContentHandler(handler);
240
236
  setErrorHandler(handler);
241
237
 
242
238
  try{
243
- setProperty("http://xml.org/sax/properties/lexical-handler",
244
- handler);
245
- } catch(Exception ex) {
246
- throw ruby.newRuntimeError(
247
- "Problem while creating XML SAX Parser: " + ex.toString());
239
+ setProperty("http://xml.org/sax/properties/lexical-handler", handler);
240
+ }
241
+ catch (Exception ex) {
242
+ throw runtime.newRuntimeError("Problem while creating XML SAX Parser: " + ex.toString());
248
243
  }
249
244
 
250
245
  try{
251
246
  try {
252
247
  do_parse();
253
- } catch(SAXParseException spe) {
248
+ }
249
+ catch (SAXParseException ex) {
254
250
  // A bad document (<foo><bar></foo>) should call the
255
251
  // error handler instead of raising a SAX exception.
256
252
 
257
- // However, an EMPTY document should raise a
258
- // RuntimeError. This is a bit kludgy, but AFAIK SAX
259
- // doesn't distinguish between empty and bad whereas
260
- // Nokogiri does.
261
- String message = spe.getMessage();
262
- if ("Premature end of file.".matches(message) && stringDataSize < 1) {
263
- throw ruby.newRuntimeError(
264
- "couldn't parse document: " + message);
265
- } else {
266
- handler.error(spe);
253
+ // However, an EMPTY document should raise a RuntimeError.
254
+ // This is a bit kludgy, but AFAIK SAX doesn't distinguish
255
+ // between empty and bad whereas Nokogiri does.
256
+ String message = ex.getMessage();
257
+ if (message != null && message.contains("Premature end of file.") && stringDataSize < 1) {
258
+ throw runtime.newRuntimeError("couldn't parse document: " + message);
267
259
  }
268
-
260
+ handler.error(ex);
269
261
  }
270
- } catch(SAXException se) {
271
- throw RaiseException.createNativeRaiseException(ruby, se);
272
- } catch(IOException ioe) {
273
- throw ruby.newIOErrorFromException(ioe);
262
+ }
263
+ catch (SAXException ex) {
264
+ throw RaiseException.createNativeRaiseException(runtime, ex);
265
+ }
266
+ catch (IOException ex) {
267
+ throw runtime.newIOErrorFromException(ex);
274
268
  }
275
269
 
276
- postParse(context, handlerRuby, handler);
270
+ postParse(runtime, handlerRuby, handler);
277
271
 
278
272
  //maybeTrimLeadingAndTrailingWhitespace(context, handlerRuby);
279
273
 
280
- return ruby.getNil();
274
+ return runtime.getNil();
281
275
  }
282
276
 
283
277
  /**
@@ -288,17 +282,14 @@ public class XmlSaxParserContext extends ParserContext {
288
282
  * @return
289
283
  */
290
284
  @JRubyMethod(name = "replace_entities=")
291
- public IRubyObject set_replace_entities(ThreadContext context,
292
- IRubyObject value) {
293
- if (!value.isTrue()) replaceEntities = context.getRuntime().getFalse();
294
- else replaceEntities = context.getRuntime().getTrue();
295
-
285
+ public IRubyObject set_replace_entities(ThreadContext context, IRubyObject value) {
286
+ replaceEntities = value.isTrue();
296
287
  return this;
297
288
  }
298
289
 
299
290
  @JRubyMethod(name="replace_entities")
300
291
  public IRubyObject get_replace_entities(ThreadContext context) {
301
- return replaceEntities;
292
+ return context.runtime.newBoolean(replaceEntities);
302
293
  }
303
294
 
304
295
  /**
@@ -309,21 +300,16 @@ public class XmlSaxParserContext extends ParserContext {
309
300
  * @return
310
301
  */
311
302
  @JRubyMethod(name = "recovery=")
312
- public IRubyObject set_recovery(ThreadContext context,
313
- IRubyObject value) {
314
- if (!value.isTrue()) recovery = context.getRuntime().getFalse();
315
- else recovery = context.getRuntime().getTrue();
316
-
303
+ public IRubyObject set_recovery(ThreadContext context, IRubyObject value) {
304
+ recovery = value.isTrue();
317
305
  return this;
318
306
  }
319
307
 
320
308
  @JRubyMethod(name="recovery")
321
309
  public IRubyObject get_recovery(ThreadContext context) {
322
- return recovery;
310
+ return context.runtime.newBoolean(recovery);
323
311
  }
324
312
 
325
-
326
-
327
313
  /**
328
314
  * If the handler's document is a FragmentHandler, attempt to trim
329
315
  * leading and trailing whitespace.
@@ -331,12 +317,9 @@ public class XmlSaxParserContext extends ParserContext {
331
317
  * This is a bit hackish and depends heavily on the internals of
332
318
  * FragmentHandler.
333
319
  */
334
- protected void maybeTrimLeadingAndTrailingWhitespace(ThreadContext context,
335
- IRubyObject parser) {
336
- final String path = "Nokogiri::XML::FragmentHandler";
320
+ protected void maybeTrimLeadingAndTrailingWhitespace(ThreadContext context, IRubyObject parser) {
337
321
  RubyObjectAdapter adapter = JavaEmbedUtils.newObjectAdapter();
338
- RubyModule mod =
339
- context.getRuntime().getClassFromPath(path);
322
+ RubyModule mod = context.getRuntime().getClassFromPath("Nokogiri::XML::FragmentHandler");
340
323
 
341
324
  IRubyObject handler = adapter.getInstanceVariable(parser, "@document");
342
325
  if (handler == null || handler.isNil() || !adapter.isKindOf(handler, mod))
@@ -354,19 +337,15 @@ public class XmlSaxParserContext extends ParserContext {
354
337
  for (;;) {
355
338
  children = adapter.callMethod(doc, "children");
356
339
  IRubyObject first = adapter.callMethod(children, "first");
357
- if (isWhitespaceText(context, first))
358
- adapter.callMethod(first, "unlink");
359
- else
360
- break;
340
+ if (NokogiriHelpers.isBlank(first)) adapter.callMethod(first, "unlink");
341
+ else break;
361
342
  }
362
343
 
363
344
  for (;;) {
364
345
  children = adapter.callMethod(doc, "children");
365
346
  IRubyObject last = adapter.callMethod(children, "last");
366
- if (isWhitespaceText(context, last))
367
- adapter.callMethod(last, "unlink");
368
- else
369
- break;
347
+ if (NokogiriHelpers.isBlank(last)) adapter.callMethod(last, "unlink");
348
+ else break;
370
349
  }
371
350
 
372
351
  // While we have a document, normalize it.
@@ -375,15 +354,16 @@ public class XmlSaxParserContext extends ParserContext {
375
354
 
376
355
  @JRubyMethod(name="column")
377
356
  public IRubyObject column(ThreadContext context) {
378
- Integer number = handler.getColumn();
357
+ final Integer number = handler.getColumn();
379
358
  if (number == null) return context.getRuntime().getNil();
380
- else return RubyFixnum.newFixnum(context.getRuntime(), number.longValue());
359
+ return RubyFixnum.newFixnum(context.getRuntime(), number.longValue());
381
360
  }
382
361
 
383
362
  @JRubyMethod(name="line")
384
363
  public IRubyObject line(ThreadContext context) {
385
- Integer number = handler.getLine();
364
+ final Integer number = handler.getLine();
386
365
  if (number == null) return context.getRuntime().getNil();
387
- else return RubyFixnum.newFixnum(context.getRuntime(), number.longValue());
366
+ return RubyFixnum.newFixnum(context.getRuntime(), number.longValue());
388
367
  }
368
+
389
369
  }