nokogiri 1.10.8-java → 1.11.0.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.
- checksums.yaml +4 -4
- data/README.md +24 -22
- data/ext/java/nokogiri/HtmlDocument.java +34 -46
- data/ext/java/nokogiri/HtmlSaxParserContext.java +87 -57
- 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 +300 -401
- data/ext/java/nokogiri/XmlNodeSet.java +72 -77
- data/ext/java/nokogiri/XmlReader.java +10 -11
- data/ext/java/nokogiri/XmlSaxParserContext.java +7 -7
- data/ext/java/nokogiri/XmlSchema.java +3 -3
- data/ext/java/nokogiri/XmlText.java +12 -9
- data/ext/java/nokogiri/XmlXpathContext.java +7 -7
- data/ext/java/nokogiri/XsltStylesheet.java +7 -15
- data/ext/java/nokogiri/internals/HtmlDomParserContext.java +4 -10
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +71 -135
- data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +90 -58
- data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +5 -4
- 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 +17 -32
- data/ext/nokogiri/extconf.rb +50 -37
- data/ext/nokogiri/nokogiri.c +12 -6
- data/ext/nokogiri/nokogiri.h +13 -0
- data/ext/nokogiri/xml_document.c +16 -2
- data/ext/nokogiri/xml_io.c +8 -6
- data/ext/nokogiri/xml_node.c +20 -0
- data/ext/nokogiri/xml_reader.c +6 -17
- data/ext/nokogiri/xml_schema.c +29 -0
- data/ext/nokogiri/xslt_stylesheet.c +0 -4
- data/lib/nokogiri.rb +3 -20
- data/lib/nokogiri/css.rb +1 -0
- data/lib/nokogiri/css/node.rb +1 -0
- data/lib/nokogiri/css/parser.rb +61 -60
- 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 +3 -1
- 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 +1 -0
- 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 +86 -45
- 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 +3 -8
- data/lib/nokogiri/xml/document_fragment.rb +1 -0
- 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 +539 -224
- 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 +4 -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 +1 -0
- 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 +1 -0
- data/lib/nokogiri/xml/searchable.rb +22 -15
- 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 +53 -34
- data/ext/java/nokogiri/internals/NokogiriEncodingReaderWrapper.java +0 -107
- data/ext/java/nokogiri/internals/UncloseableInputStream.java +0 -102
@@ -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,26 +745,20 @@ 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();
|
761
|
+
((HtmlDomParserContext) ctx).enableDocumentFragment();
|
841
762
|
istream = new ByteArrayInputStream((rubyStringToString(str)).getBytes());
|
842
763
|
} else {
|
843
764
|
klass = getNokogiriClass(runtime, "Nokogiri::XML::Document");
|
@@ -854,17 +775,16 @@ public class XmlNode extends RubyObject {
|
|
854
775
|
htmlCtx.setEncoding(document.getEncoding().asJavaString());
|
855
776
|
}
|
856
777
|
|
857
|
-
XmlDocument doc = ctx.parse(context, klass,
|
778
|
+
XmlDocument doc = ctx.parse(context, klass, context.nil);
|
858
779
|
|
859
|
-
RubyArray documentErrors =
|
860
|
-
RubyArray docErrors =
|
861
|
-
if (
|
780
|
+
RubyArray documentErrors = getErrors(document);
|
781
|
+
RubyArray docErrors = getErrors(doc);
|
782
|
+
if (checkNewErrors(documentErrors, docErrors)) {
|
862
783
|
for (int i = 0; i < docErrors.getLength(); i++) {
|
863
|
-
documentErrors.
|
784
|
+
documentErrors.append(docErrors.entry(i));
|
864
785
|
}
|
865
786
|
document.setInstanceVariable("@errors", documentErrors);
|
866
|
-
|
867
|
-
return xmlNodeSet;
|
787
|
+
return XmlNodeSet.newNodeSet(context.runtime, IRubyObject.NULL_ARRAY, this);
|
868
788
|
}
|
869
789
|
|
870
790
|
// The first child might be document type node (dtd declaration).
|
@@ -876,27 +796,24 @@ public class XmlNode extends RubyObject {
|
|
876
796
|
first = doc.node.getFirstChild();
|
877
797
|
}
|
878
798
|
|
879
|
-
IRubyObject[] nodes = new IRubyObject[]{NokogiriHelpers.getCachedNodeOrCreate(runtime, first)};
|
880
|
-
|
881
|
-
return xmlNodeSet;
|
799
|
+
IRubyObject[] nodes = new IRubyObject[] { NokogiriHelpers.getCachedNodeOrCreate(runtime, first) };
|
800
|
+
return XmlNodeSet.newNodeSet(context.runtime, nodes, this);
|
882
801
|
}
|
883
802
|
|
884
|
-
private RubyArray
|
803
|
+
private static RubyArray getErrors(XmlDocument document) {
|
885
804
|
IRubyObject obj = document.getInstanceVariable("@errors");
|
886
|
-
if (obj
|
887
|
-
|
888
|
-
}
|
889
|
-
return RubyArray.newArray(document.getRuntime());
|
805
|
+
if (obj instanceof RubyArray) return (RubyArray) obj;
|
806
|
+
return RubyArray.newEmptyArray(document.getRuntime());
|
890
807
|
}
|
891
808
|
|
892
|
-
private boolean
|
893
|
-
int length = ((RubyArray)
|
809
|
+
private static boolean checkNewErrors(RubyArray baseErrors, RubyArray newErrors) {
|
810
|
+
int length = ((RubyArray) newErrors.op_diff(baseErrors)).size();
|
894
811
|
return length > 0;
|
895
812
|
}
|
896
813
|
|
897
814
|
@JRubyMethod(name = {"content", "text", "inner_text"})
|
898
815
|
public IRubyObject content(ThreadContext context) {
|
899
|
-
return stringOrNil(context.
|
816
|
+
return stringOrNil(context.runtime, getContentImpl());
|
900
817
|
}
|
901
818
|
|
902
819
|
public CharSequence getContentImpl() {
|
@@ -906,7 +823,7 @@ public class XmlNode extends RubyObject {
|
|
906
823
|
}
|
907
824
|
CharSequence textContent;
|
908
825
|
if (this instanceof XmlDocument) {
|
909
|
-
Node node = ((Document)this.node).getDocumentElement();
|
826
|
+
Node node = ((Document) this.node).getDocumentElement();
|
910
827
|
if (node == null) {
|
911
828
|
textContent = "";
|
912
829
|
} else {
|
@@ -920,7 +837,7 @@ public class XmlNode extends RubyObject {
|
|
920
837
|
return textContent;
|
921
838
|
}
|
922
839
|
|
923
|
-
private StringBuilder getTextContentRecursively(StringBuilder buffer, Node currentNode) {
|
840
|
+
private static StringBuilder getTextContentRecursively(StringBuilder buffer, Node currentNode) {
|
924
841
|
CharSequence textContent = currentNode.getNodeValue();
|
925
842
|
if (textContent != null && NokogiriHelpers.shouldDecode(currentNode)) {
|
926
843
|
textContent = NokogiriHelpers.decodeJavaString(textContent);
|
@@ -934,7 +851,7 @@ public class XmlNode extends RubyObject {
|
|
934
851
|
return buffer;
|
935
852
|
}
|
936
853
|
|
937
|
-
private boolean hasTextContent(Node child) {
|
854
|
+
private static boolean hasTextContent(Node child) {
|
938
855
|
return child.getNodeType() != Node.COMMENT_NODE && child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE;
|
939
856
|
}
|
940
857
|
|
@@ -943,13 +860,17 @@ public class XmlNode extends RubyObject {
|
|
943
860
|
return document(context.runtime);
|
944
861
|
}
|
945
862
|
|
946
|
-
|
863
|
+
XmlDocument document(final Ruby runtime) {
|
864
|
+
return document(runtime, true);
|
865
|
+
}
|
866
|
+
|
867
|
+
XmlDocument document(final Ruby runtime, boolean create) {
|
947
868
|
if (doc == null) {
|
948
869
|
doc = (XmlDocument) node.getOwnerDocument().getUserData(NokogiriHelpers.CACHED_NODE);
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
870
|
+
if (doc == null && create) {
|
871
|
+
doc = (XmlDocument) getCachedNodeOrCreate(runtime, node.getOwnerDocument());
|
872
|
+
node.getOwnerDocument().setUserData(NokogiriHelpers.CACHED_NODE, doc, null);
|
873
|
+
}
|
953
874
|
}
|
954
875
|
return doc;
|
955
876
|
}
|
@@ -970,7 +891,7 @@ public class XmlNode extends RubyObject {
|
|
970
891
|
}
|
971
892
|
|
972
893
|
protected final IRubyObject dup_implementation(ThreadContext context, boolean deep) {
|
973
|
-
return dup_implementation(context.
|
894
|
+
return dup_implementation(context.runtime, deep);
|
974
895
|
}
|
975
896
|
|
976
897
|
protected IRubyObject dup_implementation(Ruby runtime, boolean deep) {
|
@@ -987,15 +908,14 @@ public class XmlNode extends RubyObject {
|
|
987
908
|
|
988
909
|
public static RubyString encode_special_chars(ThreadContext context, IRubyObject string) {
|
989
910
|
CharSequence str = NokogiriHelpers.encodeJavaString( rubyStringToString(string) );
|
990
|
-
return RubyString.newString(context.
|
911
|
+
return RubyString.newString(context.runtime, str);
|
991
912
|
}
|
992
913
|
|
993
914
|
/**
|
994
915
|
* Instance method version of the above static method.
|
995
916
|
*/
|
996
917
|
@JRubyMethod(name="encode_special_chars")
|
997
|
-
public IRubyObject i_encode_special_chars(ThreadContext context,
|
998
|
-
IRubyObject string) {
|
918
|
+
public IRubyObject i_encode_special_chars(ThreadContext context, IRubyObject string) {
|
999
919
|
return encode_special_chars(context, string);
|
1000
920
|
}
|
1001
921
|
|
@@ -1007,14 +927,14 @@ public class XmlNode extends RubyObject {
|
|
1007
927
|
@JRubyMethod(visibility = Visibility.PRIVATE)
|
1008
928
|
public IRubyObject get(ThreadContext context, IRubyObject rbkey) {
|
1009
929
|
if (node instanceof Element) {
|
1010
|
-
if (rbkey == null || rbkey.isNil()) context.
|
930
|
+
if (rbkey == null || rbkey.isNil()) return context.nil;
|
1011
931
|
String key = rubyStringToString(rbkey);
|
1012
932
|
Element element = (Element) node;
|
1013
|
-
if (!element.hasAttribute(key)) return context.
|
933
|
+
if (!element.hasAttribute(key)) return context.nil;
|
1014
934
|
String value = element.getAttribute(key);
|
1015
|
-
return stringOrNil(context.
|
935
|
+
return stringOrNil(context.runtime, value);
|
1016
936
|
}
|
1017
|
-
return context.
|
937
|
+
return context.nil;
|
1018
938
|
}
|
1019
939
|
|
1020
940
|
/**
|
@@ -1050,8 +970,7 @@ public class XmlNode extends RubyObject {
|
|
1050
970
|
IRubyObject system_id) {
|
1051
971
|
IRubyObject subset = internal_subset(context);
|
1052
972
|
if (!subset.isNil()) {
|
1053
|
-
throw context.
|
1054
|
-
.newRuntimeError("Document already has internal subset");
|
973
|
+
throw context.runtime.newRuntimeError("Document already has internal subset");
|
1055
974
|
}
|
1056
975
|
|
1057
976
|
Document document = getOwnerDocument();
|
@@ -1087,8 +1006,7 @@ public class XmlNode extends RubyObject {
|
|
1087
1006
|
IRubyObject system_id) {
|
1088
1007
|
IRubyObject subset = external_subset(context);
|
1089
1008
|
if (!subset.isNil()) {
|
1090
|
-
throw context.
|
1091
|
-
.newRuntimeError("Document already has external subset");
|
1009
|
+
throw context.runtime.newRuntimeError("Document already has external subset");
|
1092
1010
|
}
|
1093
1011
|
|
1094
1012
|
Document document = getOwnerDocument();
|
@@ -1110,42 +1028,40 @@ public class XmlNode extends RubyObject {
|
|
1110
1028
|
String key = rubyStringToString(rbkey);
|
1111
1029
|
Element element = (Element) node;
|
1112
1030
|
if (element.hasAttribute(key)) {
|
1113
|
-
return context.
|
1031
|
+
return context.runtime.getTrue();
|
1114
1032
|
} else {
|
1115
1033
|
NamedNodeMap namedNodeMap = element.getAttributes();
|
1116
1034
|
for (int i=0; i<namedNodeMap.getLength(); i++) {
|
1117
1035
|
Node n = namedNodeMap.item(i);
|
1118
1036
|
if (key.equals(n.getLocalName())) {
|
1119
|
-
return context.
|
1037
|
+
return context.runtime.getTrue();
|
1120
1038
|
}
|
1121
1039
|
}
|
1122
1040
|
}
|
1123
|
-
return context.
|
1124
|
-
} else {
|
1125
|
-
return context.getRuntime().getNil();
|
1041
|
+
return context.runtime.getFalse();
|
1126
1042
|
}
|
1043
|
+
return context.nil;
|
1127
1044
|
}
|
1128
1045
|
|
1129
1046
|
@JRubyMethod
|
1130
1047
|
public IRubyObject namespace(ThreadContext context) {
|
1131
|
-
|
1132
|
-
if (doc instanceof HtmlDocument) return
|
1133
|
-
|
1048
|
+
final XmlDocument doc = document(context.runtime);
|
1049
|
+
if (doc instanceof HtmlDocument) return context.nil;
|
1050
|
+
|
1134
1051
|
String namespaceURI = node.getNamespaceURI();
|
1135
|
-
if (namespaceURI == null || namespaceURI
|
1136
|
-
return
|
1052
|
+
if (namespaceURI == null || namespaceURI.isEmpty()) {
|
1053
|
+
return context.nil;
|
1137
1054
|
}
|
1138
1055
|
|
1139
1056
|
String prefix = node.getPrefix();
|
1140
|
-
|
1057
|
+
NokogiriNamespaceCache nsCache = NokogiriHelpers.getNamespaceCache(node);
|
1058
|
+
XmlNamespace namespace = nsCache.get(prefix, namespaceURI);
|
1059
|
+
|
1141
1060
|
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);
|
1061
|
+
// if it's not in the cache, create an unowned, uncached namespace and
|
1062
|
+
// return that. XmlReader can't insert namespaces into the cache, so
|
1063
|
+
// this is necessary for XmlReader to work correctly.
|
1064
|
+
namespace = new XmlNamespace(context.runtime, null, prefix, namespaceURI, doc);
|
1149
1065
|
}
|
1150
1066
|
|
1151
1067
|
return namespace;
|
@@ -1159,18 +1075,14 @@ public class XmlNode extends RubyObject {
|
|
1159
1075
|
public IRubyObject namespace_definitions(ThreadContext context) {
|
1160
1076
|
// don't use namespace_definitions cache anymore since
|
1161
1077
|
// namespaces might be deleted. Reflecting the result of
|
1162
|
-
//
|
1078
|
+
// namespace removals is complicated, so the cache might not be
|
1163
1079
|
// 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
|
-
}
|
1080
|
+
final XmlDocument doc = document(context.runtime);
|
1081
|
+
if (doc == null) return context.runtime.newEmptyArray();
|
1082
|
+
if (doc instanceof HtmlDocument) return context.runtime.newEmptyArray();
|
1172
1083
|
|
1173
|
-
|
1084
|
+
List<XmlNamespace> namespaces = doc.getNamespaceCache().get(node);
|
1085
|
+
return context.runtime.newArray((List) namespaces);
|
1174
1086
|
}
|
1175
1087
|
|
1176
1088
|
/**
|
@@ -1178,10 +1090,10 @@ public class XmlNode extends RubyObject {
|
|
1178
1090
|
* on any ancestor node.
|
1179
1091
|
*/
|
1180
1092
|
@JRubyMethod
|
1181
|
-
public
|
1182
|
-
|
1183
|
-
if (doc == null) return
|
1184
|
-
if (doc instanceof HtmlDocument) return
|
1093
|
+
public RubyArray namespace_scopes(ThreadContext context) {
|
1094
|
+
final XmlDocument doc = document(context.runtime);
|
1095
|
+
if (doc == null) return context.runtime.newEmptyArray();
|
1096
|
+
if (doc instanceof HtmlDocument) return context.runtime.newEmptyArray();
|
1185
1097
|
|
1186
1098
|
Node previousNode;
|
1187
1099
|
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
@@ -1191,11 +1103,12 @@ public class XmlNode extends RubyObject {
|
|
1191
1103
|
} else {
|
1192
1104
|
previousNode = findPreviousElement(node);
|
1193
1105
|
}
|
1194
|
-
if (previousNode == null) return
|
1106
|
+
if (previousNode == null) return context.runtime.newEmptyArray();
|
1195
1107
|
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1108
|
+
final RubyArray scoped_namespaces = context.runtime.newArray();
|
1109
|
+
final HashSet<String> prefixes_in_scope = new HashSet<String>(8);
|
1110
|
+
NokogiriNamespaceCache nsCache = NokogiriHelpers.getNamespaceCache(previousNode);
|
1111
|
+
for (Node previous = previousNode; previous != null; ) {
|
1199
1112
|
List<XmlNamespace> namespaces = nsCache.get(previous);
|
1200
1113
|
for (XmlNamespace namespace : namespaces) {
|
1201
1114
|
if (prefixes_in_scope.contains(namespace.getPrefix())) continue;
|
@@ -1220,7 +1133,7 @@ public class XmlNode extends RubyObject {
|
|
1220
1133
|
@JRubyMethod(name="namespaced_key?")
|
1221
1134
|
public IRubyObject namespaced_key_p(ThreadContext context, IRubyObject elementLName, IRubyObject namespaceUri) {
|
1222
1135
|
return this.attribute_with_ns(context, elementLName, namespaceUri).isNil() ?
|
1223
|
-
context.
|
1136
|
+
context.runtime.getFalse() : context.runtime.getTrue();
|
1224
1137
|
}
|
1225
1138
|
|
1226
1139
|
protected void setContent(IRubyObject content) {
|
@@ -1249,12 +1162,12 @@ public class XmlNode extends RubyObject {
|
|
1249
1162
|
IRubyObject currentObj = this ;
|
1250
1163
|
while (!currentObj.isNil()) {
|
1251
1164
|
XmlNode currentNode = asXmlNode(context, currentObj);
|
1252
|
-
IRubyObject lang = currentNode.getAttribute(context.
|
1165
|
+
IRubyObject lang = currentNode.getAttribute(context.runtime, "xml:lang");
|
1253
1166
|
if (!lang.isNil()) { return lang ; }
|
1254
1167
|
|
1255
1168
|
currentObj = currentNode.parent(context);
|
1256
1169
|
}
|
1257
|
-
return context.nil
|
1170
|
+
return context.nil;
|
1258
1171
|
}
|
1259
1172
|
|
1260
1173
|
@JRubyMethod(name = "lang=")
|
@@ -1277,7 +1190,7 @@ public class XmlNode extends RubyObject {
|
|
1277
1190
|
IRubyObject indentString = args[2];
|
1278
1191
|
IRubyObject options = args[3];
|
1279
1192
|
|
1280
|
-
String encString =
|
1193
|
+
String encString = rubyStringToString(encoding);
|
1281
1194
|
|
1282
1195
|
SaveContextVisitor visitor =
|
1283
1196
|
new SaveContextVisitor(RubyFixnum.fix2int(options), rubyStringToString(indentString), encString, isHtmlDoc(context), isFragment(), 0);
|
@@ -1285,11 +1198,11 @@ public class XmlNode extends RubyObject {
|
|
1285
1198
|
|
1286
1199
|
final IRubyObject rubyString;
|
1287
1200
|
if (NokogiriHelpers.isUTF8(encString)) {
|
1288
|
-
rubyString = convertString(context.
|
1201
|
+
rubyString = convertString(context.runtime, visitor.getInternalBuffer());
|
1289
1202
|
} else {
|
1290
1203
|
ByteBuffer bytes = convertEncoding(Charset.forName(encString), visitor.getInternalBuffer());
|
1291
1204
|
ByteList str = new ByteList(bytes.array(), bytes.arrayOffset(), bytes.remaining());
|
1292
|
-
rubyString = RubyString.newString(context.
|
1205
|
+
rubyString = RubyString.newString(context.runtime, str);
|
1293
1206
|
}
|
1294
1207
|
Helpers.invoke(context, io, "write", rubyString);
|
1295
1208
|
|
@@ -1297,7 +1210,7 @@ public class XmlNode extends RubyObject {
|
|
1297
1210
|
}
|
1298
1211
|
|
1299
1212
|
private boolean isHtmlDoc(ThreadContext context) {
|
1300
|
-
return document(context).getMetaClass().isKindOfModule(getNokogiriClass(context.
|
1213
|
+
return document(context).getMetaClass().isKindOfModule(getNokogiriClass(context.runtime, "Nokogiri::HTML::Document"));
|
1301
1214
|
}
|
1302
1215
|
|
1303
1216
|
private boolean isFragment() {
|
@@ -1316,14 +1229,6 @@ public class XmlNode extends RubyObject {
|
|
1316
1229
|
return getCachedNodeOrCreate(context.getRuntime(), node.getPreviousSibling());
|
1317
1230
|
}
|
1318
1231
|
|
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
1232
|
@JRubyMethod(name = {"node_name", "name"})
|
1328
1233
|
public IRubyObject node_name(ThreadContext context) {
|
1329
1234
|
return getNodeName(context);
|
@@ -1331,9 +1236,9 @@ public class XmlNode extends RubyObject {
|
|
1331
1236
|
|
1332
1237
|
@JRubyMethod(name = {"node_name=", "name="})
|
1333
1238
|
public IRubyObject node_name_set(ThreadContext context, IRubyObject nodeName) {
|
1334
|
-
|
1239
|
+
nodeName = doSetName(nodeName);
|
1240
|
+
String newName = nodeName == null ? null : rubyStringToString((RubyString) nodeName);
|
1335
1241
|
this.node = NokogiriHelpers.renameNode(node, null, newName);
|
1336
|
-
setName(nodeName);
|
1337
1242
|
return this;
|
1338
1243
|
}
|
1339
1244
|
|
@@ -1372,23 +1277,19 @@ public class XmlNode extends RubyObject {
|
|
1372
1277
|
}
|
1373
1278
|
|
1374
1279
|
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);
|
1280
|
+
XmlNode currentNode = this;
|
1281
|
+
final XmlDocument doc = document(context.runtime);
|
1282
|
+
while (currentNode != doc) {
|
1283
|
+
RubyArray namespaces = currentNode.namespace_scopes(context);
|
1284
|
+
for (int i = 0; i<namespaces.size(); i++) {
|
1285
|
+
XmlNamespace namespace = (XmlNamespace) namespaces.eltInternal(i);
|
1286
|
+
if (namespace.hasPrefix(prefix)) return namespace.getHref();
|
1287
|
+
}
|
1288
|
+
IRubyObject parent = currentNode.parent(context);
|
1289
|
+
if (parent == context.nil) break;
|
1290
|
+
currentNode = (XmlNode) parent;
|
1389
1291
|
}
|
1390
|
-
|
1391
|
-
return null;
|
1292
|
+
return null;
|
1392
1293
|
}
|
1393
1294
|
|
1394
1295
|
@JRubyMethod
|
@@ -1400,35 +1301,31 @@ public class XmlNode extends RubyObject {
|
|
1400
1301
|
if (node.getOwnerDocument() != null &&
|
1401
1302
|
node.getOwnerDocument().getDocumentElement() == node) {
|
1402
1303
|
return document(context);
|
1403
|
-
} else {
|
1404
|
-
return getCachedNodeOrCreate(context.getRuntime(), node.getParentNode());
|
1405
1304
|
}
|
1305
|
+
return getCachedNodeOrCreate(context.runtime, node.getParentNode());
|
1406
1306
|
}
|
1407
1307
|
|
1408
1308
|
@JRubyMethod
|
1409
1309
|
public IRubyObject path(ThreadContext context) {
|
1410
|
-
return RubyString.newString(context.
|
1310
|
+
return RubyString.newString(context.runtime, NokogiriHelpers.getNodeCompletePath(this.node));
|
1411
1311
|
}
|
1412
1312
|
|
1413
1313
|
@JRubyMethod
|
1414
1314
|
public IRubyObject pointer_id(ThreadContext context) {
|
1415
|
-
return RubyFixnum.newFixnum(context.
|
1315
|
+
return RubyFixnum.newFixnum(context.runtime, this.node.hashCode());
|
1416
1316
|
}
|
1417
1317
|
|
1418
1318
|
@JRubyMethod(visibility=Visibility.PRIVATE)
|
1419
1319
|
public IRubyObject set_namespace(ThreadContext context, IRubyObject namespace) {
|
1420
1320
|
if (namespace.isNil()) {
|
1321
|
+
XmlDocument doc = document(context.runtime);
|
1421
1322
|
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()));
|
1323
|
+
Node node = this.node;
|
1324
|
+
doc.getNamespaceCache().remove(node);
|
1325
|
+
this.node = NokogiriHelpers.renameNode(node, null, NokogiriHelpers.getLocalPart(node.getNodeName()));
|
1427
1326
|
}
|
1428
1327
|
} else {
|
1429
1328
|
XmlNamespace ns = (XmlNamespace) namespace;
|
1430
|
-
String prefix = rubyStringToString(ns.prefix(context));
|
1431
|
-
String href = rubyStringToString(ns.href(context));
|
1432
1329
|
|
1433
1330
|
// Assigning node = ...renameNode() or not seems to make no
|
1434
1331
|
// difference. Why not? -pmahoney
|
@@ -1438,8 +1335,8 @@ public class XmlNode extends RubyObject {
|
|
1438
1335
|
// The node you passed in *might* come back as you expect, but
|
1439
1336
|
// it might not. It's much safer to throw away the original
|
1440
1337
|
// and keep the return value. -mbklein
|
1441
|
-
String new_name = NokogiriHelpers.newQName(
|
1442
|
-
this.node = NokogiriHelpers.renameNode(node,
|
1338
|
+
String new_name = NokogiriHelpers.newQName(ns.getPrefix(), node);
|
1339
|
+
this.node = NokogiriHelpers.renameNode(node, ns.getHref(), new_name);
|
1443
1340
|
}
|
1444
1341
|
|
1445
1342
|
clearXpathContext(getNode());
|
@@ -1493,10 +1390,10 @@ public class XmlNode extends RubyObject {
|
|
1493
1390
|
case Node.DOCUMENT_FRAGMENT_NODE: type = "DOCUMENT_FRAG_NODE"; break;
|
1494
1391
|
case Node.NOTATION_NODE: type = "NOTATION_NODE"; break;
|
1495
1392
|
default:
|
1496
|
-
return context.
|
1393
|
+
return context.runtime.newFixnum(0);
|
1497
1394
|
}
|
1498
1395
|
|
1499
|
-
return getNokogiriClass(context.
|
1396
|
+
return getNokogiriClass(context.runtime, "Nokogiri::XML::Node").getConstant(type);
|
1500
1397
|
}
|
1501
1398
|
|
1502
1399
|
@JRubyMethod
|
@@ -1504,7 +1401,7 @@ public class XmlNode extends RubyObject {
|
|
1504
1401
|
Node root = getOwnerDocument();
|
1505
1402
|
int[] counter = new int[1];
|
1506
1403
|
count(root, counter);
|
1507
|
-
return RubyFixnum.newFixnum(context.
|
1404
|
+
return RubyFixnum.newFixnum(context.runtime, counter[0]+1);
|
1508
1405
|
}
|
1509
1406
|
|
1510
1407
|
private boolean count(Node node, int[] counter) {
|
@@ -1526,27 +1423,25 @@ public class XmlNode extends RubyObject {
|
|
1526
1423
|
@JRubyMethod
|
1527
1424
|
public IRubyObject next_element(ThreadContext context) {
|
1528
1425
|
Node nextNode = node.getNextSibling();
|
1529
|
-
|
1530
|
-
if (nextNode == null) return ruby.getNil();
|
1426
|
+
if (nextNode == null) return context.nil;
|
1531
1427
|
if (nextNode instanceof Element) {
|
1532
|
-
return getCachedNodeOrCreate(context.
|
1428
|
+
return getCachedNodeOrCreate(context.runtime, nextNode);
|
1533
1429
|
}
|
1534
1430
|
Node deeper = nextNode.getNextSibling();
|
1535
|
-
if (deeper == null) return
|
1536
|
-
return getCachedNodeOrCreate(context.
|
1431
|
+
if (deeper == null) return context.nil;
|
1432
|
+
return getCachedNodeOrCreate(context.runtime, deeper);
|
1537
1433
|
}
|
1538
1434
|
|
1539
1435
|
@JRubyMethod
|
1540
1436
|
public IRubyObject previous_element(ThreadContext context) {
|
1541
1437
|
Node prevNode = node.getPreviousSibling();
|
1542
|
-
|
1543
|
-
if (prevNode == null) return ruby.getNil();
|
1438
|
+
if (prevNode == null) return context.nil;
|
1544
1439
|
if (prevNode instanceof Element) {
|
1545
|
-
return getCachedNodeOrCreate(context.
|
1440
|
+
return getCachedNodeOrCreate(context.runtime, prevNode);
|
1546
1441
|
}
|
1547
1442
|
Node shallower = prevNode.getPreviousSibling();
|
1548
|
-
if (shallower == null) return
|
1549
|
-
return getCachedNodeOrCreate(context.
|
1443
|
+
if (shallower == null) return context.nil;
|
1444
|
+
return getCachedNodeOrCreate(context.runtime, shallower);
|
1550
1445
|
}
|
1551
1446
|
|
1552
1447
|
protected enum AdoptScheme {
|
@@ -1557,13 +1452,11 @@ public class XmlNode extends RubyObject {
|
|
1557
1452
|
* Adopt XmlNode <code>other</code> into the document of
|
1558
1453
|
* <code>this</code> using the specified scheme.
|
1559
1454
|
*/
|
1560
|
-
protected IRubyObject adoptAs(ThreadContext context, AdoptScheme scheme,
|
1561
|
-
|
1562
|
-
XmlNode other = asXmlNode(context, other_);
|
1455
|
+
protected IRubyObject adoptAs(ThreadContext context, AdoptScheme scheme, IRubyObject other_) {
|
1456
|
+
final XmlNode other = asXmlNode(context, other_);
|
1563
1457
|
// this.doc might be null since this node can be empty node.
|
1564
|
-
if (
|
1565
|
-
|
1566
|
-
}
|
1458
|
+
if (doc != null) other.setDocument(context, doc);
|
1459
|
+
|
1567
1460
|
IRubyObject nodeOrTags = other;
|
1568
1461
|
Node thisNode = node;
|
1569
1462
|
Node otherNode = other.node;
|
@@ -1572,18 +1465,18 @@ public class XmlNode extends RubyObject {
|
|
1572
1465
|
Document prev = otherNode.getOwnerDocument();
|
1573
1466
|
Document doc = thisNode.getOwnerDocument();
|
1574
1467
|
if (doc == null && thisNode instanceof Document) {
|
1575
|
-
|
1576
|
-
|
1468
|
+
// we are adding the new node to a new empty document
|
1469
|
+
doc = (Document) thisNode;
|
1577
1470
|
}
|
1578
1471
|
clearXpathContext(prev);
|
1579
1472
|
clearXpathContext(doc);
|
1580
1473
|
if (doc != null && doc != otherNode.getOwnerDocument()) {
|
1581
1474
|
Node ret = doc.adoptNode(otherNode);
|
1582
|
-
// FIXME: this is really a hack, see documentation of fixUserData() for more details.
|
1583
|
-
fixUserData(prev, ret);
|
1584
1475
|
if (ret == null) {
|
1585
|
-
throw context.
|
1476
|
+
throw context.runtime.newRuntimeError("Failed to take ownership of node");
|
1586
1477
|
}
|
1478
|
+
// FIXME: this is really a hack, see documentation of fixUserData() for more details.
|
1479
|
+
fixUserData(prev, ret);
|
1587
1480
|
otherNode = ret;
|
1588
1481
|
}
|
1589
1482
|
|
@@ -1591,11 +1484,11 @@ public class XmlNode extends RubyObject {
|
|
1591
1484
|
|
1592
1485
|
switch (scheme) {
|
1593
1486
|
case CHILD:
|
1594
|
-
Node[] children = adoptAsChild(
|
1487
|
+
Node[] children = adoptAsChild(thisNode, otherNode);
|
1595
1488
|
if (children.length == 1 && otherNode == children[0]) {
|
1596
1489
|
break;
|
1597
1490
|
} else {
|
1598
|
-
nodeOrTags = nodeArrayToRubyArray(context.
|
1491
|
+
nodeOrTags = nodeArrayToRubyArray(context.runtime, children);
|
1599
1492
|
}
|
1600
1493
|
break;
|
1601
1494
|
case PREV_SIBLING:
|
@@ -1609,7 +1502,7 @@ public class XmlNode extends RubyObject {
|
|
1609
1502
|
break;
|
1610
1503
|
}
|
1611
1504
|
} catch (Exception e) {
|
1612
|
-
throw context.
|
1505
|
+
throw context.runtime.newRuntimeError(e.toString());
|
1613
1506
|
}
|
1614
1507
|
|
1615
1508
|
if (otherNode.getNodeType() == Node.TEXT_NODE) {
|
@@ -1630,42 +1523,38 @@ public class XmlNode extends RubyObject {
|
|
1630
1523
|
* It looks like CoreDocumentImpl.adoptNode() doesn't copy
|
1631
1524
|
* the user data associated with child nodes (recursively).
|
1632
1525
|
*/
|
1633
|
-
private void fixUserData(Document previous, Node ret) {
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1526
|
+
private static void fixUserData(Document previous, Node ret) {
|
1527
|
+
final String key = NokogiriHelpers.ENCODED_STRING;
|
1528
|
+
for (Node child = ret.getFirstChild(); child != null; child = child.getNextSibling()) {
|
1529
|
+
CoreDocumentImpl previousDocument = (CoreDocumentImpl) previous;
|
1530
|
+
child.setUserData(key, previousDocument.getUserData(child, key), null);
|
1531
|
+
fixUserData(previous, child);
|
1532
|
+
}
|
1640
1533
|
}
|
1641
1534
|
|
1642
|
-
|
1643
|
-
Node otherNode) {
|
1535
|
+
private Node[] adoptAsChild(final Node parent, Node otherNode) {
|
1644
1536
|
/*
|
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.
|
1537
|
+
* This is a bit of a hack. C-Nokogiri allows adding a bare text node as the root element.
|
1538
|
+
* Java (and XML spec?) does not. So we wrap the text node in an element.
|
1648
1539
|
*/
|
1649
1540
|
if (parent.getNodeType() == Node.DOCUMENT_NODE && otherNode.getNodeType() == Node.TEXT_NODE) {
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
|
1541
|
+
Element e = (Element) parent.getFirstChild();
|
1542
|
+
if (e == null || !e.getNodeName().equals(TEXT_WRAPPER_NAME)) {
|
1543
|
+
e = ((Document) parent).createElement(TEXT_WRAPPER_NAME);
|
1544
|
+
adoptAsChild(parent, e);
|
1545
|
+
}
|
1546
|
+
e.appendChild(otherNode);
|
1547
|
+
otherNode = e;
|
1657
1548
|
} else {
|
1658
|
-
|
1659
|
-
|
1549
|
+
addNamespaceURIIfNeeded(otherNode);
|
1550
|
+
parent.appendChild(otherNode);
|
1660
1551
|
}
|
1661
|
-
Node[]
|
1662
|
-
nodes[0] = otherNode;
|
1663
|
-
return nodes;
|
1552
|
+
return new Node[] { otherNode };
|
1664
1553
|
}
|
1665
1554
|
|
1666
1555
|
private void addNamespaceURIIfNeeded(Node child) {
|
1667
|
-
if (this instanceof XmlDocumentFragment && ((XmlDocumentFragment)this).getFragmentContext() != null) {
|
1668
|
-
XmlElement fragmentContext = ((XmlDocumentFragment)this).getFragmentContext();
|
1556
|
+
if (this instanceof XmlDocumentFragment && ((XmlDocumentFragment) this).getFragmentContext() != null) {
|
1557
|
+
XmlElement fragmentContext = ((XmlDocumentFragment) this).getFragmentContext();
|
1669
1558
|
String namespace_uri = fragmentContext.node.getNamespaceURI();
|
1670
1559
|
if (namespace_uri != null && namespace_uri.length() > 0) {
|
1671
1560
|
NokogiriHelpers.renameNode(child, namespace_uri, child.getNodeName());
|
@@ -1722,7 +1611,7 @@ public class XmlNode extends RubyObject {
|
|
1722
1611
|
parentNode.replaceChild(otherNode, thisNode);
|
1723
1612
|
} catch (Exception e) {
|
1724
1613
|
String prefix = "could not replace child: ";
|
1725
|
-
throw context.
|
1614
|
+
throw context.runtime.newRuntimeError(prefix + e.toString());
|
1726
1615
|
}
|
1727
1616
|
}
|
1728
1617
|
|
@@ -1784,4 +1673,14 @@ public class XmlNode extends RubyObject {
|
|
1784
1673
|
clearXpathContext(getNode());
|
1785
1674
|
return context.nil ;
|
1786
1675
|
}
|
1676
|
+
|
1677
|
+
@SuppressWarnings("unchecked")
|
1678
|
+
@Override
|
1679
|
+
public Object toJava(final Class target) {
|
1680
|
+
if (target == Object.class || Node.class.isAssignableFrom(target)) {
|
1681
|
+
return getNode();
|
1682
|
+
}
|
1683
|
+
return super.toJava(target);
|
1684
|
+
}
|
1685
|
+
|
1787
1686
|
}
|