nokogiri 1.10.9-java → 1.11.0.rc4-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.
- checksums.yaml +4 -4
- data/LICENSE-DEPENDENCIES.md +1015 -947
- data/README.md +24 -22
- data/ext/java/nokogiri/HtmlDocument.java +34 -46
- data/ext/java/nokogiri/HtmlSaxParserContext.java +88 -58
- data/ext/java/nokogiri/HtmlSaxPushParser.java +1 -1
- data/ext/java/nokogiri/NokogiriService.java +1 -1
- data/ext/java/nokogiri/XmlAttr.java +13 -20
- data/ext/java/nokogiri/XmlAttributeDecl.java +11 -12
- data/ext/java/nokogiri/XmlCdata.java +3 -4
- data/ext/java/nokogiri/XmlComment.java +1 -1
- data/ext/java/nokogiri/XmlDocument.java +148 -175
- data/ext/java/nokogiri/XmlDocumentFragment.java +13 -31
- data/ext/java/nokogiri/XmlDtd.java +5 -8
- data/ext/java/nokogiri/XmlElement.java +1 -20
- data/ext/java/nokogiri/XmlElementDecl.java +23 -28
- data/ext/java/nokogiri/XmlEntityDecl.java +23 -27
- data/ext/java/nokogiri/XmlEntityReference.java +2 -2
- data/ext/java/nokogiri/XmlNamespace.java +72 -89
- data/ext/java/nokogiri/XmlNode.java +303 -406
- data/ext/java/nokogiri/XmlNodeSet.java +70 -76
- data/ext/java/nokogiri/XmlReader.java +12 -13
- data/ext/java/nokogiri/XmlRelaxng.java +10 -3
- data/ext/java/nokogiri/XmlSaxParserContext.java +15 -10
- data/ext/java/nokogiri/XmlSchema.java +87 -27
- data/ext/java/nokogiri/XmlSyntaxError.java +2 -6
- data/ext/java/nokogiri/XmlText.java +12 -9
- data/ext/java/nokogiri/XmlXpathContext.java +55 -25
- data/ext/java/nokogiri/XsltStylesheet.java +7 -15
- data/ext/java/nokogiri/internals/HtmlDomParserContext.java +52 -46
- data/ext/java/nokogiri/internals/NokogiriHandler.java +1 -1
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +71 -135
- data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +90 -58
- data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +9 -2
- data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +67 -10
- data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +4 -2
- data/ext/java/nokogiri/internals/ParserContext.java +27 -73
- data/ext/java/nokogiri/internals/ReaderNode.java +2 -4
- data/ext/java/nokogiri/internals/XmlDomParserContext.java +18 -33
- data/ext/nokogiri/depend +476 -357
- data/ext/nokogiri/extconf.rb +485 -352
- data/ext/nokogiri/html_document.c +79 -78
- data/ext/nokogiri/html_sax_parser_context.c +2 -2
- data/ext/nokogiri/nokogiri.c +34 -40
- data/ext/nokogiri/xml_document.c +18 -4
- data/ext/nokogiri/xml_io.c +8 -6
- data/ext/nokogiri/xml_node.c +21 -1
- data/ext/nokogiri/xml_node_set.c +1 -1
- data/ext/nokogiri/xml_reader.c +6 -17
- data/ext/nokogiri/xml_relax_ng.c +29 -11
- data/ext/nokogiri/xml_sax_parser.c +2 -7
- data/ext/nokogiri/xml_sax_parser_context.c +2 -2
- data/ext/nokogiri/xml_schema.c +55 -13
- data/ext/nokogiri/xml_xpath_context.c +80 -4
- data/ext/nokogiri/xslt_stylesheet.c +1 -8
- data/lib/nokogiri.rb +4 -21
- data/lib/nokogiri/css.rb +1 -0
- data/lib/nokogiri/css/node.rb +1 -0
- data/lib/nokogiri/css/parser.rb +63 -62
- data/lib/nokogiri/css/parser.y +2 -2
- data/lib/nokogiri/css/parser_extras.rb +39 -36
- data/lib/nokogiri/css/syntax_error.rb +1 -0
- data/lib/nokogiri/css/tokenizer.rb +1 -0
- data/lib/nokogiri/css/xpath_visitor.rb +73 -43
- data/lib/nokogiri/decorators/slop.rb +1 -0
- data/lib/nokogiri/html.rb +1 -0
- data/lib/nokogiri/html/builder.rb +1 -0
- data/lib/nokogiri/html/document.rb +13 -26
- data/lib/nokogiri/html/document_fragment.rb +1 -0
- data/lib/nokogiri/html/element_description.rb +1 -0
- data/lib/nokogiri/html/element_description_defaults.rb +1 -0
- data/lib/nokogiri/html/entity_lookup.rb +1 -0
- data/lib/nokogiri/html/sax/parser.rb +1 -0
- data/lib/nokogiri/html/sax/parser_context.rb +1 -0
- data/lib/nokogiri/html/sax/push_parser.rb +1 -0
- data/lib/nokogiri/jruby/dependencies.rb +20 -0
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/lib/nokogiri/syntax_error.rb +1 -0
- data/lib/nokogiri/version.rb +3 -109
- data/lib/nokogiri/version/constant.rb +5 -0
- data/lib/nokogiri/version/info.rb +182 -0
- data/lib/nokogiri/xml.rb +1 -0
- data/lib/nokogiri/xml/attr.rb +1 -0
- data/lib/nokogiri/xml/attribute_decl.rb +1 -0
- data/lib/nokogiri/xml/builder.rb +3 -2
- data/lib/nokogiri/xml/cdata.rb +1 -0
- data/lib/nokogiri/xml/character_data.rb +1 -0
- data/lib/nokogiri/xml/document.rb +20 -15
- data/lib/nokogiri/xml/document_fragment.rb +5 -6
- data/lib/nokogiri/xml/dtd.rb +1 -0
- data/lib/nokogiri/xml/element_content.rb +1 -0
- data/lib/nokogiri/xml/element_decl.rb +1 -0
- data/lib/nokogiri/xml/entity_decl.rb +1 -0
- data/lib/nokogiri/xml/entity_reference.rb +1 -0
- data/lib/nokogiri/xml/namespace.rb +1 -0
- data/lib/nokogiri/xml/node.rb +587 -249
- data/lib/nokogiri/xml/node/save_options.rb +1 -0
- data/lib/nokogiri/xml/node_set.rb +1 -0
- data/lib/nokogiri/xml/notation.rb +1 -0
- data/lib/nokogiri/xml/parse_options.rb +10 -3
- data/lib/nokogiri/xml/pp.rb +1 -0
- data/lib/nokogiri/xml/pp/character_data.rb +1 -0
- data/lib/nokogiri/xml/pp/node.rb +1 -0
- data/lib/nokogiri/xml/processing_instruction.rb +1 -0
- data/lib/nokogiri/xml/reader.rb +7 -3
- data/lib/nokogiri/xml/relax_ng.rb +7 -2
- data/lib/nokogiri/xml/sax.rb +1 -0
- data/lib/nokogiri/xml/sax/document.rb +1 -0
- data/lib/nokogiri/xml/sax/parser.rb +1 -0
- data/lib/nokogiri/xml/sax/parser_context.rb +1 -0
- data/lib/nokogiri/xml/sax/push_parser.rb +1 -0
- data/lib/nokogiri/xml/schema.rb +13 -4
- data/lib/nokogiri/xml/searchable.rb +25 -16
- data/lib/nokogiri/xml/syntax_error.rb +1 -0
- data/lib/nokogiri/xml/text.rb +1 -0
- data/lib/nokogiri/xml/xpath.rb +1 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -0
- data/lib/nokogiri/xml/xpath_context.rb +1 -0
- data/lib/nokogiri/xslt.rb +1 -0
- data/lib/nokogiri/xslt/stylesheet.rb +1 -0
- data/lib/xsd/xmlparser/nokogiri.rb +1 -0
- metadata +89 -96
- data/ext/java/nokogiri/internals/NokogiriEncodingReaderWrapper.java +0 -107
- data/ext/java/nokogiri/internals/UncloseableInputStream.java +0 -102
- data/ext/nokogiri/html_document.h +0 -10
- data/ext/nokogiri/html_element_description.h +0 -10
- data/ext/nokogiri/html_entity_lookup.h +0 -8
- data/ext/nokogiri/html_sax_parser_context.h +0 -11
- data/ext/nokogiri/html_sax_push_parser.h +0 -9
- data/ext/nokogiri/nokogiri.h +0 -121
- data/ext/nokogiri/xml_attr.h +0 -9
- data/ext/nokogiri/xml_attribute_decl.h +0 -9
- data/ext/nokogiri/xml_cdata.h +0 -9
- data/ext/nokogiri/xml_comment.h +0 -9
- data/ext/nokogiri/xml_document.h +0 -23
- data/ext/nokogiri/xml_document_fragment.h +0 -10
- data/ext/nokogiri/xml_dtd.h +0 -10
- data/ext/nokogiri/xml_element_content.h +0 -10
- data/ext/nokogiri/xml_element_decl.h +0 -9
- data/ext/nokogiri/xml_encoding_handler.h +0 -8
- data/ext/nokogiri/xml_entity_decl.h +0 -10
- data/ext/nokogiri/xml_entity_reference.h +0 -9
- data/ext/nokogiri/xml_io.h +0 -11
- data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
- data/ext/nokogiri/xml_namespace.h +0 -14
- data/ext/nokogiri/xml_node.h +0 -13
- data/ext/nokogiri/xml_node_set.h +0 -12
- data/ext/nokogiri/xml_processing_instruction.h +0 -9
- data/ext/nokogiri/xml_reader.h +0 -10
- data/ext/nokogiri/xml_relax_ng.h +0 -9
- data/ext/nokogiri/xml_sax_parser.h +0 -39
- data/ext/nokogiri/xml_sax_parser_context.h +0 -10
- data/ext/nokogiri/xml_sax_push_parser.h +0 -9
- data/ext/nokogiri/xml_schema.h +0 -9
- data/ext/nokogiri/xml_syntax_error.h +0 -13
- data/ext/nokogiri/xml_text.h +0 -9
- data/ext/nokogiri/xml_xpath_context.h +0 -10
- data/ext/nokogiri/xslt_stylesheet.h +0 -14
@@ -33,24 +33,13 @@
|
|
33
33
|
package nokogiri;
|
34
34
|
|
35
35
|
import static java.lang.Math.max;
|
36
|
-
import static nokogiri.internals.NokogiriHelpers
|
37
|
-
import static nokogiri.internals.NokogiriHelpers.convertEncoding;
|
38
|
-
import static nokogiri.internals.NokogiriHelpers.convertString;
|
39
|
-
import static nokogiri.internals.NokogiriHelpers.getCachedNodeOrCreate;
|
40
|
-
import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
|
41
|
-
import static nokogiri.internals.NokogiriHelpers.isBlank;
|
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
41
|
import java.nio.charset.Charset;
|
51
|
-
import java.util
|
52
|
-
import java.util.Iterator;
|
53
|
-
import java.util.List;
|
42
|
+
import java.util.*;
|
54
43
|
|
55
44
|
import org.apache.xerces.dom.CoreDocumentImpl;
|
56
45
|
import org.jruby.Ruby;
|
@@ -64,8 +53,8 @@ import org.jruby.RubyString;
|
|
64
53
|
import org.jruby.anno.JRubyClass;
|
65
54
|
import org.jruby.anno.JRubyMethod;
|
66
55
|
import org.jruby.exceptions.RaiseException;
|
67
|
-
import org.jruby.runtime.Helpers;
|
68
56
|
import org.jruby.runtime.Block;
|
57
|
+
import org.jruby.runtime.Helpers;
|
69
58
|
import org.jruby.runtime.ThreadContext;
|
70
59
|
import org.jruby.runtime.Visibility;
|
71
60
|
import org.jruby.runtime.builtin.IRubyObject;
|
@@ -102,8 +91,8 @@ public class XmlNode extends RubyObject {
|
|
102
91
|
|
103
92
|
/* Cached objects */
|
104
93
|
protected IRubyObject content = null;
|
105
|
-
|
106
|
-
protected
|
94
|
+
private transient XmlDocument doc;
|
95
|
+
protected transient RubyString name;
|
107
96
|
|
108
97
|
/*
|
109
98
|
* Taken from http://ejohn.org/blog/comparing-document-position/
|
@@ -124,7 +113,7 @@ public class XmlNode extends RubyObject {
|
|
124
113
|
*/
|
125
114
|
protected static XmlNode asXmlNode(ThreadContext context, IRubyObject node) {
|
126
115
|
if ( !(node instanceof XmlNode) ) {
|
127
|
-
final Ruby runtime = context.
|
116
|
+
final Ruby runtime = context.runtime;
|
128
117
|
throw runtime.newTypeError(node == null ? runtime.getNil() : node, getNokogiriClass(runtime, "Nokogiri::XML::Node"));
|
129
118
|
}
|
130
119
|
return (XmlNode) node;
|
@@ -206,29 +195,25 @@ public class XmlNode extends RubyObject {
|
|
206
195
|
* This is the allocator for XmlNode class. It should only be
|
207
196
|
* called from Ruby code.
|
208
197
|
*/
|
209
|
-
public XmlNode(Ruby
|
210
|
-
super(
|
198
|
+
public XmlNode(Ruby runtime, RubyClass klass) {
|
199
|
+
super(runtime, klass);
|
211
200
|
}
|
212
201
|
|
213
202
|
/**
|
214
203
|
* This is a constructor to create an XmlNode from an already
|
215
204
|
* existing node. It may be called by Java code.
|
216
205
|
*/
|
217
|
-
public XmlNode(Ruby
|
218
|
-
super(
|
219
|
-
setNode(
|
206
|
+
public XmlNode(Ruby runtime, RubyClass klass, Node node) {
|
207
|
+
super(runtime, klass);
|
208
|
+
setNode(runtime, node);
|
220
209
|
}
|
221
210
|
|
222
|
-
protected void decorate(final
|
211
|
+
protected void decorate(final Ruby runtime) {
|
223
212
|
if (node != null) {
|
224
213
|
resetCache();
|
225
214
|
|
226
215
|
if (node.getNodeType() != Node.DOCUMENT_NODE) {
|
227
|
-
|
228
|
-
|
229
|
-
if (doc != null && ! doc.isNil()) {
|
230
|
-
Helpers.invoke(context, doc, "decorate", this);
|
231
|
-
}
|
216
|
+
setDocumentAndDecorate(runtime.getCurrentContext(), this, document(runtime));
|
232
217
|
}
|
233
218
|
}
|
234
219
|
}
|
@@ -287,7 +272,7 @@ public class XmlNode extends RubyObject {
|
|
287
272
|
@JRubyMethod(name = "new", meta = true, rest = true)
|
288
273
|
public static IRubyObject rbNew(ThreadContext context, IRubyObject cls,
|
289
274
|
IRubyObject[] args, Block block) {
|
290
|
-
Ruby ruby = context.
|
275
|
+
Ruby ruby = context.runtime;
|
291
276
|
RubyClass klazz = (RubyClass) cls;
|
292
277
|
|
293
278
|
if ("Nokogiri::XML::Node".equals(klazz.getName())) {
|
@@ -320,14 +305,14 @@ public class XmlNode extends RubyObject {
|
|
320
305
|
*/
|
321
306
|
protected void init(ThreadContext context, IRubyObject[] args) {
|
322
307
|
if (args.length < 2)
|
323
|
-
throw context.
|
308
|
+
throw context.runtime.newArgumentError(args.length, 2);
|
324
309
|
|
325
310
|
IRubyObject name = args[0];
|
326
311
|
IRubyObject doc = args[1];
|
327
312
|
|
328
313
|
Document document = asXmlNode(context, doc).getOwnerDocument();
|
329
314
|
if (document == null) {
|
330
|
-
throw
|
315
|
+
throw context.runtime.newArgumentError("node must have owner document");
|
331
316
|
}
|
332
317
|
|
333
318
|
Element element;
|
@@ -338,7 +323,7 @@ public class XmlNode extends RubyObject {
|
|
338
323
|
namespace_uri = document.getDocumentElement().lookupNamespaceURI(prefix);
|
339
324
|
}
|
340
325
|
element = document.createElementNS(namespace_uri, node_name);
|
341
|
-
setNode(context, element);
|
326
|
+
setNode(context.runtime, element);
|
342
327
|
}
|
343
328
|
|
344
329
|
/**
|
@@ -365,53 +350,6 @@ public class XmlNode extends RubyObject {
|
|
365
350
|
return node;
|
366
351
|
}
|
367
352
|
|
368
|
-
public static Node getNodeFromXmlNode(ThreadContext context, IRubyObject xmlNode) {
|
369
|
-
return asXmlNode(context, xmlNode).node;
|
370
|
-
}
|
371
|
-
|
372
|
-
protected String indentString(IRubyObject indentStringObject, String xml) {
|
373
|
-
String[] lines = xml.split("\n");
|
374
|
-
|
375
|
-
if(lines.length <= 1) return xml;
|
376
|
-
|
377
|
-
String[] resultLines = new String[lines.length];
|
378
|
-
|
379
|
-
String curLine;
|
380
|
-
boolean closingTag = false;
|
381
|
-
String indentString = rubyStringToString(indentStringObject);
|
382
|
-
int lengthInd = indentString.length();
|
383
|
-
StringBuilder curInd = new StringBuilder();
|
384
|
-
|
385
|
-
resultLines[0] = lines[0];
|
386
|
-
|
387
|
-
for(int i = 1; i < lines.length; i++) {
|
388
|
-
|
389
|
-
curLine = lines[i].trim();
|
390
|
-
|
391
|
-
if(curLine.length() == 0) continue;
|
392
|
-
|
393
|
-
if(curLine.startsWith("</")) {
|
394
|
-
closingTag = true;
|
395
|
-
curInd.setLength(max(0,curInd.length() - lengthInd));
|
396
|
-
}
|
397
|
-
|
398
|
-
resultLines[i] = curInd.toString() + curLine;
|
399
|
-
|
400
|
-
if(!curLine.endsWith("/>") && !closingTag) {
|
401
|
-
curInd.append(indentString);
|
402
|
-
}
|
403
|
-
|
404
|
-
closingTag = false;
|
405
|
-
}
|
406
|
-
|
407
|
-
StringBuilder result = new StringBuilder();
|
408
|
-
for(int i = 0; i < resultLines.length; i++) {
|
409
|
-
result.append(resultLines[i]).append('\n');
|
410
|
-
}
|
411
|
-
|
412
|
-
return result.toString();
|
413
|
-
}
|
414
|
-
|
415
353
|
public boolean isComment() { return false; }
|
416
354
|
|
417
355
|
public boolean isElement() {
|
@@ -431,7 +369,7 @@ public class XmlNode extends RubyObject {
|
|
431
369
|
* declarations like XmlElementDecl.
|
432
370
|
*/
|
433
371
|
protected IRubyObject getAttribute(ThreadContext context, String key) {
|
434
|
-
return getAttribute(context.
|
372
|
+
return getAttribute(context.runtime, key);
|
435
373
|
}
|
436
374
|
|
437
375
|
protected IRubyObject getAttribute(Ruby runtime, String key) {
|
@@ -472,9 +410,7 @@ public class XmlNode extends RubyObject {
|
|
472
410
|
String nsURI = e.lookupNamespaceURI(prefix);
|
473
411
|
this.node = NokogiriHelpers.renameNode(e, nsURI, e.getNodeName());
|
474
412
|
|
475
|
-
if (nsURI == null || nsURI
|
476
|
-
return;
|
477
|
-
}
|
413
|
+
if (nsURI == null || nsURI.isEmpty()) return;
|
478
414
|
|
479
415
|
String currentPrefix = e.getParentNode().lookupPrefix(nsURI);
|
480
416
|
String currentURI = e.getParentNode().lookupNamespaceURI(prefix);
|
@@ -483,18 +419,15 @@ public class XmlNode extends RubyObject {
|
|
483
419
|
// add xmlns attribute if this is a new root node or if the node's
|
484
420
|
// namespace isn't a default namespace in the new document
|
485
421
|
if (e.getParentNode().getNodeType() == Node.DOCUMENT_NODE) {
|
486
|
-
|
487
|
-
|
488
|
-
e.setAttribute(prefix == null ? "xmlns":"xmlns:"+prefix, nsURI);
|
422
|
+
// this is the root node, so we must set the namespaces attributes anyway
|
423
|
+
e.setAttribute(prefix == null ? "xmlns" : "xmlns:" + prefix, nsURI);
|
489
424
|
} else if (prefix == null) {
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
// the prefix is set to a diffent URI
|
497
|
-
e.setAttribute("xmlns:"+prefix, nsURI);
|
425
|
+
// this is a default namespace but isn't the default where this node is being added
|
426
|
+
if (!isDefault) e.setAttribute("xmlns", nsURI);
|
427
|
+
} else if (!prefix.equals(currentPrefix) || nsURI.equals(currentURI)) {
|
428
|
+
// this is a prefixed namespace
|
429
|
+
// but doesn't have the same prefix or the prefix is set to a different URI
|
430
|
+
e.setAttribute("xmlns:" + prefix, nsURI);
|
498
431
|
}
|
499
432
|
|
500
433
|
if (e.hasAttributes()) {
|
@@ -516,87 +449,76 @@ public class XmlNode extends RubyObject {
|
|
516
449
|
nsUri = attr.lookupNamespaceURI(attrPrefix);
|
517
450
|
}
|
518
451
|
|
519
|
-
if (nsUri
|
452
|
+
if (nsUri != null && nsUri.equals(e.getNamespaceURI())) {
|
520
453
|
nsUri = null;
|
521
454
|
}
|
522
455
|
|
523
456
|
if (!(nsUri == null || "".equals(nsUri) || "http://www.w3.org/XML/1998/namespace".equals(nsUri))) {
|
524
|
-
// Create a new namespace object and add it to the document
|
525
|
-
// namespace cache.
|
457
|
+
// Create a new namespace object and add it to the document namespace cache.
|
526
458
|
// TODO: why do we need the namespace cache ?
|
527
|
-
XmlNamespace.createFromAttr(context.
|
459
|
+
XmlNamespace.createFromAttr(context.runtime, attr);
|
528
460
|
}
|
529
461
|
NokogiriHelpers.renameNode(attr, nsUri, nodeName);
|
530
462
|
}
|
531
463
|
}
|
532
464
|
|
533
465
|
if (this.node.hasChildNodes()) {
|
534
|
-
|
535
|
-
|
466
|
+
relink_namespace(context, getChildren());
|
467
|
+
}
|
468
|
+
}
|
469
|
+
|
470
|
+
static void relink_namespace(ThreadContext context, IRubyObject[] nodes) {
|
471
|
+
for (int i = 0; i < nodes.length; i++) {
|
472
|
+
if (nodes[i] instanceof XmlNode) {
|
473
|
+
((XmlNode) nodes[i]).relink_namespace(context);
|
474
|
+
}
|
536
475
|
}
|
537
476
|
}
|
538
477
|
|
539
478
|
// Users might extend XmlNode. This method works for such a case.
|
540
479
|
public void accept(ThreadContext context, SaveContextVisitor visitor) {
|
541
480
|
visitor.enter(node);
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
481
|
+
acceptChildren(context, getChildren(), visitor);
|
482
|
+
visitor.leave(node);
|
483
|
+
}
|
484
|
+
|
485
|
+
void acceptChildren(ThreadContext context, IRubyObject[] nodes, SaveContextVisitor visitor) {
|
486
|
+
if (nodes.length > 0) {
|
487
|
+
for (int i = 0; i < nodes.length; i++) {
|
488
|
+
Object item = nodes[i];
|
547
489
|
if (item instanceof XmlNode) {
|
548
|
-
|
549
|
-
cur.accept(context, visitor);
|
490
|
+
((XmlNode) item).accept(context, visitor);
|
550
491
|
} else if (item instanceof XmlNamespace) {
|
551
|
-
XmlNamespace
|
552
|
-
cur.accept(context, visitor);
|
492
|
+
((XmlNamespace) item).accept(context, visitor);
|
553
493
|
}
|
554
494
|
}
|
555
495
|
}
|
556
|
-
visitor.leave(node);
|
557
496
|
}
|
558
497
|
|
559
|
-
|
560
|
-
this.name =
|
498
|
+
RubyString doSetName(IRubyObject name) {
|
499
|
+
if (name.isNil()) return this.name = null;
|
500
|
+
return this.name = name.convertToString();
|
561
501
|
}
|
562
502
|
|
563
|
-
public void setDocument(ThreadContext context,
|
503
|
+
public void setDocument(ThreadContext context, XmlDocument doc) {
|
564
504
|
this.doc = doc;
|
565
505
|
|
566
506
|
setDocumentAndDecorate(context, this, doc);
|
567
507
|
}
|
568
508
|
|
569
509
|
// shared logic with XmlNodeSet
|
570
|
-
static void setDocumentAndDecorate(ThreadContext context, RubyObject self,
|
571
|
-
self.setInstanceVariable("@document", doc);
|
572
|
-
if (doc != null)
|
573
|
-
Helpers.invoke(context, doc, "decorate", self);
|
574
|
-
}
|
510
|
+
static void setDocumentAndDecorate(ThreadContext context, RubyObject self, XmlDocument doc) {
|
511
|
+
self.setInstanceVariable("@document", doc == null ? context.nil : doc);
|
512
|
+
if (doc != null) Helpers.invoke(context, doc, "decorate", self);
|
575
513
|
}
|
576
514
|
|
577
|
-
public void setNode(
|
515
|
+
public void setNode(Ruby runtime, Node node) {
|
578
516
|
this.node = node;
|
579
517
|
|
580
|
-
decorate(
|
518
|
+
decorate(runtime);
|
581
519
|
|
582
520
|
if (this instanceof XmlAttr) {
|
583
|
-
((XmlAttr)this).setNamespaceIfNecessary(
|
584
|
-
}
|
585
|
-
}
|
586
|
-
|
587
|
-
public void updateNodeNamespaceIfNecessary(ThreadContext context, XmlNamespace ns) {
|
588
|
-
String oldPrefix = this.node.getPrefix();
|
589
|
-
String uri = rubyStringToString(ns.href(context));
|
590
|
-
|
591
|
-
/*
|
592
|
-
* Update if both prefixes are null or equal
|
593
|
-
*/
|
594
|
-
boolean update = (oldPrefix == null && ns.prefix(context).isNil()) ||
|
595
|
-
(oldPrefix != null && !ns.prefix(context).isNil()
|
596
|
-
&& oldPrefix.equals(rubyStringToString(ns.prefix(context))));
|
597
|
-
|
598
|
-
if(update) {
|
599
|
-
this.node = NokogiriHelpers.renameNode(this.node, uri, this.node.getNodeName());
|
521
|
+
((XmlAttr) this).setNamespaceIfNecessary(runtime);
|
600
522
|
}
|
601
523
|
}
|
602
524
|
|
@@ -605,12 +527,11 @@ public class XmlNode extends RubyObject {
|
|
605
527
|
|
606
528
|
String str = null;
|
607
529
|
if (node != null) {
|
608
|
-
str = node.getNodeName();
|
609
|
-
str = NokogiriHelpers.getLocalPart(str);
|
530
|
+
str = NokogiriHelpers.getLocalPart(node.getNodeName());
|
610
531
|
}
|
611
532
|
if (str == null) str = "";
|
612
|
-
if (str.startsWith("#")) str = str.substring(1);
|
613
|
-
return name =
|
533
|
+
if (str.startsWith("#")) str = str.substring(1); // eliminates '#'
|
534
|
+
return name = context.runtime.newString(str);
|
614
535
|
}
|
615
536
|
|
616
537
|
/**
|
@@ -619,26 +540,20 @@ public class XmlNode extends RubyObject {
|
|
619
540
|
* <code>xmlns:prefix="uri"</code>.
|
620
541
|
*/
|
621
542
|
@JRubyMethod(name = {"add_namespace_definition", "add_namespace"})
|
622
|
-
public IRubyObject add_namespace_definition(ThreadContext context,
|
623
|
-
|
624
|
-
IRubyObject href) {
|
625
|
-
String prefixString = rubyStringToString(prefix);
|
626
|
-
String hrefString ;
|
543
|
+
public IRubyObject add_namespace_definition(ThreadContext context, IRubyObject prefix, IRubyObject href) {
|
544
|
+
String hrefStr, prefixStr = prefix.isNil() ? null : prefix.convertToString().decodeString();
|
627
545
|
|
628
546
|
// try to search the namespace first
|
629
547
|
if (href.isNil()) {
|
630
|
-
|
631
|
-
if (
|
632
|
-
|
633
|
-
}
|
634
|
-
href = context.getRuntime().newString(hrefString);
|
548
|
+
hrefStr = findNamespaceHref(context, prefixStr);
|
549
|
+
if (hrefStr == null) return context.nil;
|
550
|
+
href = context.runtime.newString(hrefStr);
|
635
551
|
} else {
|
636
|
-
|
552
|
+
hrefStr = rubyStringToString(href.convertToString());
|
637
553
|
}
|
638
554
|
|
639
|
-
NokogiriNamespaceCache nsCache = NokogiriHelpers.
|
640
|
-
XmlNamespace cachedNamespace = nsCache.get(
|
641
|
-
|
555
|
+
NokogiriNamespaceCache nsCache = NokogiriHelpers.getNamespaceCache(node);
|
556
|
+
XmlNamespace cachedNamespace = nsCache.get(prefixStr, hrefStr);
|
642
557
|
if (cachedNamespace != null) return cachedNamespace;
|
643
558
|
|
644
559
|
Node namespaceOwner;
|
@@ -646,48 +561,58 @@ public class XmlNode extends RubyObject {
|
|
646
561
|
namespaceOwner = node;
|
647
562
|
Element element = (Element) node;
|
648
563
|
// adds namespace as node's attribute
|
649
|
-
|
650
|
-
|
651
|
-
prefix.isNil() ? "xmlns" : "xmlns:" + prefixString;
|
652
|
-
|
653
|
-
element.setAttributeNS(uri, qName, hrefString);
|
564
|
+
String qName = prefix.isNil() ? "xmlns" : "xmlns:" + prefixStr;
|
565
|
+
element.setAttributeNS("http://www.w3.org/2000/xmlns/", qName, hrefStr);
|
654
566
|
}
|
655
|
-
else if (node.getNodeType() == Node.ATTRIBUTE_NODE) namespaceOwner = ((Attr)node).getOwnerElement();
|
567
|
+
else if (node.getNodeType() == Node.ATTRIBUTE_NODE) namespaceOwner = ((Attr) node).getOwnerElement();
|
656
568
|
else namespaceOwner = node.getParentNode();
|
657
|
-
XmlNamespace ns = XmlNamespace.createFromPrefixAndHref(namespaceOwner, prefix, href);
|
658
|
-
if (node != namespaceOwner) {
|
659
569
|
|
660
|
-
|
570
|
+
XmlNamespace ns = XmlNamespace.createImpl(namespaceOwner, prefix, prefixStr, href, hrefStr);
|
571
|
+
|
572
|
+
if (node != namespaceOwner) {
|
573
|
+
node = NokogiriHelpers.renameNode(node, ns.getHref(), ns.getPrefix() + ':' + node.getLocalName());
|
661
574
|
}
|
662
|
-
updateNodeNamespaceIfNecessary(
|
575
|
+
updateNodeNamespaceIfNecessary(ns);
|
663
576
|
|
664
577
|
return ns;
|
665
578
|
}
|
666
579
|
|
580
|
+
private void updateNodeNamespaceIfNecessary(XmlNamespace ns) {
|
581
|
+
String oldPrefix = this.node.getPrefix();
|
582
|
+
|
583
|
+
/*
|
584
|
+
* Update if both prefixes are null or equal
|
585
|
+
*/
|
586
|
+
boolean update =
|
587
|
+
(oldPrefix == null && ns.getPrefix() == null) ||
|
588
|
+
(oldPrefix != null && oldPrefix.equals(ns.getPrefix()));
|
589
|
+
|
590
|
+
if (update) {
|
591
|
+
this.node = NokogiriHelpers.renameNode(this.node, ns.getHref(), this.node.getNodeName());
|
592
|
+
}
|
593
|
+
}
|
594
|
+
|
667
595
|
@JRubyMethod(name = {"attribute", "attr"})
|
668
596
|
public IRubyObject attribute(ThreadContext context, IRubyObject name){
|
669
597
|
NamedNodeMap attrs = this.node.getAttributes();
|
670
598
|
Node attr = attrs.getNamedItem(rubyStringToString(name));
|
671
|
-
if(attr == null)
|
672
|
-
|
673
|
-
}
|
674
|
-
return getCachedNodeOrCreate(context.getRuntime(), attr);
|
599
|
+
if (attr == null) return context.nil;
|
600
|
+
return getCachedNodeOrCreate(context.runtime, attr);
|
675
601
|
}
|
676
602
|
|
677
603
|
@JRubyMethod
|
678
604
|
public IRubyObject attribute_nodes(ThreadContext context) {
|
679
|
-
|
605
|
+
final Ruby runtime = context.runtime;
|
680
606
|
|
681
|
-
|
682
|
-
if(nodeMap == null){
|
683
|
-
return ruby.newEmptyArray();
|
684
|
-
}
|
607
|
+
NamedNodeMap nodeMap = this.node.getAttributes();
|
685
608
|
|
686
|
-
|
609
|
+
if (nodeMap == null) return runtime.newEmptyArray();
|
610
|
+
RubyArray attr = runtime.newArray(nodeMap.getLength());
|
687
611
|
|
688
|
-
|
612
|
+
final XmlDocument doc = document(context.runtime);
|
613
|
+
for (int i = 0; i < nodeMap.getLength(); i++) {
|
689
614
|
if ((doc instanceof HtmlDocument) || !NokogiriHelpers.isNamespace(nodeMap.item(i))) {
|
690
|
-
attr.append(getCachedNodeOrCreate(
|
615
|
+
attr.append(getCachedNodeOrCreate(runtime, nodeMap.item(i)));
|
691
616
|
}
|
692
617
|
}
|
693
618
|
|
@@ -701,10 +626,9 @@ public class XmlNode extends RubyObject {
|
|
701
626
|
|
702
627
|
Node el = this.node.getAttributes().getNamedItemNS(nsj, namej);
|
703
628
|
|
704
|
-
if(el == null)
|
705
|
-
|
706
|
-
|
707
|
-
return NokogiriHelpers.getCachedNodeOrCreate(context.getRuntime(), el);
|
629
|
+
if (el == null) return context.nil;
|
630
|
+
|
631
|
+
return NokogiriHelpers.getCachedNodeOrCreate(context.runtime, el);
|
708
632
|
}
|
709
633
|
|
710
634
|
@JRubyMethod(name = "blank?")
|
@@ -725,55 +649,58 @@ public class XmlNode extends RubyObject {
|
|
725
649
|
|
726
650
|
@JRubyMethod
|
727
651
|
public IRubyObject children(ThreadContext context) {
|
728
|
-
|
652
|
+
final IRubyObject[] nodes = getChildren();
|
653
|
+
if (nodes.length == 0) {
|
654
|
+
return XmlNodeSet.newEmptyNodeSet(context, this);
|
655
|
+
}
|
656
|
+
return XmlNodeSet.newNodeSet(context.runtime, nodes);
|
657
|
+
}
|
729
658
|
|
659
|
+
IRubyObject[] getChildren() {
|
730
660
|
NodeList nodeList = node.getChildNodes();
|
731
661
|
if (nodeList.getLength() > 0) {
|
732
|
-
|
733
|
-
}
|
734
|
-
else { // TODO this is very ripe for refactoring
|
735
|
-
setDocumentAndDecorate(context, xmlNodeSet, doc);
|
662
|
+
return nodeListToRubyArray(getRuntime(), nodeList);
|
736
663
|
}
|
737
|
-
|
738
|
-
return xmlNodeSet;
|
664
|
+
return IRubyObject.NULL_ARRAY;
|
739
665
|
}
|
740
666
|
|
741
667
|
@JRubyMethod
|
742
668
|
public IRubyObject first_element_child(ThreadContext context) {
|
743
|
-
List<Node> elementNodes =
|
744
|
-
|
745
|
-
|
746
|
-
return getCachedNodeOrCreate(context.getRuntime(), elementNodes.get(0));
|
669
|
+
List<Node> elementNodes = getElements(node, true);
|
670
|
+
if (elementNodes.size() == 0) return context.nil;
|
671
|
+
return getCachedNodeOrCreate(context.runtime, elementNodes.get(0));
|
747
672
|
}
|
748
673
|
|
749
674
|
@JRubyMethod
|
750
675
|
public IRubyObject last_element_child(ThreadContext context) {
|
751
|
-
List<Node> elementNodes =
|
752
|
-
|
753
|
-
|
754
|
-
return getCachedNodeOrCreate(context.getRuntime(), elementNodes.get(elementNodes.size()-1));
|
676
|
+
List<Node> elementNodes = getElements(node, false);
|
677
|
+
if (elementNodes.size() == 0) return context.nil;
|
678
|
+
return getCachedNodeOrCreate(context.runtime, elementNodes.get(elementNodes.size() - 1));
|
755
679
|
}
|
756
680
|
|
757
681
|
@JRubyMethod(name = {"element_children", "elements"})
|
758
682
|
public IRubyObject element_children(ThreadContext context) {
|
759
|
-
List<Node> elementNodes =
|
760
|
-
|
761
|
-
|
762
|
-
elementNodes.toArray(new Node[0]));
|
763
|
-
XmlNodeSet xmlNodeSet = XmlNodeSet.newXmlNodeSet(context, array);
|
764
|
-
return xmlNodeSet;
|
683
|
+
List<Node> elementNodes = getElements(node, false);
|
684
|
+
IRubyObject[] array = NokogiriHelpers.nodeListToArray(context.runtime, elementNodes);
|
685
|
+
return XmlNodeSet.newNodeSet(context.runtime, array, this);
|
765
686
|
}
|
766
687
|
|
767
|
-
private
|
768
|
-
NodeList children =
|
769
|
-
if (children.getLength() == 0)
|
688
|
+
private static List<Node> getElements(Node node, final boolean firstOnly) {
|
689
|
+
NodeList children = node.getChildNodes();
|
690
|
+
if (children.getLength() == 0) {
|
691
|
+
return Collections.emptyList();
|
692
|
+
}
|
693
|
+
ArrayList<Node> elements = firstOnly ? null : new ArrayList<Node>(children.getLength());
|
770
694
|
for (int i=0; i< children.getLength(); i++) {
|
771
695
|
Node child = children.item(i);
|
772
696
|
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
773
|
-
|
774
|
-
|
697
|
+
if (firstOnly) {
|
698
|
+
return Collections.singletonList(child);
|
699
|
+
}
|
700
|
+
elements.add(child);
|
775
701
|
}
|
776
702
|
}
|
703
|
+
return elements;
|
777
704
|
}
|
778
705
|
|
779
706
|
/**
|
@@ -785,7 +712,7 @@ public class XmlNode extends RubyObject {
|
|
785
712
|
@JRubyMethod(visibility=Visibility.PRIVATE)
|
786
713
|
public IRubyObject compare(ThreadContext context, IRubyObject other) {
|
787
714
|
if (!(other instanceof XmlNode)) {
|
788
|
-
return context.
|
715
|
+
return context.runtime.newFixnum(-2);
|
789
716
|
}
|
790
717
|
|
791
718
|
Node otherNode = asXmlNode(context, other).node;
|
@@ -793,22 +720,22 @@ public class XmlNode extends RubyObject {
|
|
793
720
|
// Do not touch this if, if it's not for a good reason.
|
794
721
|
if (node.getNodeType() == Node.DOCUMENT_NODE ||
|
795
722
|
otherNode.getNodeType() == Node.DOCUMENT_NODE) {
|
796
|
-
return context.
|
723
|
+
return context.runtime.newFixnum(1);
|
797
724
|
}
|
798
725
|
|
799
726
|
try{
|
800
727
|
int res = node.compareDocumentPosition(otherNode);
|
801
728
|
if ((res & FIRST_PRECEDES_SECOND) == FIRST_PRECEDES_SECOND) {
|
802
|
-
return context.
|
729
|
+
return context.runtime.newFixnum(-1);
|
803
730
|
} else if ((res & SECOND_PRECEDES_FIRST) == SECOND_PRECEDES_FIRST) {
|
804
|
-
return context.
|
731
|
+
return context.runtime.newFixnum(1);
|
805
732
|
} else if (res == IDENTICAL_ELEMENTS) {
|
806
|
-
return context.
|
733
|
+
return context.runtime.newFixnum(0);
|
807
734
|
}
|
808
735
|
|
809
|
-
return context.
|
736
|
+
return context.runtime.newFixnum(-2);
|
810
737
|
} catch (Exception ex) {
|
811
|
-
return context.
|
738
|
+
return context.runtime.newFixnum(-2);
|
812
739
|
}
|
813
740
|
}
|
814
741
|
|
@@ -818,35 +745,27 @@ public class XmlNode extends RubyObject {
|
|
818
745
|
* <code>options</code> into account.
|
819
746
|
*/
|
820
747
|
@JRubyMethod(required = 2, visibility = Visibility.PRIVATE)
|
821
|
-
public IRubyObject in_context(ThreadContext context,
|
822
|
-
|
823
|
-
IRubyObject options) {
|
824
|
-
RubyModule klass;
|
748
|
+
public IRubyObject in_context(ThreadContext context, IRubyObject str, IRubyObject options) {
|
749
|
+
RubyClass klass;
|
825
750
|
XmlDomParserContext ctx;
|
826
751
|
InputStream istream;
|
827
|
-
XmlDocument document;
|
828
752
|
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
} else {
|
834
|
-
return runtime.getNil();
|
835
|
-
}
|
753
|
+
final Ruby runtime = context.runtime;
|
754
|
+
|
755
|
+
XmlDocument document = document(runtime);
|
756
|
+
if (document == null) return context.nil;
|
836
757
|
|
837
758
|
if (document instanceof HtmlDocument) {
|
838
759
|
klass = getNokogiriClass(runtime, "Nokogiri::HTML::Document");
|
839
760
|
ctx = new HtmlDomParserContext(runtime, options);
|
840
|
-
((HtmlDomParserContext)ctx).enableDocumentFragment();
|
841
|
-
|
761
|
+
((HtmlDomParserContext) ctx).enableDocumentFragment();
|
762
|
+
ctx.setStringInputSource(context, str, context.nil);
|
842
763
|
} else {
|
843
764
|
klass = getNokogiriClass(runtime, "Nokogiri::XML::Document");
|
844
765
|
ctx = new XmlDomParserContext(runtime, options);
|
845
|
-
|
846
|
-
istream = new ByteArrayInputStream(input.getBytes());
|
766
|
+
ctx.setStringInputSource(context, str, context.nil);
|
847
767
|
}
|
848
768
|
|
849
|
-
ctx.setInputSource(istream);
|
850
769
|
// TODO: for some reason, document.getEncoding() can be null or nil (don't know why)
|
851
770
|
// run `test_parse_with_unparented_html_text_context_node' few times to see this happen
|
852
771
|
if (document instanceof HtmlDocument && !(document.getEncoding() == null || document.getEncoding().isNil())) {
|
@@ -854,17 +773,16 @@ public class XmlNode extends RubyObject {
|
|
854
773
|
htmlCtx.setEncoding(document.getEncoding().asJavaString());
|
855
774
|
}
|
856
775
|
|
857
|
-
XmlDocument doc = ctx.parse(context, klass,
|
776
|
+
XmlDocument doc = ctx.parse(context, klass, context.nil);
|
858
777
|
|
859
|
-
RubyArray documentErrors =
|
860
|
-
RubyArray docErrors =
|
861
|
-
if (
|
778
|
+
RubyArray documentErrors = getErrors(document);
|
779
|
+
RubyArray docErrors = getErrors(doc);
|
780
|
+
if (checkNewErrors(documentErrors, docErrors)) {
|
862
781
|
for (int i = 0; i < docErrors.getLength(); i++) {
|
863
|
-
documentErrors.
|
782
|
+
documentErrors.append(docErrors.entry(i));
|
864
783
|
}
|
865
784
|
document.setInstanceVariable("@errors", documentErrors);
|
866
|
-
|
867
|
-
return xmlNodeSet;
|
785
|
+
return XmlNodeSet.newNodeSet(context.runtime, IRubyObject.NULL_ARRAY, this);
|
868
786
|
}
|
869
787
|
|
870
788
|
// The first child might be document type node (dtd declaration).
|
@@ -876,27 +794,24 @@ public class XmlNode extends RubyObject {
|
|
876
794
|
first = doc.node.getFirstChild();
|
877
795
|
}
|
878
796
|
|
879
|
-
IRubyObject[] nodes = new IRubyObject[]{NokogiriHelpers.getCachedNodeOrCreate(runtime, first)};
|
880
|
-
|
881
|
-
return xmlNodeSet;
|
797
|
+
IRubyObject[] nodes = new IRubyObject[] { NokogiriHelpers.getCachedNodeOrCreate(runtime, first) };
|
798
|
+
return XmlNodeSet.newNodeSet(context.runtime, nodes, this);
|
882
799
|
}
|
883
800
|
|
884
|
-
private RubyArray
|
801
|
+
private static RubyArray getErrors(XmlDocument document) {
|
885
802
|
IRubyObject obj = document.getInstanceVariable("@errors");
|
886
|
-
if (obj
|
887
|
-
|
888
|
-
}
|
889
|
-
return RubyArray.newArray(document.getRuntime());
|
803
|
+
if (obj instanceof RubyArray) return (RubyArray) obj;
|
804
|
+
return RubyArray.newEmptyArray(document.getRuntime());
|
890
805
|
}
|
891
806
|
|
892
|
-
private boolean
|
893
|
-
int length = ((RubyArray)
|
807
|
+
private static boolean checkNewErrors(RubyArray baseErrors, RubyArray newErrors) {
|
808
|
+
int length = ((RubyArray) newErrors.op_diff(baseErrors)).size();
|
894
809
|
return length > 0;
|
895
810
|
}
|
896
811
|
|
897
812
|
@JRubyMethod(name = {"content", "text", "inner_text"})
|
898
813
|
public IRubyObject content(ThreadContext context) {
|
899
|
-
return stringOrNil(context.
|
814
|
+
return stringOrNil(context.runtime, getContentImpl());
|
900
815
|
}
|
901
816
|
|
902
817
|
public CharSequence getContentImpl() {
|
@@ -906,7 +821,7 @@ public class XmlNode extends RubyObject {
|
|
906
821
|
}
|
907
822
|
CharSequence textContent;
|
908
823
|
if (this instanceof XmlDocument) {
|
909
|
-
Node node = ((Document)this.node).getDocumentElement();
|
824
|
+
Node node = ((Document) this.node).getDocumentElement();
|
910
825
|
if (node == null) {
|
911
826
|
textContent = "";
|
912
827
|
} else {
|
@@ -920,7 +835,7 @@ public class XmlNode extends RubyObject {
|
|
920
835
|
return textContent;
|
921
836
|
}
|
922
837
|
|
923
|
-
private StringBuilder getTextContentRecursively(StringBuilder buffer, Node currentNode) {
|
838
|
+
private static StringBuilder getTextContentRecursively(StringBuilder buffer, Node currentNode) {
|
924
839
|
CharSequence textContent = currentNode.getNodeValue();
|
925
840
|
if (textContent != null && NokogiriHelpers.shouldDecode(currentNode)) {
|
926
841
|
textContent = NokogiriHelpers.decodeJavaString(textContent);
|
@@ -934,7 +849,7 @@ public class XmlNode extends RubyObject {
|
|
934
849
|
return buffer;
|
935
850
|
}
|
936
851
|
|
937
|
-
private boolean hasTextContent(Node child) {
|
852
|
+
private static boolean hasTextContent(Node child) {
|
938
853
|
return child.getNodeType() != Node.COMMENT_NODE && child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE;
|
939
854
|
}
|
940
855
|
|
@@ -943,13 +858,17 @@ public class XmlNode extends RubyObject {
|
|
943
858
|
return document(context.runtime);
|
944
859
|
}
|
945
860
|
|
946
|
-
|
861
|
+
XmlDocument document(final Ruby runtime) {
|
862
|
+
return document(runtime, true);
|
863
|
+
}
|
864
|
+
|
865
|
+
XmlDocument document(final Ruby runtime, boolean create) {
|
947
866
|
if (doc == null) {
|
948
867
|
doc = (XmlDocument) node.getOwnerDocument().getUserData(NokogiriHelpers.CACHED_NODE);
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
868
|
+
if (doc == null && create) {
|
869
|
+
doc = (XmlDocument) getCachedNodeOrCreate(runtime, node.getOwnerDocument());
|
870
|
+
node.getOwnerDocument().setUserData(NokogiriHelpers.CACHED_NODE, doc, null);
|
871
|
+
}
|
953
872
|
}
|
954
873
|
return doc;
|
955
874
|
}
|
@@ -970,7 +889,7 @@ public class XmlNode extends RubyObject {
|
|
970
889
|
}
|
971
890
|
|
972
891
|
protected final IRubyObject dup_implementation(ThreadContext context, boolean deep) {
|
973
|
-
return dup_implementation(context.
|
892
|
+
return dup_implementation(context.runtime, deep);
|
974
893
|
}
|
975
894
|
|
976
895
|
protected IRubyObject dup_implementation(Ruby runtime, boolean deep) {
|
@@ -987,15 +906,14 @@ public class XmlNode extends RubyObject {
|
|
987
906
|
|
988
907
|
public static RubyString encode_special_chars(ThreadContext context, IRubyObject string) {
|
989
908
|
CharSequence str = NokogiriHelpers.encodeJavaString( rubyStringToString(string) );
|
990
|
-
return RubyString.newString(context.
|
909
|
+
return RubyString.newString(context.runtime, str);
|
991
910
|
}
|
992
911
|
|
993
912
|
/**
|
994
913
|
* Instance method version of the above static method.
|
995
914
|
*/
|
996
915
|
@JRubyMethod(name="encode_special_chars")
|
997
|
-
public IRubyObject i_encode_special_chars(ThreadContext context,
|
998
|
-
IRubyObject string) {
|
916
|
+
public IRubyObject i_encode_special_chars(ThreadContext context, IRubyObject string) {
|
999
917
|
return encode_special_chars(context, string);
|
1000
918
|
}
|
1001
919
|
|
@@ -1007,14 +925,14 @@ public class XmlNode extends RubyObject {
|
|
1007
925
|
@JRubyMethod(visibility = Visibility.PRIVATE)
|
1008
926
|
public IRubyObject get(ThreadContext context, IRubyObject rbkey) {
|
1009
927
|
if (node instanceof Element) {
|
1010
|
-
if (rbkey == null || rbkey.isNil()) context.
|
928
|
+
if (rbkey == null || rbkey.isNil()) return context.nil;
|
1011
929
|
String key = rubyStringToString(rbkey);
|
1012
930
|
Element element = (Element) node;
|
1013
|
-
if (!element.hasAttribute(key)) return context.
|
931
|
+
if (!element.hasAttribute(key)) return context.nil;
|
1014
932
|
String value = element.getAttribute(key);
|
1015
|
-
return stringOrNil(context.
|
933
|
+
return stringOrNil(context.runtime, value);
|
1016
934
|
}
|
1017
|
-
return context.
|
935
|
+
return context.nil;
|
1018
936
|
}
|
1019
937
|
|
1020
938
|
/**
|
@@ -1050,8 +968,7 @@ public class XmlNode extends RubyObject {
|
|
1050
968
|
IRubyObject system_id) {
|
1051
969
|
IRubyObject subset = internal_subset(context);
|
1052
970
|
if (!subset.isNil()) {
|
1053
|
-
throw context.
|
1054
|
-
.newRuntimeError("Document already has internal subset");
|
971
|
+
throw context.runtime.newRuntimeError("Document already has internal subset");
|
1055
972
|
}
|
1056
973
|
|
1057
974
|
Document document = getOwnerDocument();
|
@@ -1087,8 +1004,7 @@ public class XmlNode extends RubyObject {
|
|
1087
1004
|
IRubyObject system_id) {
|
1088
1005
|
IRubyObject subset = external_subset(context);
|
1089
1006
|
if (!subset.isNil()) {
|
1090
|
-
throw context.
|
1091
|
-
.newRuntimeError("Document already has external subset");
|
1007
|
+
throw context.runtime.newRuntimeError("Document already has external subset");
|
1092
1008
|
}
|
1093
1009
|
|
1094
1010
|
Document document = getOwnerDocument();
|
@@ -1110,42 +1026,40 @@ public class XmlNode extends RubyObject {
|
|
1110
1026
|
String key = rubyStringToString(rbkey);
|
1111
1027
|
Element element = (Element) node;
|
1112
1028
|
if (element.hasAttribute(key)) {
|
1113
|
-
return context.
|
1029
|
+
return context.runtime.getTrue();
|
1114
1030
|
} else {
|
1115
1031
|
NamedNodeMap namedNodeMap = element.getAttributes();
|
1116
1032
|
for (int i=0; i<namedNodeMap.getLength(); i++) {
|
1117
1033
|
Node n = namedNodeMap.item(i);
|
1118
1034
|
if (key.equals(n.getLocalName())) {
|
1119
|
-
return context.
|
1035
|
+
return context.runtime.getTrue();
|
1120
1036
|
}
|
1121
1037
|
}
|
1122
1038
|
}
|
1123
|
-
return context.
|
1124
|
-
} else {
|
1125
|
-
return context.getRuntime().getNil();
|
1039
|
+
return context.runtime.getFalse();
|
1126
1040
|
}
|
1041
|
+
return context.nil;
|
1127
1042
|
}
|
1128
1043
|
|
1129
1044
|
@JRubyMethod
|
1130
1045
|
public IRubyObject namespace(ThreadContext context) {
|
1131
|
-
|
1132
|
-
if (doc instanceof HtmlDocument) return
|
1133
|
-
|
1046
|
+
final XmlDocument doc = document(context.runtime);
|
1047
|
+
if (doc instanceof HtmlDocument) return context.nil;
|
1048
|
+
|
1134
1049
|
String namespaceURI = node.getNamespaceURI();
|
1135
|
-
if (namespaceURI == null || namespaceURI
|
1136
|
-
return
|
1050
|
+
if (namespaceURI == null || namespaceURI.isEmpty()) {
|
1051
|
+
return context.nil;
|
1137
1052
|
}
|
1138
1053
|
|
1139
1054
|
String prefix = node.getPrefix();
|
1140
|
-
|
1055
|
+
NokogiriNamespaceCache nsCache = NokogiriHelpers.getNamespaceCache(node);
|
1056
|
+
XmlNamespace namespace = nsCache.get(prefix, namespaceURI);
|
1057
|
+
|
1141
1058
|
if (namespace == null || namespace.isEmpty()) {
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
IRubyObject rubyPrefix = NokogiriHelpers.stringOrNil(runtime, prefix);
|
1147
|
-
IRubyObject rubyUri = NokogiriHelpers.stringOrNil(runtime, namespaceURI);
|
1148
|
-
namespace.init(null, rubyPrefix, rubyUri, doc);
|
1059
|
+
// if it's not in the cache, create an unowned, uncached namespace and
|
1060
|
+
// return that. XmlReader can't insert namespaces into the cache, so
|
1061
|
+
// this is necessary for XmlReader to work correctly.
|
1062
|
+
namespace = new XmlNamespace(context.runtime, null, prefix, namespaceURI, doc);
|
1149
1063
|
}
|
1150
1064
|
|
1151
1065
|
return namespace;
|
@@ -1159,18 +1073,14 @@ public class XmlNode extends RubyObject {
|
|
1159
1073
|
public IRubyObject namespace_definitions(ThreadContext context) {
|
1160
1074
|
// don't use namespace_definitions cache anymore since
|
1161
1075
|
// namespaces might be deleted. Reflecting the result of
|
1162
|
-
//
|
1076
|
+
// namespace removals is complicated, so the cache might not be
|
1163
1077
|
// updated.
|
1164
|
-
|
1165
|
-
|
1166
|
-
if (doc
|
1167
|
-
if (doc instanceof HtmlDocument) return namespace_definitions;
|
1168
|
-
List<XmlNamespace> namespaces = ((XmlDocument)doc).getNamespaceCache().get(node);
|
1169
|
-
for (XmlNamespace namespace : namespaces) {
|
1170
|
-
namespace_definitions.append(namespace);
|
1171
|
-
}
|
1078
|
+
final XmlDocument doc = document(context.runtime);
|
1079
|
+
if (doc == null) return context.runtime.newEmptyArray();
|
1080
|
+
if (doc instanceof HtmlDocument) return context.runtime.newEmptyArray();
|
1172
1081
|
|
1173
|
-
|
1082
|
+
List<XmlNamespace> namespaces = doc.getNamespaceCache().get(node);
|
1083
|
+
return context.runtime.newArray((List) namespaces);
|
1174
1084
|
}
|
1175
1085
|
|
1176
1086
|
/**
|
@@ -1178,10 +1088,10 @@ public class XmlNode extends RubyObject {
|
|
1178
1088
|
* on any ancestor node.
|
1179
1089
|
*/
|
1180
1090
|
@JRubyMethod
|
1181
|
-
public
|
1182
|
-
|
1183
|
-
if (doc == null) return
|
1184
|
-
if (doc instanceof HtmlDocument) return
|
1091
|
+
public RubyArray namespace_scopes(ThreadContext context) {
|
1092
|
+
final XmlDocument doc = document(context.runtime);
|
1093
|
+
if (doc == null) return context.runtime.newEmptyArray();
|
1094
|
+
if (doc instanceof HtmlDocument) return context.runtime.newEmptyArray();
|
1185
1095
|
|
1186
1096
|
Node previousNode;
|
1187
1097
|
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
@@ -1191,11 +1101,12 @@ public class XmlNode extends RubyObject {
|
|
1191
1101
|
} else {
|
1192
1102
|
previousNode = findPreviousElement(node);
|
1193
1103
|
}
|
1194
|
-
if (previousNode == null) return
|
1104
|
+
if (previousNode == null) return context.runtime.newEmptyArray();
|
1195
1105
|
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1106
|
+
final RubyArray scoped_namespaces = context.runtime.newArray();
|
1107
|
+
final HashSet<String> prefixes_in_scope = new HashSet<String>(8);
|
1108
|
+
NokogiriNamespaceCache nsCache = NokogiriHelpers.getNamespaceCache(previousNode);
|
1109
|
+
for (Node previous = previousNode; previous != null; ) {
|
1199
1110
|
List<XmlNamespace> namespaces = nsCache.get(previous);
|
1200
1111
|
for (XmlNamespace namespace : namespaces) {
|
1201
1112
|
if (prefixes_in_scope.contains(namespace.getPrefix())) continue;
|
@@ -1220,7 +1131,7 @@ public class XmlNode extends RubyObject {
|
|
1220
1131
|
@JRubyMethod(name="namespaced_key?")
|
1221
1132
|
public IRubyObject namespaced_key_p(ThreadContext context, IRubyObject elementLName, IRubyObject namespaceUri) {
|
1222
1133
|
return this.attribute_with_ns(context, elementLName, namespaceUri).isNil() ?
|
1223
|
-
context.
|
1134
|
+
context.runtime.getFalse() : context.runtime.getTrue();
|
1224
1135
|
}
|
1225
1136
|
|
1226
1137
|
protected void setContent(IRubyObject content) {
|
@@ -1249,12 +1160,12 @@ public class XmlNode extends RubyObject {
|
|
1249
1160
|
IRubyObject currentObj = this ;
|
1250
1161
|
while (!currentObj.isNil()) {
|
1251
1162
|
XmlNode currentNode = asXmlNode(context, currentObj);
|
1252
|
-
IRubyObject lang = currentNode.getAttribute(context.
|
1163
|
+
IRubyObject lang = currentNode.getAttribute(context.runtime, "xml:lang");
|
1253
1164
|
if (!lang.isNil()) { return lang ; }
|
1254
1165
|
|
1255
1166
|
currentObj = currentNode.parent(context);
|
1256
1167
|
}
|
1257
|
-
return context.nil
|
1168
|
+
return context.nil;
|
1258
1169
|
}
|
1259
1170
|
|
1260
1171
|
@JRubyMethod(name = "lang=")
|
@@ -1277,7 +1188,7 @@ public class XmlNode extends RubyObject {
|
|
1277
1188
|
IRubyObject indentString = args[2];
|
1278
1189
|
IRubyObject options = args[3];
|
1279
1190
|
|
1280
|
-
String encString =
|
1191
|
+
String encString = rubyStringToString(encoding);
|
1281
1192
|
|
1282
1193
|
SaveContextVisitor visitor =
|
1283
1194
|
new SaveContextVisitor(RubyFixnum.fix2int(options), rubyStringToString(indentString), encString, isHtmlDoc(context), isFragment(), 0);
|
@@ -1285,11 +1196,11 @@ public class XmlNode extends RubyObject {
|
|
1285
1196
|
|
1286
1197
|
final IRubyObject rubyString;
|
1287
1198
|
if (NokogiriHelpers.isUTF8(encString)) {
|
1288
|
-
rubyString = convertString(context.
|
1199
|
+
rubyString = convertString(context.runtime, visitor.getInternalBuffer());
|
1289
1200
|
} else {
|
1290
1201
|
ByteBuffer bytes = convertEncoding(Charset.forName(encString), visitor.getInternalBuffer());
|
1291
1202
|
ByteList str = new ByteList(bytes.array(), bytes.arrayOffset(), bytes.remaining());
|
1292
|
-
rubyString = RubyString.newString(context.
|
1203
|
+
rubyString = RubyString.newString(context.runtime, str);
|
1293
1204
|
}
|
1294
1205
|
Helpers.invoke(context, io, "write", rubyString);
|
1295
1206
|
|
@@ -1297,7 +1208,7 @@ public class XmlNode extends RubyObject {
|
|
1297
1208
|
}
|
1298
1209
|
|
1299
1210
|
private boolean isHtmlDoc(ThreadContext context) {
|
1300
|
-
return document(context).getMetaClass().isKindOfModule(getNokogiriClass(context.
|
1211
|
+
return document(context).getMetaClass().isKindOfModule(getNokogiriClass(context.runtime, "Nokogiri::HTML::Document"));
|
1301
1212
|
}
|
1302
1213
|
|
1303
1214
|
private boolean isFragment() {
|
@@ -1316,14 +1227,6 @@ public class XmlNode extends RubyObject {
|
|
1316
1227
|
return getCachedNodeOrCreate(context.getRuntime(), node.getPreviousSibling());
|
1317
1228
|
}
|
1318
1229
|
|
1319
|
-
@JRubyMethod(meta = true, rest = true)
|
1320
|
-
public static IRubyObject new_from_str(ThreadContext context,
|
1321
|
-
IRubyObject cls,
|
1322
|
-
IRubyObject[] args) {
|
1323
|
-
XmlDocument doc = (XmlDocument) XmlDocument.read_memory(context, args);
|
1324
|
-
return doc.root(context);
|
1325
|
-
}
|
1326
|
-
|
1327
1230
|
@JRubyMethod(name = {"node_name", "name"})
|
1328
1231
|
public IRubyObject node_name(ThreadContext context) {
|
1329
1232
|
return getNodeName(context);
|
@@ -1331,9 +1234,9 @@ public class XmlNode extends RubyObject {
|
|
1331
1234
|
|
1332
1235
|
@JRubyMethod(name = {"node_name=", "name="})
|
1333
1236
|
public IRubyObject node_name_set(ThreadContext context, IRubyObject nodeName) {
|
1334
|
-
|
1237
|
+
nodeName = doSetName(nodeName);
|
1238
|
+
String newName = nodeName == null ? null : rubyStringToString((RubyString) nodeName);
|
1335
1239
|
this.node = NokogiriHelpers.renameNode(node, null, newName);
|
1336
|
-
setName(nodeName);
|
1337
1240
|
return this;
|
1338
1241
|
}
|
1339
1242
|
|
@@ -1372,23 +1275,19 @@ public class XmlNode extends RubyObject {
|
|
1372
1275
|
}
|
1373
1276
|
|
1374
1277
|
private String findNamespaceHref(ThreadContext context, String prefix) {
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
break;
|
1387
|
-
} else {
|
1388
|
-
currentNode = (XmlNode) currentNode.parent(context);
|
1278
|
+
XmlNode currentNode = this;
|
1279
|
+
final XmlDocument doc = document(context.runtime);
|
1280
|
+
while (currentNode != doc) {
|
1281
|
+
RubyArray namespaces = currentNode.namespace_scopes(context);
|
1282
|
+
for (int i = 0; i<namespaces.size(); i++) {
|
1283
|
+
XmlNamespace namespace = (XmlNamespace) namespaces.eltInternal(i);
|
1284
|
+
if (namespace.hasPrefix(prefix)) return namespace.getHref();
|
1285
|
+
}
|
1286
|
+
IRubyObject parent = currentNode.parent(context);
|
1287
|
+
if (parent == context.nil) break;
|
1288
|
+
currentNode = (XmlNode) parent;
|
1389
1289
|
}
|
1390
|
-
|
1391
|
-
return null;
|
1290
|
+
return null;
|
1392
1291
|
}
|
1393
1292
|
|
1394
1293
|
@JRubyMethod
|
@@ -1400,35 +1299,31 @@ public class XmlNode extends RubyObject {
|
|
1400
1299
|
if (node.getOwnerDocument() != null &&
|
1401
1300
|
node.getOwnerDocument().getDocumentElement() == node) {
|
1402
1301
|
return document(context);
|
1403
|
-
} else {
|
1404
|
-
return getCachedNodeOrCreate(context.getRuntime(), node.getParentNode());
|
1405
1302
|
}
|
1303
|
+
return getCachedNodeOrCreate(context.runtime, node.getParentNode());
|
1406
1304
|
}
|
1407
1305
|
|
1408
1306
|
@JRubyMethod
|
1409
1307
|
public IRubyObject path(ThreadContext context) {
|
1410
|
-
return RubyString.newString(context.
|
1308
|
+
return RubyString.newString(context.runtime, NokogiriHelpers.getNodeCompletePath(this.node));
|
1411
1309
|
}
|
1412
1310
|
|
1413
1311
|
@JRubyMethod
|
1414
1312
|
public IRubyObject pointer_id(ThreadContext context) {
|
1415
|
-
return RubyFixnum.newFixnum(context.
|
1313
|
+
return RubyFixnum.newFixnum(context.runtime, this.node.hashCode());
|
1416
1314
|
}
|
1417
1315
|
|
1418
1316
|
@JRubyMethod(visibility=Visibility.PRIVATE)
|
1419
1317
|
public IRubyObject set_namespace(ThreadContext context, IRubyObject namespace) {
|
1420
1318
|
if (namespace.isNil()) {
|
1319
|
+
XmlDocument doc = document(context.runtime);
|
1421
1320
|
if (doc != null) {
|
1422
|
-
Node
|
1423
|
-
|
1424
|
-
|
1425
|
-
((XmlDocument)doc).getNamespaceCache().remove(prefix == null ? "" : prefix, href);
|
1426
|
-
this.node = NokogiriHelpers.renameNode(n, null, NokogiriHelpers.getLocalPart(n.getNodeName()));
|
1321
|
+
Node node = this.node;
|
1322
|
+
doc.getNamespaceCache().remove(node);
|
1323
|
+
this.node = NokogiriHelpers.renameNode(node, null, NokogiriHelpers.getLocalPart(node.getNodeName()));
|
1427
1324
|
}
|
1428
1325
|
} else {
|
1429
1326
|
XmlNamespace ns = (XmlNamespace) namespace;
|
1430
|
-
String prefix = rubyStringToString(ns.prefix(context));
|
1431
|
-
String href = rubyStringToString(ns.href(context));
|
1432
1327
|
|
1433
1328
|
// Assigning node = ...renameNode() or not seems to make no
|
1434
1329
|
// difference. Why not? -pmahoney
|
@@ -1438,8 +1333,8 @@ public class XmlNode extends RubyObject {
|
|
1438
1333
|
// The node you passed in *might* come back as you expect, but
|
1439
1334
|
// it might not. It's much safer to throw away the original
|
1440
1335
|
// and keep the return value. -mbklein
|
1441
|
-
String new_name = NokogiriHelpers.newQName(
|
1442
|
-
this.node = NokogiriHelpers.renameNode(node,
|
1336
|
+
String new_name = NokogiriHelpers.newQName(ns.getPrefix(), node);
|
1337
|
+
this.node = NokogiriHelpers.renameNode(node, ns.getHref(), new_name);
|
1443
1338
|
}
|
1444
1339
|
|
1445
1340
|
clearXpathContext(getNode());
|
@@ -1493,10 +1388,10 @@ public class XmlNode extends RubyObject {
|
|
1493
1388
|
case Node.DOCUMENT_FRAGMENT_NODE: type = "DOCUMENT_FRAG_NODE"; break;
|
1494
1389
|
case Node.NOTATION_NODE: type = "NOTATION_NODE"; break;
|
1495
1390
|
default:
|
1496
|
-
return context.
|
1391
|
+
return context.runtime.newFixnum(0);
|
1497
1392
|
}
|
1498
1393
|
|
1499
|
-
return getNokogiriClass(context.
|
1394
|
+
return getNokogiriClass(context.runtime, "Nokogiri::XML::Node").getConstant(type);
|
1500
1395
|
}
|
1501
1396
|
|
1502
1397
|
@JRubyMethod
|
@@ -1504,7 +1399,7 @@ public class XmlNode extends RubyObject {
|
|
1504
1399
|
Node root = getOwnerDocument();
|
1505
1400
|
int[] counter = new int[1];
|
1506
1401
|
count(root, counter);
|
1507
|
-
return RubyFixnum.newFixnum(context.
|
1402
|
+
return RubyFixnum.newFixnum(context.runtime, counter[0]+1);
|
1508
1403
|
}
|
1509
1404
|
|
1510
1405
|
private boolean count(Node node, int[] counter) {
|
@@ -1526,27 +1421,25 @@ public class XmlNode extends RubyObject {
|
|
1526
1421
|
@JRubyMethod
|
1527
1422
|
public IRubyObject next_element(ThreadContext context) {
|
1528
1423
|
Node nextNode = node.getNextSibling();
|
1529
|
-
|
1530
|
-
if (nextNode == null) return ruby.getNil();
|
1424
|
+
if (nextNode == null) return context.nil;
|
1531
1425
|
if (nextNode instanceof Element) {
|
1532
|
-
return getCachedNodeOrCreate(context.
|
1426
|
+
return getCachedNodeOrCreate(context.runtime, nextNode);
|
1533
1427
|
}
|
1534
1428
|
Node deeper = nextNode.getNextSibling();
|
1535
|
-
if (deeper == null) return
|
1536
|
-
return getCachedNodeOrCreate(context.
|
1429
|
+
if (deeper == null) return context.nil;
|
1430
|
+
return getCachedNodeOrCreate(context.runtime, deeper);
|
1537
1431
|
}
|
1538
1432
|
|
1539
1433
|
@JRubyMethod
|
1540
1434
|
public IRubyObject previous_element(ThreadContext context) {
|
1541
1435
|
Node prevNode = node.getPreviousSibling();
|
1542
|
-
|
1543
|
-
if (prevNode == null) return ruby.getNil();
|
1436
|
+
if (prevNode == null) return context.nil;
|
1544
1437
|
if (prevNode instanceof Element) {
|
1545
|
-
return getCachedNodeOrCreate(context.
|
1438
|
+
return getCachedNodeOrCreate(context.runtime, prevNode);
|
1546
1439
|
}
|
1547
1440
|
Node shallower = prevNode.getPreviousSibling();
|
1548
|
-
if (shallower == null) return
|
1549
|
-
return getCachedNodeOrCreate(context.
|
1441
|
+
if (shallower == null) return context.nil;
|
1442
|
+
return getCachedNodeOrCreate(context.runtime, shallower);
|
1550
1443
|
}
|
1551
1444
|
|
1552
1445
|
protected enum AdoptScheme {
|
@@ -1557,13 +1450,11 @@ public class XmlNode extends RubyObject {
|
|
1557
1450
|
* Adopt XmlNode <code>other</code> into the document of
|
1558
1451
|
* <code>this</code> using the specified scheme.
|
1559
1452
|
*/
|
1560
|
-
protected IRubyObject adoptAs(ThreadContext context, AdoptScheme scheme,
|
1561
|
-
|
1562
|
-
XmlNode other = asXmlNode(context, other_);
|
1453
|
+
protected IRubyObject adoptAs(ThreadContext context, AdoptScheme scheme, IRubyObject other_) {
|
1454
|
+
final XmlNode other = asXmlNode(context, other_);
|
1563
1455
|
// this.doc might be null since this node can be empty node.
|
1564
|
-
if (
|
1565
|
-
|
1566
|
-
}
|
1456
|
+
if (doc != null) other.setDocument(context, doc);
|
1457
|
+
|
1567
1458
|
IRubyObject nodeOrTags = other;
|
1568
1459
|
Node thisNode = node;
|
1569
1460
|
Node otherNode = other.node;
|
@@ -1572,18 +1463,18 @@ public class XmlNode extends RubyObject {
|
|
1572
1463
|
Document prev = otherNode.getOwnerDocument();
|
1573
1464
|
Document doc = thisNode.getOwnerDocument();
|
1574
1465
|
if (doc == null && thisNode instanceof Document) {
|
1575
|
-
|
1576
|
-
|
1466
|
+
// we are adding the new node to a new empty document
|
1467
|
+
doc = (Document) thisNode;
|
1577
1468
|
}
|
1578
1469
|
clearXpathContext(prev);
|
1579
1470
|
clearXpathContext(doc);
|
1580
1471
|
if (doc != null && doc != otherNode.getOwnerDocument()) {
|
1581
1472
|
Node ret = doc.adoptNode(otherNode);
|
1582
|
-
// FIXME: this is really a hack, see documentation of fixUserData() for more details.
|
1583
|
-
fixUserData(prev, ret);
|
1584
1473
|
if (ret == null) {
|
1585
|
-
throw context.
|
1474
|
+
throw context.runtime.newRuntimeError("Failed to take ownership of node");
|
1586
1475
|
}
|
1476
|
+
// FIXME: this is really a hack, see documentation of fixUserData() for more details.
|
1477
|
+
fixUserData(prev, ret);
|
1587
1478
|
otherNode = ret;
|
1588
1479
|
}
|
1589
1480
|
|
@@ -1591,11 +1482,11 @@ public class XmlNode extends RubyObject {
|
|
1591
1482
|
|
1592
1483
|
switch (scheme) {
|
1593
1484
|
case CHILD:
|
1594
|
-
Node[] children = adoptAsChild(
|
1485
|
+
Node[] children = adoptAsChild(thisNode, otherNode);
|
1595
1486
|
if (children.length == 1 && otherNode == children[0]) {
|
1596
1487
|
break;
|
1597
1488
|
} else {
|
1598
|
-
nodeOrTags = nodeArrayToRubyArray(context.
|
1489
|
+
nodeOrTags = nodeArrayToRubyArray(context.runtime, children);
|
1599
1490
|
}
|
1600
1491
|
break;
|
1601
1492
|
case PREV_SIBLING:
|
@@ -1609,7 +1500,7 @@ public class XmlNode extends RubyObject {
|
|
1609
1500
|
break;
|
1610
1501
|
}
|
1611
1502
|
} catch (Exception e) {
|
1612
|
-
throw context.
|
1503
|
+
throw context.runtime.newRuntimeError(e.toString());
|
1613
1504
|
}
|
1614
1505
|
|
1615
1506
|
if (otherNode.getNodeType() == Node.TEXT_NODE) {
|
@@ -1630,42 +1521,38 @@ public class XmlNode extends RubyObject {
|
|
1630
1521
|
* It looks like CoreDocumentImpl.adoptNode() doesn't copy
|
1631
1522
|
* the user data associated with child nodes (recursively).
|
1632
1523
|
*/
|
1633
|
-
private void fixUserData(Document previous, Node ret) {
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1524
|
+
private static void fixUserData(Document previous, Node ret) {
|
1525
|
+
final String key = NokogiriHelpers.ENCODED_STRING;
|
1526
|
+
for (Node child = ret.getFirstChild(); child != null; child = child.getNextSibling()) {
|
1527
|
+
CoreDocumentImpl previousDocument = (CoreDocumentImpl) previous;
|
1528
|
+
child.setUserData(key, previousDocument.getUserData(child, key), null);
|
1529
|
+
fixUserData(previous, child);
|
1530
|
+
}
|
1640
1531
|
}
|
1641
1532
|
|
1642
|
-
|
1643
|
-
Node otherNode) {
|
1533
|
+
private Node[] adoptAsChild(final Node parent, Node otherNode) {
|
1644
1534
|
/*
|
1645
|
-
* This is a bit of a hack. C-Nokogiri allows adding a bare
|
1646
|
-
*
|
1647
|
-
* not. So we wrap the text node in an element.
|
1535
|
+
* This is a bit of a hack. C-Nokogiri allows adding a bare text node as the root element.
|
1536
|
+
* Java (and XML spec?) does not. So we wrap the text node in an element.
|
1648
1537
|
*/
|
1649
1538
|
if (parent.getNodeType() == Node.DOCUMENT_NODE && otherNode.getNodeType() == Node.TEXT_NODE) {
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
|
1539
|
+
Element e = (Element) parent.getFirstChild();
|
1540
|
+
if (e == null || !e.getNodeName().equals(TEXT_WRAPPER_NAME)) {
|
1541
|
+
e = ((Document) parent).createElement(TEXT_WRAPPER_NAME);
|
1542
|
+
adoptAsChild(parent, e);
|
1543
|
+
}
|
1544
|
+
e.appendChild(otherNode);
|
1545
|
+
otherNode = e;
|
1657
1546
|
} else {
|
1658
|
-
|
1659
|
-
|
1547
|
+
addNamespaceURIIfNeeded(otherNode);
|
1548
|
+
parent.appendChild(otherNode);
|
1660
1549
|
}
|
1661
|
-
Node[]
|
1662
|
-
nodes[0] = otherNode;
|
1663
|
-
return nodes;
|
1550
|
+
return new Node[] { otherNode };
|
1664
1551
|
}
|
1665
1552
|
|
1666
1553
|
private void addNamespaceURIIfNeeded(Node child) {
|
1667
|
-
if (this instanceof XmlDocumentFragment && ((XmlDocumentFragment)this).getFragmentContext() != null) {
|
1668
|
-
XmlElement fragmentContext = ((XmlDocumentFragment)this).getFragmentContext();
|
1554
|
+
if (this instanceof XmlDocumentFragment && ((XmlDocumentFragment) this).getFragmentContext() != null) {
|
1555
|
+
XmlElement fragmentContext = ((XmlDocumentFragment) this).getFragmentContext();
|
1669
1556
|
String namespace_uri = fragmentContext.node.getNamespaceURI();
|
1670
1557
|
if (namespace_uri != null && namespace_uri.length() > 0) {
|
1671
1558
|
NokogiriHelpers.renameNode(child, namespace_uri, child.getNodeName());
|
@@ -1722,7 +1609,7 @@ public class XmlNode extends RubyObject {
|
|
1722
1609
|
parentNode.replaceChild(otherNode, thisNode);
|
1723
1610
|
} catch (Exception e) {
|
1724
1611
|
String prefix = "could not replace child: ";
|
1725
|
-
throw context.
|
1612
|
+
throw context.runtime.newRuntimeError(prefix + e.toString());
|
1726
1613
|
}
|
1727
1614
|
}
|
1728
1615
|
|
@@ -1773,7 +1660,7 @@ public class XmlNode extends RubyObject {
|
|
1773
1660
|
while(errors.getLength() > 0) {
|
1774
1661
|
XmlSyntaxError error = (XmlSyntaxError)errors.shift(context);
|
1775
1662
|
if (error.toString().contains("Include operation failed")) {
|
1776
|
-
throw
|
1663
|
+
throw error.toThrowable();
|
1777
1664
|
}
|
1778
1665
|
}
|
1779
1666
|
return this;
|
@@ -1784,4 +1671,14 @@ public class XmlNode extends RubyObject {
|
|
1784
1671
|
clearXpathContext(getNode());
|
1785
1672
|
return context.nil ;
|
1786
1673
|
}
|
1674
|
+
|
1675
|
+
@SuppressWarnings("unchecked")
|
1676
|
+
@Override
|
1677
|
+
public Object toJava(final Class target) {
|
1678
|
+
if (target == Object.class || Node.class.isAssignableFrom(target)) {
|
1679
|
+
return getNode();
|
1680
|
+
}
|
1681
|
+
return super.toJava(target);
|
1682
|
+
}
|
1683
|
+
|
1787
1684
|
}
|