nokogiri 1.5.5.rc2-java → 1.5.5.rc3-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.

@@ -14,6 +14,7 @@
14
14
  * JRuby で xpath を namespace 付きで指定した場合に、エラーが発生する。pull request #681 (ありがとう, Piotr Szmielew)
15
15
  * JRuby で Nokogiri::XML::Node を継承したクラスを定義すると、namespace が表示されない。 #695
16
16
  * JRuby で RDF::RDFXML::Writer をインスタンス化しようとすると NAMESPACE_ERR (org.w3c.dom.DOMException) が発生する. #683
17
+ * JRuby で xpath に namespaces を指定すると例外が発生する. #493
17
18
 
18
19
 
19
20
  == 1.5.4 / 2012年6月12日
@@ -14,6 +14,7 @@
14
14
  * JRuby raises exception when xpath with namespace is specified. pull request #681 (Thanks, Piotr Szmielew)
15
15
  * JRuby renders nodes without their namespace when subclassing Node. #695
16
16
  * JRuby raises NAMESPACE_ERR (org.w3c.dom.DOMException) while instantiating RDF::RDFXML::Writer. #683
17
+ * JRuby is not able to use namespaces in xpath. #493
17
18
 
18
19
 
19
20
  == 1.5.4 / 2012-06-12
@@ -1,10 +1,10 @@
1
1
  = Nokogiri (鋸)
2
2
 
3
3
  * http://nokogiri.org/
4
- * http://github.com/tenderlove/nokogiri/wikis
5
- * http://github.com/tenderlove/nokogiri/tree/master
4
+ * http://github.com/sparklemotion/nokogiri/wikis
5
+ * http://github.com/sparklemotion/nokogiri/tree/master
6
6
  * http://groups.google.com/group/nokogiri-list
7
- * http://github.com/tenderlove/nokogiri/issues
7
+ * http://github.com/sparklemotion/nokogiri/issues
8
8
 
9
9
  == DESCRIPTION:
10
10
 
@@ -29,9 +29,9 @@ XML/HTMLの高速な解析と探索検索、ならびにCSS3セレクタとXPath
29
29
 
30
30
  * http://groups.google.com/group/nokogiri-list
31
31
 
32
- {バグ報告}[http://github.com/tenderlove/nokogiri/issues]
32
+ {バグ報告}[http://github.com/sparklemotion/nokogiri/issues]
33
33
 
34
- * http://github.com/tenderlove/nokogiri/issues
34
+ * http://github.com/sparklemotion/nokogiri/issues
35
35
 
36
36
  IRCのチャンネルはfreenodeの #nokogiri です。
37
37
 
@@ -1,10 +1,10 @@
1
- = Nokogiri {<img src="https://secure.travis-ci.org/tenderlove/nokogiri.png?rvm=1.9.3" />}[http://travis-ci.org/tenderlove/nokogiri]
1
+ = Nokogiri {<img src="https://secure.travis-ci.org/sparklemotion/nokogiri.png?rvm=1.9.3" />}[http://travis-ci.org/sparklemotion/nokogiri]
2
2
 
3
3
  * http://nokogiri.org
4
- * http://github.com/tenderlove/nokogiri/wikis
5
- * http://github.com/tenderlove/nokogiri/tree/master
4
+ * http://github.com/sparklemotion/nokogiri/wikis
5
+ * http://github.com/sparklemotion/nokogiri/tree/master
6
6
  * http://groups.google.com/group/nokogiri-talk
7
- * http://github.com/tenderlove/nokogiri/issues
7
+ * http://github.com/sparklemotion/nokogiri/issues
8
8
 
9
9
  == DESCRIPTION:
10
10
 
@@ -34,10 +34,10 @@ is available here:
34
34
 
35
35
  * http://groups.google.com/group/nokogiri-talk
36
36
 
37
- The {bug tracker}[http://github.com/tenderlove/nokogiri/issues]
37
+ The {bug tracker}[http://github.com/sparklemotion/nokogiri/issues]
38
38
  is available here:
39
39
 
40
- * http://github.com/tenderlove/nokogiri/issues
40
+ * http://github.com/sparklemotion/nokogiri/issues
41
41
 
42
42
  The IRC channel is #nokogiri on freenode.
43
43
 
@@ -46,9 +46,9 @@ The IRC channel is #nokogiri on freenode.
46
46
  require 'nokogiri'
47
47
  require 'open-uri'
48
48
 
49
- # Get a Nokogiri::HTML:Document for the page we’re interested in...
49
+ # Get a Nokogiri::HTML::Document for the page we’re interested in...
50
50
 
51
- doc = Nokogiri::HTML(open('http://www.google.com/search?q=tenderlove'))
51
+ doc = Nokogiri::HTML(open('http://www.google.com/search?q=sparklemotion'))
52
52
 
53
53
  # Do funky things with it using Nokogiri::XML::Node methods...
54
54
 
@@ -151,7 +151,7 @@ Then run rake:
151
151
 
152
152
  Copyright (c) 2008 - 2012:
153
153
 
154
- * {Aaron Patterson}[http://tenderlovemaking.com]
154
+ * {Aaron Patterson}[http://sparklemotionmaking.com]
155
155
  * {Mike Dalessio}[http://mike.daless.io]
156
156
  * {Charles Nutter}[http://blog.headius.com]
157
157
  * {Sergio Arbeo}[http://www.serabe.com]
data/ROADMAP.md CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  ## overhaul serialize/pretty printing API
4
4
 
5
- * https://github.com/tenderlove/nokogiri/issues/530
5
+ * https://github.com/sparklemotion/nokogiri/issues/530
6
6
  XHTML formatting can't be turned off
7
7
 
8
- * https://github.com/tenderlove/nokogiri/issues/415
8
+ * https://github.com/sparklemotion/nokogiri/issues/415
9
9
  XML formatting should be no formatting
10
10
 
11
11
 
@@ -16,35 +16,35 @@
16
16
 
17
17
  ## Node should not be Enumerable; and should have a better attributes API
18
18
 
19
- * https://github.com/tenderlove/nokogiri/issues/679
19
+ * https://github.com/sparklemotion/nokogiri/issues/679
20
20
  Mixing in Enumerable has some unintended consequences; plus we want to improve the attributes API
21
21
 
22
- * (closed) https://github.com/tenderlove/nokogiri/issues/666
22
+ * (closed) https://github.com/sparklemotion/nokogiri/issues/666
23
23
  Some ideas for a better attributes API?
24
24
 
25
25
 
26
26
  ## improve CSS query parsing
27
27
 
28
- * https://github.com/tenderlove/nokogiri/issues/528
28
+ * https://github.com/sparklemotion/nokogiri/issues/528
29
29
  support `:not()` with a nontrivial argument, like `:not(div p.c)`
30
30
 
31
- * https://github.com/tenderlove/nokogiri/issues/451
31
+ * https://github.com/sparklemotion/nokogiri/issues/451
32
32
  chained :not pseudoselectors
33
33
 
34
34
  * better jQuery selector support:
35
- * https://github.com/tenderlove/nokogiri/issues/621
36
- * https://github.com/tenderlove/nokogiri/issues/342
37
- * https://github.com/tenderlove/nokogiri/issues/628
38
- * https://github.com/tenderlove/nokogiri/issues/652
39
- * https://github.com/tenderlove/nokogiri/issues/688
35
+ * https://github.com/sparklemotion/nokogiri/issues/621
36
+ * https://github.com/sparklemotion/nokogiri/issues/342
37
+ * https://github.com/sparklemotion/nokogiri/issues/628
38
+ * https://github.com/sparklemotion/nokogiri/issues/652
39
+ * https://github.com/sparklemotion/nokogiri/issues/688
40
40
 
41
- * https://github.com/tenderlove/nokogiri/issues/394
41
+ * https://github.com/sparklemotion/nokogiri/issues/394
42
42
  nth-of-type is wrong, and possibly other selectors as well
43
43
 
44
- * https://github.com/tenderlove/nokogiri/issues/309
44
+ * https://github.com/sparklemotion/nokogiri/issues/309
45
45
  incorrect query being executed
46
46
 
47
- * https://github.com/tenderlove/nokogiri/issues/350
47
+ * https://github.com/sparklemotion/nokogiri/issues/350
48
48
  :has is wrong?
49
49
 
50
50
 
@@ -52,15 +52,15 @@
52
52
 
53
53
  * there are a few tickets about searches not working properly if you
54
54
  use or do not use the context node as part of the search.
55
- - https://github.com/tenderlove/nokogiri/issues/213
56
- - https://github.com/tenderlove/nokogiri/issues/370
57
- - https://github.com/tenderlove/nokogiri/issues/454
58
- - https://github.com/tenderlove/nokogiri/issues/572
55
+ - https://github.com/sparklemotion/nokogiri/issues/213
56
+ - https://github.com/sparklemotion/nokogiri/issues/370
57
+ - https://github.com/sparklemotion/nokogiri/issues/454
58
+ - https://github.com/sparklemotion/nokogiri/issues/572
59
59
 
60
60
 
61
61
  ## Better Syntax for custom XPath function handler
62
62
 
63
- * https://github.com/tenderlove/nokogiri/pull/464
63
+ * https://github.com/sparklemotion/nokogiri/pull/464
64
64
 
65
65
 
66
66
  ## Better Syntax around Node#xpath and NodeSet#xpath
@@ -68,7 +68,7 @@
68
68
  * look at those methods, and use of Node#extract_params in Node#{css,search}
69
69
  * we should standardize on a hash of options for these and other calls
70
70
  * what should NodeSet#xpath return?
71
- * https://github.com/tenderlove/nokogiri/issues/656
71
+ * https://github.com/sparklemotion/nokogiri/issues/656
72
72
 
73
73
  ## Encoding
74
74
 
data/Rakefile CHANGED
@@ -145,7 +145,12 @@ end
145
145
 
146
146
  require 'tasks/test'
147
147
 
148
+ task :java_debug do
149
+ ENV['JAVA_OPTS'] = '-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y' if java? && ENV['JAVA_DEBUG']
150
+ end
151
+
148
152
  Rake::Task[:test].prerequisites << :compile
153
+ Rake::Task[:test].prerequisites << :java_debug
149
154
  Rake::Task[:test].prerequisites << :check_extra_deps unless java?
150
155
  if Hoe.plugins.include?(:debugging)
151
156
  ['valgrind', 'valgrind:mem', 'valgrind:mem0'].each do |task_name|
@@ -16,9 +16,9 @@ OHAI! Thank you for asking this question!
16
16
  Team Nokogiri gets asked this pretty frequently. Just a sample from
17
17
  the historical record:
18
18
 
19
- * [Issue #274](https://github.com/tenderlove/nokogiri/issues/274)
20
- * [Issue #371](https://github.com/tenderlove/nokogiri/issues/371)
21
- * [A commit removing nokogiri.gemspec](https://github.com/tenderlove/nokogiri/commit/7f17a643a05ca381d65131515b54d4a3a61ca2e1#commitcomment-667477)
19
+ * [Issue #274](https://github.com/sparklemotion/nokogiri/issues/274)
20
+ * [Issue #371](https://github.com/sparklemotion/nokogiri/issues/371)
21
+ * [A commit removing nokogiri.gemspec](https://github.com/sparklemotion/nokogiri/commit/7f17a643a05ca381d65131515b54d4a3a61ca2e1#commitcomment-667477)
22
22
  * [A nokogiri-talk thread](http://groups.google.com/group/nokogiri-talk/browse_thread/thread/4706b002e492d23f)
23
23
  * [Another nokogiri-talk thread](http://groups.google.com/group/nokogiri-talk/browse_thread/thread/0b201bb80ea3eea0)
24
24
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2011:
4
+ * Copyright (c) 2008 - 2012:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2011:
4
+ * Copyright (c) 2008 - 2012:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -32,20 +32,15 @@
32
32
 
33
33
  package nokogiri;
34
34
 
35
- import static nokogiri.internals.NokogiriHelpers.rubyStringToString;
36
35
  import nokogiri.internals.SaveContextVisitor;
37
36
 
38
37
  import org.jruby.Ruby;
39
38
  import org.jruby.RubyArray;
40
39
  import org.jruby.RubyClass;
41
40
  import org.jruby.anno.JRubyClass;
42
- import org.jruby.anno.JRubyMethod;
43
41
  import org.jruby.javasupport.util.RuntimeHelpers;
44
42
  import org.jruby.runtime.ThreadContext;
45
- import org.jruby.runtime.builtin.IRubyObject;
46
- import org.w3c.dom.Attr;
47
43
  import org.w3c.dom.Element;
48
- import org.w3c.dom.NamedNodeMap;
49
44
  import org.w3c.dom.Node;
50
45
 
51
46
  /**
@@ -79,41 +74,6 @@ public class XmlElement extends XmlNode {
79
74
  }
80
75
  }
81
76
  }
82
-
83
- @Override
84
- public boolean isElement() { return true; }
85
-
86
- @Override
87
- public void relink_namespace(ThreadContext context) {
88
- Element e = (Element) node;
89
-
90
- e.getOwnerDocument().renameNode(e, e.lookupNamespaceURI(e.getPrefix()), e.getNodeName());
91
-
92
- if(e.hasAttributes()) {
93
- NamedNodeMap attrs = e.getAttributes();
94
-
95
- for(int i = 0; i < attrs.getLength(); i++) {
96
- Attr attr = (Attr) attrs.item(i);
97
- String nsUri = "";
98
- String prefix = attr.getPrefix();
99
- String nodeName = attr.getNodeName();
100
- if("xml".equals(prefix)) {
101
- nsUri = "http://www.w3.org/XML/1998/namespace";
102
- } else if("xmlns".equals(prefix) || nodeName.equals("xmlns")) {
103
- nsUri = "http://www.w3.org/2000/xmlns/";
104
- } else {
105
- nsUri = attr.lookupNamespaceURI(nodeName);
106
- }
107
-
108
- e.getOwnerDocument().renameNode(attr, nsUri, nodeName);
109
-
110
- }
111
- }
112
-
113
- if(e.hasChildNodes()) {
114
- ((XmlNodeSet) children(context)).relink_namespace(context);
115
- }
116
- }
117
77
 
118
78
  @Override
119
79
  public void accept(ThreadContext context, SaveContextVisitor visitor) {
@@ -409,7 +409,10 @@ public class XmlNode extends RubyObject {
409
409
 
410
410
  public boolean isComment() { return false; }
411
411
 
412
- public boolean isElement() { return false; }
412
+ public boolean isElement() {
413
+ if (node instanceof Element) return true; // in case of subclassing
414
+ else return false;
415
+ }
413
416
 
414
417
  public boolean isProcessingInstruction() { return false; }
415
418
 
@@ -443,7 +446,33 @@ public class XmlNode extends RubyObject {
443
446
  }
444
447
 
445
448
  public void relink_namespace(ThreadContext context) {
446
- //this should delegate to subclasses' implementation
449
+ if (node instanceof Element) {
450
+ Element e = (Element) node;
451
+ e.getOwnerDocument().renameNode(e, e.lookupNamespaceURI(e.getPrefix()), e.getNodeName());
452
+
453
+ if (e.hasAttributes()) {
454
+ NamedNodeMap attrs = e.getAttributes();
455
+
456
+ for (int i = 0; i < attrs.getLength(); i++) {
457
+ Attr attr = (Attr) attrs.item(i);
458
+ String nsUri = "";
459
+ String prefix = attr.getPrefix();
460
+ String nodeName = attr.getNodeName();
461
+ if ("xml".equals(prefix)) {
462
+ nsUri = "http://www.w3.org/XML/1998/namespace";
463
+ } else if ("xmlns".equals(prefix) || nodeName.equals("xmlns")) {
464
+ nsUri = "http://www.w3.org/2000/xmlns/";
465
+ } else {
466
+ nsUri = attr.getNamespaceURI();
467
+ }
468
+ e.getOwnerDocument().renameNode(attr, nsUri, nodeName);
469
+ }
470
+ }
471
+
472
+ if (e.hasChildNodes()) {
473
+ ((XmlNodeSet) children(context)).relink_namespace(context);
474
+ }
475
+ }
447
476
  }
448
477
 
449
478
  // Users might extend XmlNode. This method works for such a case.
@@ -40,6 +40,9 @@ import java.io.IOException;
40
40
  import java.util.ArrayDeque;
41
41
  import java.util.Stack;
42
42
 
43
+ import nokogiri.internals.NokogiriEntityResolver;
44
+ import nokogiri.internals.ParserContext;
45
+ import nokogiri.internals.ParserContext.Options;
43
46
  import nokogiri.internals.ReaderNode;
44
47
  import nokogiri.internals.ReaderNode.ElementNode;
45
48
 
@@ -54,6 +57,7 @@ import org.jruby.anno.JRubyClass;
54
57
  import org.jruby.anno.JRubyMethod;
55
58
  import org.jruby.exceptions.RaiseException;
56
59
  import org.jruby.javasupport.util.RuntimeHelpers;
60
+ import org.jruby.lexer.yacc.SyntaxException;
57
61
  import org.jruby.runtime.ThreadContext;
58
62
  import org.jruby.runtime.builtin.IRubyObject;
59
63
  import org.jruby.util.ByteList;
@@ -97,20 +101,22 @@ public class XmlReader extends RubyObject {
97
101
  public Object clone() throws CloneNotSupportedException {
98
102
  return super.clone();
99
103
  }
100
-
104
+
101
105
  public void init(Ruby runtime) {
102
106
  nodeQueue = new ArrayDeque<ReaderNode>();
103
107
  nodeQueue.add(new ReaderNode.EmptyNode(runtime));
104
108
  }
105
109
 
106
- private void parseRubyString(ThreadContext context, RubyString content){
110
+ private void parseRubyString(ThreadContext context, RubyString content, IRubyObject url, Options options){
107
111
  Ruby ruby = context.getRuntime();
108
112
  try {
109
113
  this.setState(XML_TEXTREADER_MODE_READING);
110
- XMLReader reader = this.createReader(ruby);
114
+ XMLReader reader = this.createReader(ruby, options);
111
115
  ByteList byteList = content.getByteList();
112
116
  ByteArrayInputStream bais = new ByteArrayInputStream(byteList.unsafeBytes(), byteList.begin(), byteList.length());
113
- reader.parse(new InputSource(bais));
117
+ InputSource inputSource = new InputSource(bais);
118
+ ParserContext.setUrl(context, inputSource, url);
119
+ reader.parse(inputSource);
114
120
  this.setState(XML_TEXTREADER_MODE_CLOSED);
115
121
  } catch (SAXParseException spe) {
116
122
  this.setState(XML_TEXTREADER_MODE_ERROR);
@@ -188,16 +194,26 @@ public class XmlReader extends RubyObject {
188
194
  reader.init(runtime);
189
195
  reader.setInstanceVariable("@source", args[0]);
190
196
  reader.setInstanceVariable("@errors", runtime.newArray());
197
+ IRubyObject url = context.nil;
198
+ if (args.length > 1) url = args[1];
191
199
  if (args.length > 2) reader.setInstanceVariable("@encoding", args[2]);
192
200
 
193
201
  RubyString content = RuntimeHelpers.invoke(context, args[0], "read").convertToString();
194
- reader.parseRubyString(context, content);
202
+
203
+ Options options;
204
+ if (args.length > 3) {
205
+ options = new ParserContext.Options((Long)args[3].toJava(Long.class));
206
+ } else {
207
+ // use the default options RECOVER | NONET
208
+ options = new ParserContext.Options(2048 | 1);
209
+ }
210
+ reader.parseRubyString(context, content, url, options);
195
211
  return reader;
196
212
  }
197
213
 
198
214
  @JRubyMethod(meta = true, rest = true)
199
215
  public static IRubyObject from_memory(ThreadContext context, IRubyObject cls, IRubyObject args[]) {
200
- // args[0]: string, args[1]: url, args[2]: encoding, args[3]: options
216
+ // args[0]: string, args[1]: url, args[2]: encoding, args[3]: options
201
217
  Ruby runtime = context.getRuntime();
202
218
  // Not nil allowed!
203
219
  if(args[0].isNil()) throw runtime.newArgumentError("string cannot be nil");
@@ -206,9 +222,18 @@ public class XmlReader extends RubyObject {
206
222
  reader.init(runtime);
207
223
  reader.setInstanceVariable("@source", args[0]);
208
224
  reader.setInstanceVariable("@errors", runtime.newArray());
225
+ IRubyObject url = context.nil;
226
+ if (args.length > 1) url = args[1];
209
227
  if (args.length > 2) reader.setInstanceVariable("@encoding", args[2]);
210
228
 
211
- reader.parseRubyString(context, args[0].convertToString());
229
+ Options options;
230
+ if (args.length > 3) {
231
+ options = new ParserContext.Options((Long)args[3].toJava(Long.class));
232
+ } else {
233
+ // use the default options RECOVER | NONET
234
+ options = new ParserContext.Options(2048 | 1);
235
+ }
236
+ reader.parseRubyString(context, args[0].convertToString(), url, options);
212
237
  return reader;
213
238
  }
214
239
 
@@ -227,13 +252,13 @@ public class XmlReader extends RubyObject {
227
252
  if (current.depth < 0) return null;
228
253
  if (!current.hasChildren) return null;
229
254
  StringBuffer sb = new StringBuffer();
230
- int currentDepth = (Integer)current.depth;
255
+ int currentDepth = current.depth;
231
256
  int inner = 0;
232
257
  for (ReaderNode node : nodeQueue) {
233
- if (((Integer)node.depth) == currentDepth && node.getName().equals(current.getName())) {
258
+ if (node.depth == currentDepth && node.getName().equals(current.getName())) {
234
259
  inner++;
235
260
  }
236
- if (((Integer)node.depth) > currentDepth) {
261
+ if (node.depth > currentDepth) {
237
262
  sb.append(node.getString());
238
263
  }
239
264
  if (inner == 2) break;
@@ -249,11 +274,11 @@ public class XmlReader extends RubyObject {
249
274
  private String getOuterXml(ArrayDeque<ReaderNode> nodeQueue, ReaderNode current) {
250
275
  if (current.depth < 0) return null;
251
276
  StringBuffer sb = new StringBuffer();
252
- int initialDepth = (Integer)current.depth;
277
+ int initialDepth = current.depth;
253
278
  int inner = 0;
254
279
  for (ReaderNode node : nodeQueue) {
255
- if (((Integer)node.depth) >= initialDepth) {
256
- if (((Integer)node.depth) == initialDepth && node.getName().equals(current.getName())) {
280
+ if (node.depth >= initialDepth) {
281
+ if (node.depth == initialDepth && node.getName().equals(current.getName())) {
257
282
  inner++;
258
283
  }
259
284
 
@@ -331,7 +356,7 @@ public class XmlReader extends RubyObject {
331
356
  return nodeQueue.peek().getXmlVersion();
332
357
  }
333
358
 
334
- protected XMLReader createReader(final Ruby ruby) {
359
+ protected XMLReader createReader(final Ruby ruby, Options options) {
335
360
  DefaultHandler2 handler = new DefaultHandler2() {
336
361
 
337
362
  Stack<String> langStack;
@@ -401,6 +426,13 @@ public class XmlReader extends RubyObject {
401
426
  elementStack.push((ReaderNode.ElementNode)readerNode);
402
427
  }
403
428
 
429
+ @Override
430
+ public void skippedEntity(String name) {
431
+ XmlSyntaxError error = XmlSyntaxError.createNokogiriXmlSyntaxError(ruby);
432
+ error.setException(new Exception("Unknown entity " + name));
433
+ throw new RaiseException(error);
434
+ }
435
+
404
436
  @Override
405
437
  public void warning(SAXParseException ex) throws SAXParseException {
406
438
  nodeQueue.add(new ReaderNode.ExceptionNode(ruby, ex));
@@ -412,9 +444,10 @@ public class XmlReader extends RubyObject {
412
444
  reader.setContentHandler(handler);
413
445
  reader.setDTDHandler(handler);
414
446
  reader.setErrorHandler(handler);
447
+ reader.setEntityResolver(new NokogiriEntityResolver(ruby, null, options));
415
448
  reader.setFeature("http://xml.org/sax/features/xmlns-uris", true);
416
449
  reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
417
- reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
450
+ reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", options.dtdLoad || options.dtdValid);
418
451
  return reader;
419
452
  } catch (SAXException saxe) {
420
453
  throw RaiseException.createNativeRaiseException(ruby, saxe);