nokogiri 1.5.0.beta.4 → 1.5.0

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 (107) hide show
  1. data/.gemtest +0 -0
  2. data/CHANGELOG.ja.rdoc +34 -0
  3. data/CHANGELOG.rdoc +40 -1
  4. data/Manifest.txt +11 -2
  5. data/README.rdoc +1 -1
  6. data/Rakefile +100 -104
  7. data/bin/nokogiri +1 -2
  8. data/ext/nokogiri/nokogiri.c +24 -1
  9. data/ext/nokogiri/xml_io.c +32 -7
  10. data/ext/nokogiri/xml_node.c +14 -13
  11. data/ext/nokogiri/xml_sax_parser.c +9 -4
  12. data/ext/nokogiri/xslt_stylesheet.c +7 -1
  13. data/lib/nokogiri.rb +3 -22
  14. data/lib/nokogiri/css.rb +4 -0
  15. data/lib/nokogiri/html/document.rb +10 -14
  16. data/lib/nokogiri/version.rb +76 -23
  17. data/lib/nokogiri/xml/builder.rb +7 -0
  18. data/lib/nokogiri/xml/document.rb +17 -1
  19. data/lib/nokogiri/xml/document_fragment.rb +14 -0
  20. data/lib/nokogiri/xml/node.rb +36 -28
  21. data/lib/nokogiri/xml/node/save_options.rb +17 -1
  22. data/lib/nokogiri/xml/node_set.rb +7 -0
  23. data/lib/nokogiri/xml/parse_options.rb +8 -0
  24. data/lib/nokogiri/xml/reader.rb +6 -6
  25. data/lib/nokogiri/xml/schema.rb +7 -1
  26. data/nokogiri_help_responses.md +40 -0
  27. data/tasks/cross_compile.rb +134 -159
  28. data/tasks/nokogiri.org.rb +18 -0
  29. data/tasks/test.rb +1 -1
  30. data/test/files/encoding.html +82 -0
  31. data/test/files/encoding.xhtml +84 -0
  32. data/test/files/metacharset.html +10 -0
  33. data/test/files/noencoding.html +47 -0
  34. data/test/helper.rb +2 -0
  35. data/test/html/test_document.rb +15 -0
  36. data/test/html/test_document_encoding.rb +13 -0
  37. data/test/test_memory_leak.rb +20 -0
  38. data/test/test_reader.rb +22 -0
  39. data/test/test_xslt_transforms.rb +6 -2
  40. data/test/xml/node/test_save_options.rb +10 -2
  41. data/test/xml/test_builder.rb +17 -0
  42. data/test/xml/test_document.rb +22 -0
  43. data/test/xml/test_node.rb +19 -1
  44. data/test/xml/test_node_reparenting.rb +16 -3
  45. data/test/xml/test_node_set.rb +34 -0
  46. data/test/xml/test_schema.rb +5 -0
  47. data/test/xslt/test_exception_handling.rb +37 -0
  48. metadata +185 -157
  49. data/deps.rip +0 -5
  50. data/ext/java/nokogiri/EncodingHandler.java +0 -124
  51. data/ext/java/nokogiri/HtmlDocument.java +0 -149
  52. data/ext/java/nokogiri/HtmlElementDescription.java +0 -145
  53. data/ext/java/nokogiri/HtmlEntityLookup.java +0 -79
  54. data/ext/java/nokogiri/HtmlSaxParserContext.java +0 -259
  55. data/ext/java/nokogiri/NokogiriService.java +0 -535
  56. data/ext/java/nokogiri/XmlAttr.java +0 -191
  57. data/ext/java/nokogiri/XmlAttributeDecl.java +0 -130
  58. data/ext/java/nokogiri/XmlCdata.java +0 -91
  59. data/ext/java/nokogiri/XmlComment.java +0 -86
  60. data/ext/java/nokogiri/XmlDocument.java +0 -529
  61. data/ext/java/nokogiri/XmlDocumentFragment.java +0 -217
  62. data/ext/java/nokogiri/XmlDtd.java +0 -467
  63. data/ext/java/nokogiri/XmlElement.java +0 -222
  64. data/ext/java/nokogiri/XmlElementContent.java +0 -382
  65. data/ext/java/nokogiri/XmlElementDecl.java +0 -148
  66. data/ext/java/nokogiri/XmlEntityDecl.java +0 -162
  67. data/ext/java/nokogiri/XmlEntityReference.java +0 -75
  68. data/ext/java/nokogiri/XmlNamespace.java +0 -128
  69. data/ext/java/nokogiri/XmlNode.java +0 -1399
  70. data/ext/java/nokogiri/XmlNodeSet.java +0 -311
  71. data/ext/java/nokogiri/XmlProcessingInstruction.java +0 -103
  72. data/ext/java/nokogiri/XmlReader.java +0 -411
  73. data/ext/java/nokogiri/XmlRelaxng.java +0 -144
  74. data/ext/java/nokogiri/XmlSaxParserContext.java +0 -367
  75. data/ext/java/nokogiri/XmlSaxPushParser.java +0 -184
  76. data/ext/java/nokogiri/XmlSchema.java +0 -319
  77. data/ext/java/nokogiri/XmlSyntaxError.java +0 -119
  78. data/ext/java/nokogiri/XmlText.java +0 -136
  79. data/ext/java/nokogiri/XmlXpathContext.java +0 -179
  80. data/ext/java/nokogiri/XsltStylesheet.java +0 -183
  81. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +0 -206
  82. data/ext/java/nokogiri/internals/NokogiriDocumentCache.java +0 -73
  83. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +0 -86
  84. data/ext/java/nokogiri/internals/NokogiriHandler.java +0 -327
  85. data/ext/java/nokogiri/internals/NokogiriHelpers.java +0 -582
  86. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +0 -171
  87. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +0 -118
  88. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +0 -74
  89. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +0 -121
  90. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +0 -79
  91. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +0 -126
  92. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +0 -56
  93. data/ext/java/nokogiri/internals/ParserContext.java +0 -278
  94. data/ext/java/nokogiri/internals/PushInputStream.java +0 -411
  95. data/ext/java/nokogiri/internals/ReaderNode.java +0 -474
  96. data/ext/java/nokogiri/internals/SaveContext.java +0 -288
  97. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +0 -76
  98. data/ext/java/nokogiri/internals/XmlDeclHandler.java +0 -42
  99. data/ext/java/nokogiri/internals/XmlDomParser.java +0 -77
  100. data/ext/java/nokogiri/internals/XmlDomParserContext.java +0 -238
  101. data/ext/java/nokogiri/internals/XmlSaxParser.java +0 -65
  102. data/ext/java/nokogiri/internals/XsltExtensionFunction.java +0 -72
  103. data/lib/isorelax.jar +0 -0
  104. data/lib/jing.jar +0 -0
  105. data/lib/nekodtd.jar +0 -0
  106. data/lib/nekohtml.jar +0 -0
  107. data/lib/xercesImpl.jar +0 -0
@@ -1,529 +0,0 @@
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
- package nokogiri;
34
-
35
- import static nokogiri.internals.NokogiriHelpers.getCachedNodeOrCreate;
36
- import static nokogiri.internals.NokogiriHelpers.getLocalNameForNamespace;
37
- import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
38
- import static nokogiri.internals.NokogiriHelpers.isNamespace;
39
- import static nokogiri.internals.NokogiriHelpers.rubyStringToString;
40
- import static nokogiri.internals.NokogiriHelpers.stringOrNil;
41
-
42
- import javax.xml.parsers.DocumentBuilderFactory;
43
- import javax.xml.parsers.ParserConfigurationException;
44
-
45
- import nokogiri.internals.NokogiriHelpers;
46
- import nokogiri.internals.NokogiriNamespaceCache;
47
- import nokogiri.internals.SaveContext;
48
- import nokogiri.internals.XmlDomParserContext;
49
-
50
- import org.jruby.Ruby;
51
- import org.jruby.RubyClass;
52
- import org.jruby.RubyFixnum;
53
- import org.jruby.RubyNil;
54
- import org.jruby.anno.JRubyClass;
55
- import org.jruby.anno.JRubyMethod;
56
- import org.jruby.javasupport.util.RuntimeHelpers;
57
- import org.jruby.runtime.Arity;
58
- import org.jruby.runtime.ThreadContext;
59
- import org.jruby.runtime.builtin.IRubyObject;
60
- import org.w3c.dom.Attr;
61
- import org.w3c.dom.Document;
62
- import org.w3c.dom.NamedNodeMap;
63
- import org.w3c.dom.Node;
64
- import org.w3c.dom.NodeList;
65
-
66
- /**
67
- * Class for Nokogiri::XML::Document
68
- *
69
- * @author sergio
70
- * @author Yoko Harada <yokolet@gmail.com>
71
- */
72
-
73
- @JRubyClass(name="Nokogiri::XML::Document", parent="Nokogiri::XML::Node")
74
- public class XmlDocument extends XmlNode {
75
- private NokogiriNamespaceCache nsCache;
76
-
77
- /* UserData keys for storing extra info in the document node. */
78
- public final static String DTD_RAW_DOCUMENT = "DTD_RAW_DOCUMENT";
79
- protected final static String DTD_INTERNAL_SUBSET = "DTD_INTERNAL_SUBSET";
80
- protected final static String DTD_EXTERNAL_SUBSET = "DTD_EXTERNAL_SUBSET";
81
-
82
- /* DocumentBuilderFactory implementation class name. This needs to set a classloader into it.
83
- * Setting an appropriate classloader resolves issue 380.
84
- */
85
- private static final String DOCUMENTBUILDERFACTORY_IMPLE_NAME = "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
86
-
87
- private static boolean substituteEntities = false;
88
- private static boolean loadExternalSubset = false; // TODO: Verify this.
89
-
90
- /** cache variables */
91
- protected IRubyObject encoding = null;
92
- protected IRubyObject url = null;
93
-
94
- public XmlDocument(Ruby ruby, RubyClass klazz) {
95
- super(ruby, klazz, createNewDocument());
96
- }
97
-
98
- public XmlDocument(Ruby ruby, Document document) {
99
- this(ruby, getNokogiriClass(ruby, "Nokogiri::XML::Document"), document);
100
- }
101
-
102
- public XmlDocument(Ruby ruby, RubyClass klass, Document document) {
103
- super(ruby, klass, document);
104
- nsCache = new NokogiriNamespaceCache();
105
- createAndCacheNamespaces(ruby, document.getDocumentElement());
106
- stabilizeTextContent(document);
107
- setInstanceVariable("@decorators", ruby.getNil());
108
- }
109
-
110
- @Override
111
- public void setNode(ThreadContext context, Node node) {
112
- super.setNode(context, node);
113
- if (nsCache == null) nsCache = new NokogiriNamespaceCache();
114
- Ruby runtime = context.getRuntime();
115
- if (node != null) {
116
- Document document = (Document)node;
117
- stabilizeTextContent(document);
118
- createAndCacheNamespaces(runtime, document.getDocumentElement());
119
- }
120
- setInstanceVariable("@decorators", runtime.getNil());
121
- }
122
-
123
- public void setEncoding(IRubyObject encoding) {
124
- this.encoding = encoding;
125
- }
126
-
127
- // not sure, but like attribute values, text value will be lost
128
- // unless it is referred once before this document is used.
129
- // this seems to happen only when the fragment is parsed from Node#in_context.
130
- private void stabilizeTextContent(Document document) {
131
- if (document.getDocumentElement() != null) document.getDocumentElement().getTextContent();
132
- }
133
-
134
- private void createAndCacheNamespaces(Ruby ruby, Node node) {
135
- if (node == null) return;
136
- if (node.hasAttributes()) {
137
- NamedNodeMap nodeMap = node.getAttributes();
138
- for (int i=0; i<nodeMap.getLength(); i++) {
139
- Node n = nodeMap.item(i);
140
- if (n instanceof Attr) {
141
- Attr attr = (Attr)n;
142
- String attrName = attr.getName();
143
- // not sure, but need to get value always before document is referred.
144
- // or lose attribute value
145
- String attrValue = attr.getValue();
146
- if (isNamespace(attrName)) {
147
- String prefix = getLocalNameForNamespace(attrName);
148
- prefix = prefix != null ? prefix : "";
149
- nsCache.put(ruby, prefix, attrValue, node, this);
150
- }
151
- }
152
- }
153
- }
154
- NodeList children = node.getChildNodes();
155
- for (int i=0; i<children.getLength(); i++) {
156
- createAndCacheNamespaces(ruby, children.item(i));
157
- }
158
- }
159
-
160
- // When a document is created from fragment with a context (reference) document,
161
- // namespace should be resolved based on the context document.
162
- public XmlDocument(Ruby ruby, RubyClass klass, Document document, XmlDocument contextDoc) {
163
- super(ruby, klass, document);
164
- nsCache = contextDoc.getNamespaceCache();
165
- XmlNamespace default_ns = nsCache.getDefault();
166
- String default_href = rubyStringToString(default_ns.href(ruby.getCurrentContext()));
167
- resolveNamespaceIfNecessary(ruby.getCurrentContext(), document.getDocumentElement(), default_href);
168
- }
169
-
170
- private void resolveNamespaceIfNecessary(ThreadContext context, Node node, String default_href) {
171
- if (node == null) return;
172
- String nodePrefix = node.getPrefix();
173
- if (nodePrefix == null) { // default namespace
174
- node.getOwnerDocument().renameNode(node, default_href, node.getNodeName());
175
- } else {
176
- XmlNamespace xmlNamespace = nsCache.get(nodePrefix);
177
- String href = rubyStringToString(xmlNamespace.href(context));
178
- node.getOwnerDocument().renameNode(node, href, node.getNodeName());
179
- }
180
- resolveNamespaceIfNecessary(context, node.getNextSibling(), default_href);
181
- NodeList children = node.getChildNodes();
182
- for (int i=0; i<children.getLength(); i++) {
183
- resolveNamespaceIfNecessary(context, children.item(i), default_href);
184
- }
185
- }
186
-
187
- public NokogiriNamespaceCache getNamespaceCache() {
188
- return nsCache;
189
- }
190
-
191
- public void setNamespaceCache(NokogiriNamespaceCache nsCache) {
192
- this.nsCache = nsCache;
193
- }
194
-
195
- public Document getDocument() {
196
- return (Document) node;
197
- }
198
-
199
- @Override
200
- protected IRubyObject getNodeName(ThreadContext context) {
201
- if (name == null) name = context.getRuntime().newString("document");
202
- return name;
203
- }
204
-
205
- public void setUrl(IRubyObject url) {
206
- this.url = url;
207
- }
208
-
209
- protected IRubyObject getUrl() {
210
- return this.url;
211
- }
212
-
213
- @JRubyMethod
214
- public IRubyObject url(ThreadContext context) {
215
- return getUrl();
216
- }
217
-
218
- protected static Document createNewDocument() {
219
- try {
220
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(DOCUMENTBUILDERFACTORY_IMPLE_NAME, NokogiriService.class.getClassLoader());
221
- return factory.newDocumentBuilder().newDocument();
222
- } catch (ParserConfigurationException e) {
223
- return null; // this will end is disaster...
224
- }
225
- }
226
-
227
- /*
228
- * call-seq:
229
- * new(version = default)
230
- *
231
- * Create a new document with +version+ (defaults to "1.0")
232
- */
233
- @JRubyMethod(name="new", meta = true, rest = true, required=0)
234
- public static IRubyObject rbNew(ThreadContext context, IRubyObject klazz, IRubyObject[] args) {
235
- XmlDocument xmlDocument = null;
236
- try {
237
- Document docNode = createNewDocument();
238
- if ("Nokogiri::HTML::Document".equals(((RubyClass)klazz).getName())) {
239
- xmlDocument = (XmlDocument) NokogiriService.HTML_DOCUMENT_ALLOCATOR.allocate(context.getRuntime(), (RubyClass) klazz);
240
- xmlDocument.setNode(context, docNode);
241
- } else {
242
- // XML::Document and sublass
243
- xmlDocument = (XmlDocument) NokogiriService.XML_DOCUMENT_ALLOCATOR.allocate(context.getRuntime(), (RubyClass) klazz);
244
- xmlDocument.setNode(context, docNode);
245
- }
246
- } catch (Exception ex) {
247
- throw context.getRuntime().newRuntimeError("couldn't create document: "+ex.toString());
248
- }
249
-
250
- RuntimeHelpers.invoke(context, xmlDocument, "initialize", args);
251
-
252
- return xmlDocument;
253
- }
254
-
255
- @JRubyMethod(required=1, optional=4)
256
- public IRubyObject create_entity(ThreadContext context, IRubyObject[] argv) {
257
- // FIXME: Entity node should be create by some right way.
258
- // this impl passes tests, but entity doesn't exists in DTD, which
259
- // would cause validation failure.
260
- if (argv.length == 0) throw context.getRuntime().newRuntimeError("Could not create entity");
261
- String tagName = rubyStringToString(argv[0]);
262
- Node n = this.getOwnerDocument().createElement(tagName);
263
- return XmlEntityDecl.create(context, n, argv);
264
- }
265
-
266
- @Override
267
- @JRubyMethod
268
- public IRubyObject document(ThreadContext context) {
269
- return this;
270
- }
271
-
272
- @JRubyMethod(name="encoding=")
273
- public IRubyObject encoding_set(ThreadContext context, IRubyObject encoding) {
274
- this.encoding = encoding;
275
- return this;
276
- }
277
-
278
- @JRubyMethod
279
- public IRubyObject encoding(ThreadContext context) {
280
- if (this.encoding == null) {
281
- if (getDocument().getXmlEncoding() == null) {
282
- this.encoding = context.getRuntime().getNil();
283
- } else {
284
- this.encoding = context.getRuntime().newString(getDocument().getXmlEncoding());
285
- }
286
- }
287
-
288
- return this.encoding;
289
- }
290
-
291
- @JRubyMethod(meta = true)
292
- public static IRubyObject load_external_subsets_set(ThreadContext context, IRubyObject cls, IRubyObject value) {
293
- XmlDocument.loadExternalSubset = value.isTrue();
294
- return context.getRuntime().getNil();
295
- }
296
-
297
- /**
298
- * TODO: handle encoding?
299
- *
300
- * @param args[0] a Ruby IO or StringIO
301
- * @param args[1] url or nil
302
- * @param args[2] encoding
303
- * @param args[3] bitset of parser options
304
- */
305
- public static IRubyObject newFromData(ThreadContext context,
306
- IRubyObject klass,
307
- IRubyObject[] args) {
308
- Ruby ruby = context.getRuntime();
309
- Arity.checkArgumentCount(ruby, args, 4, 4);
310
- XmlDomParserContext ctx =
311
- new XmlDomParserContext(ruby, args[2], args[3]);
312
- ctx.setInputSource(context, args[0]);
313
- return ctx.parse(context, klass, args[1]);
314
- }
315
-
316
- @JRubyMethod(meta = true, rest = true)
317
- public static IRubyObject read_io(ThreadContext context,
318
- IRubyObject klass,
319
- IRubyObject[] args) {
320
- return newFromData(context, klass, args);
321
- }
322
-
323
- @JRubyMethod(meta = true, rest = true)
324
- public static IRubyObject read_memory(ThreadContext context,
325
- IRubyObject klass,
326
- IRubyObject[] args) {
327
- return newFromData(context, klass, args);
328
- }
329
-
330
- /** not a JRubyMethod */
331
- public static IRubyObject read_memory(ThreadContext context,
332
- IRubyObject[] args) {
333
- return read_memory(context,
334
- getNokogiriClass(context.getRuntime(), "Nokogiri::XML::Document"),
335
- args);
336
- }
337
-
338
- @JRubyMethod(name="remove_namespaces!")
339
- public IRubyObject remove_namespaces(ThreadContext context) {
340
- removeNamespceRecursively(context, this);
341
- nsCache.clear();
342
- return this;
343
- }
344
-
345
- private void removeNamespceRecursively(ThreadContext context, XmlNode xmlNode) {
346
- Node node = xmlNode.node;
347
- if (node.getNodeType() == Node.ELEMENT_NODE) {
348
- node.setPrefix(null);
349
- node.getOwnerDocument().renameNode(node, null, node.getLocalName());
350
- NamedNodeMap attrs = node.getAttributes();
351
- for (int i=0; i<attrs.getLength(); i++) {
352
- Node attr = attrs.item(i);
353
- attr.setPrefix(null);
354
- attr.getOwnerDocument().renameNode(attr, null, attr.getLocalName());
355
- }
356
- }
357
- XmlNodeSet nodeSet = (XmlNodeSet) xmlNode.children(context);
358
- for (long i=0; i < nodeSet.length(); i++) {
359
- XmlNode childNode = (XmlNode)nodeSet.slice(context, RubyFixnum.newFixnum(context.getRuntime(), i));
360
- removeNamespceRecursively(context, childNode);
361
- }
362
- }
363
-
364
- @JRubyMethod
365
- public IRubyObject root(ThreadContext context) {
366
- Node rootNode = getDocument().getDocumentElement();
367
- try {
368
- Boolean isValid = (Boolean)rootNode.getUserData(NokogiriHelpers.VALID_ROOT_NODE);
369
- if (!isValid) return context.getRuntime().getNil();
370
- } catch (NullPointerException e) {
371
- // does nothing since nil wasn't set to the root node before.
372
- }
373
- if (rootNode == null)
374
- return context.getRuntime().getNil();
375
- else
376
- return getCachedNodeOrCreate(context.getRuntime(), rootNode);
377
- }
378
-
379
- @JRubyMethod(name="root=")
380
- public IRubyObject root_set(ThreadContext context, IRubyObject newRoot_) {
381
- // in case of document fragment, temporary root node should be deleted.
382
-
383
- // Java can't have a root whose value is null. Instead of setting null,
384
- // the method sets user data so that other methods are able to know the root
385
- // should be nil.
386
- if (newRoot_ instanceof RubyNil) {
387
- getDocument().getDocumentElement().setUserData(NokogiriHelpers.VALID_ROOT_NODE, false, null);
388
- return newRoot_;
389
- }
390
- XmlNode newRoot = asXmlNode(context, newRoot_);
391
-
392
- IRubyObject root = root(context);
393
- if (root.isNil()) {
394
- Node newRootNode;
395
- if (getDocument() == newRoot.getOwnerDocument()) {
396
- newRootNode = newRoot.node;
397
- } else {
398
- // must copy otherwise newRoot may exist in two places
399
- // with different owner document.
400
- newRootNode = getDocument().importNode(newRoot.node, true);
401
- }
402
- add_child_node(context, getCachedNodeOrCreate(context.getRuntime(), newRootNode));
403
- } else {
404
- Node rootNode = asXmlNode(context, root).node;
405
- ((XmlNode)getCachedNodeOrCreate(context.getRuntime(), rootNode)).replace_node(context, newRoot);
406
- }
407
-
408
- return newRoot;
409
- }
410
-
411
- @JRubyMethod
412
- public IRubyObject version(ThreadContext context) {
413
- return stringOrNil(context.getRuntime(), getDocument().getXmlVersion());
414
- }
415
-
416
- @JRubyMethod(meta = true)
417
- public static IRubyObject substitute_entities_set(ThreadContext context, IRubyObject cls, IRubyObject value) {
418
- XmlDocument.substituteEntities = value.isTrue();
419
- return context.getRuntime().getNil();
420
- }
421
-
422
- public IRubyObject getInternalSubset(ThreadContext context) {
423
- IRubyObject dtd =
424
- (IRubyObject) node.getUserData(DTD_INTERNAL_SUBSET);
425
-
426
- if (dtd == null) {
427
- if (getDocument().getDoctype() == null)
428
- dtd = context.getRuntime().getNil();
429
- else
430
- dtd = XmlDtd.newFromInternalSubset(context.getRuntime(),
431
- getDocument());
432
-
433
- setInternalSubset(dtd);
434
- }
435
-
436
- return dtd;
437
- }
438
-
439
- /**
440
- * Assumes XmlNode#internal_subset() has returned nil. (i.e. there
441
- * is not already an internal subset).
442
- */
443
- public IRubyObject createInternalSubset(ThreadContext context,
444
- IRubyObject name,
445
- IRubyObject external_id,
446
- IRubyObject system_id) {
447
- XmlDtd dtd = XmlDtd.newEmpty(context.getRuntime(),
448
- this.getDocument(),
449
- name, external_id, system_id);
450
- setInternalSubset(dtd);
451
- return dtd;
452
- }
453
-
454
- protected void setInternalSubset(IRubyObject data) {
455
- node.setUserData(DTD_INTERNAL_SUBSET, data, null);
456
- }
457
-
458
- public IRubyObject getExternalSubset(ThreadContext context) {
459
- IRubyObject dtd = (IRubyObject)
460
- node.getUserData(DTD_EXTERNAL_SUBSET);
461
-
462
- if (dtd == null) {
463
- dtd = XmlDtd.newFromExternalSubset(context.getRuntime(),
464
- getDocument());
465
- setExternalSubset(dtd);
466
- }
467
-
468
- return dtd;
469
- }
470
-
471
- /**
472
- * Assumes XmlNode#external_subset() has returned nil. (i.e. there
473
- * is not already an external subset).
474
- */
475
- public IRubyObject createExternalSubset(ThreadContext context,
476
- IRubyObject name,
477
- IRubyObject external_id,
478
- IRubyObject system_id) {
479
- XmlDtd dtd = XmlDtd.newEmpty(context.getRuntime(),
480
- this.getDocument(),
481
- name, external_id, system_id);
482
- setExternalSubset(dtd);
483
- return dtd;
484
- }
485
-
486
- protected void setExternalSubset(IRubyObject data) {
487
- node.setUserData(DTD_EXTERNAL_SUBSET, data, null);
488
- }
489
-
490
- //public IRubyObject createE
491
-
492
- @Override
493
- public void saveContent(ThreadContext context, SaveContext ctx) {
494
- if(!ctx.noDecl()) {
495
- ctx.append("<?xml version=\"");
496
- ctx.append(getDocument().getXmlVersion());
497
- ctx.append("\"");
498
- // if(!cur.encoding(context).isNil()) {
499
- // ctx.append(" encoding=");
500
- // ctx.append(cur.encoding(context).asJavaString());
501
- // }
502
-
503
- String encoding = ctx.getEncoding();
504
-
505
- if(encoding == null &&
506
- !encoding(context).isNil()) {
507
- encoding = encoding(context).convertToString().asJavaString();
508
- }
509
-
510
- if(encoding != null) {
511
- ctx.append(" encoding=\"");
512
- ctx.append(encoding);
513
- ctx.append("\"");
514
- }
515
-
516
- //ctx.append(" standalone=\"");
517
- //ctx.append(getDocument().getXmlStandalone() ? "yes" : "no");
518
- ctx.append("?>\n");
519
- }
520
-
521
- IRubyObject maybeRoot = root(context);
522
- if (maybeRoot.isNil())
523
- throw context.getRuntime().newRuntimeError("no root document");
524
-
525
- XmlNode root = (XmlNode) maybeRoot;
526
- root.saveContent(context, ctx);
527
- ctx.append("\n");
528
- }
529
- }