nokogiri 1.8.5-java → 1.9.0-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 +5 -5
- data/README.md +0 -1
- data/ext/java/nokogiri/XmlAttr.java +3 -1
- data/ext/java/nokogiri/XmlDtd.java +20 -16
- data/ext/java/nokogiri/XmlElement.java +6 -6
- data/ext/java/nokogiri/XmlNode.java +29 -9
- data/ext/java/nokogiri/XmlNodeSet.java +258 -77
- data/ext/java/nokogiri/XmlXpathContext.java +10 -12
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +25 -23
- data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +5 -5
- data/ext/java/nokogiri/internals/XalanDTMManagerPatch.java +11 -10
- data/ext/java/{org/apache/xml/dtm/ref/dom2dtm/DOM2DTMExt.java → nokogiri/internals/dom2dtm/DOM2DTM.java} +3 -7
- data/ext/java/nokogiri/internals/dom2dtm/DOM2DTMdefaultNamespaceDeclarationNode.java +685 -0
- data/ext/nokogiri/extconf.rb +10 -6
- data/ext/nokogiri/xml_attr.c +26 -21
- data/ext/nokogiri/xml_document.c +4 -1
- data/ext/nokogiri/xml_namespace.c +3 -3
- data/ext/nokogiri/xml_namespace.h +1 -2
- data/ext/nokogiri/xml_node.c +55 -15
- data/lib/nokogiri/css/parser.rb +61 -61
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/lib/nokogiri/version.rb +1 -1
- data/lib/nokogiri/xml/document_fragment.rb +11 -0
- data/lib/nokogiri/xml/node.rb +12 -0
- data/lib/nokogiri/xml/node_set.rb +4 -8
- data/lib/xercesImpl.jar +0 -0
- metadata +17 -152
- data/.autotest +0 -22
- data/.cross_rubies +0 -8
- data/.editorconfig +0 -17
- data/.gemtest +0 -0
- data/.travis.yml +0 -63
- data/CHANGELOG.md +0 -1368
- data/CONTRIBUTING.md +0 -42
- data/C_CODING_STYLE.rdoc +0 -33
- data/Gemfile +0 -23
- data/Gemfile-libxml-ruby +0 -3
- data/Manifest.txt +0 -370
- data/ROADMAP.md +0 -111
- data/Rakefile +0 -348
- data/SECURITY.md +0 -19
- data/STANDARD_RESPONSES.md +0 -47
- data/Y_U_NO_GEMSPEC.md +0 -155
- data/appveyor.yml +0 -29
- data/build_all +0 -44
- data/patches/sort-patches-by-date +0 -25
- data/suppressions/README.txt +0 -1
- data/suppressions/nokogiri_ruby-2.supp +0 -10
- data/tasks/test.rb +0 -100
- data/test/css/test_nthiness.rb +0 -226
- data/test/css/test_parser.rb +0 -386
- data/test/css/test_tokenizer.rb +0 -215
- data/test/css/test_xpath_visitor.rb +0 -96
- data/test/decorators/test_slop.rb +0 -23
- data/test/files/2ch.html +0 -108
- data/test/files/GH_1042.html +0 -18
- data/test/files/address_book.rlx +0 -12
- data/test/files/address_book.xml +0 -10
- data/test/files/atom.xml +0 -344
- data/test/files/bar/bar.xsd +0 -4
- data/test/files/bogus.xml +0 -0
- data/test/files/dont_hurt_em_why.xml +0 -422
- data/test/files/encoding.html +0 -82
- data/test/files/encoding.xhtml +0 -84
- data/test/files/exslt.xml +0 -8
- data/test/files/exslt.xslt +0 -35
- data/test/files/foo/foo.xsd +0 -4
- data/test/files/metacharset.html +0 -10
- data/test/files/namespace_pressure_test.xml +0 -1684
- data/test/files/noencoding.html +0 -47
- data/test/files/po.xml +0 -32
- data/test/files/po.xsd +0 -66
- data/test/files/saml/saml20assertion_schema.xsd +0 -283
- data/test/files/saml/saml20protocol_schema.xsd +0 -302
- data/test/files/saml/xenc_schema.xsd +0 -146
- data/test/files/saml/xmldsig_schema.xsd +0 -318
- data/test/files/shift_jis.html +0 -10
- data/test/files/shift_jis.xml +0 -5
- data/test/files/shift_jis_no_charset.html +0 -9
- data/test/files/slow-xpath.xml +0 -25509
- data/test/files/snuggles.xml +0 -3
- data/test/files/staff.dtd +0 -10
- data/test/files/staff.xml +0 -59
- data/test/files/staff.xslt +0 -32
- data/test/files/test_document_url/bar.xml +0 -2
- data/test/files/test_document_url/document.dtd +0 -4
- data/test/files/test_document_url/document.xml +0 -6
- data/test/files/tlm.html +0 -851
- data/test/files/to_be_xincluded.xml +0 -2
- data/test/files/valid_bar.xml +0 -2
- data/test/files/xinclude.xml +0 -4
- data/test/helper.rb +0 -271
- data/test/html/sax/test_parser.rb +0 -168
- data/test/html/sax/test_parser_context.rb +0 -46
- data/test/html/sax/test_parser_text.rb +0 -163
- data/test/html/sax/test_push_parser.rb +0 -87
- data/test/html/test_attributes.rb +0 -85
- data/test/html/test_builder.rb +0 -164
- data/test/html/test_document.rb +0 -712
- data/test/html/test_document_encoding.rb +0 -143
- data/test/html/test_document_fragment.rb +0 -310
- data/test/html/test_element_description.rb +0 -105
- data/test/html/test_named_characters.rb +0 -14
- data/test/html/test_node.rb +0 -212
- data/test/html/test_node_encoding.rb +0 -91
- data/test/namespaces/test_additional_namespaces_in_builder_doc.rb +0 -14
- data/test/namespaces/test_namespaces_aliased_default.rb +0 -24
- data/test/namespaces/test_namespaces_in_builder_doc.rb +0 -75
- data/test/namespaces/test_namespaces_in_cloned_doc.rb +0 -31
- data/test/namespaces/test_namespaces_in_created_doc.rb +0 -75
- data/test/namespaces/test_namespaces_in_parsed_doc.rb +0 -80
- data/test/namespaces/test_namespaces_preservation.rb +0 -31
- data/test/test_convert_xpath.rb +0 -135
- data/test/test_css_cache.rb +0 -47
- data/test/test_encoding_handler.rb +0 -48
- data/test/test_memory_leak.rb +0 -156
- data/test/test_nokogiri.rb +0 -138
- data/test/test_soap4r_sax.rb +0 -52
- data/test/test_xslt_transforms.rb +0 -314
- data/test/xml/node/test_save_options.rb +0 -28
- data/test/xml/node/test_subclass.rb +0 -44
- data/test/xml/sax/test_parser.rb +0 -402
- data/test/xml/sax/test_parser_context.rb +0 -115
- data/test/xml/sax/test_parser_text.rb +0 -202
- data/test/xml/sax/test_push_parser.rb +0 -265
- data/test/xml/test_attr.rb +0 -74
- data/test/xml/test_attribute_decl.rb +0 -86
- data/test/xml/test_builder.rb +0 -341
- data/test/xml/test_c14n.rb +0 -180
- data/test/xml/test_cdata.rb +0 -54
- data/test/xml/test_comment.rb +0 -40
- data/test/xml/test_document.rb +0 -982
- data/test/xml/test_document_encoding.rb +0 -31
- data/test/xml/test_document_fragment.rb +0 -298
- data/test/xml/test_dtd.rb +0 -187
- data/test/xml/test_dtd_encoding.rb +0 -31
- data/test/xml/test_element_content.rb +0 -56
- data/test/xml/test_element_decl.rb +0 -73
- data/test/xml/test_entity_decl.rb +0 -122
- data/test/xml/test_entity_reference.rb +0 -262
- data/test/xml/test_namespace.rb +0 -96
- data/test/xml/test_node.rb +0 -1325
- data/test/xml/test_node_attributes.rb +0 -115
- data/test/xml/test_node_encoding.rb +0 -75
- data/test/xml/test_node_inheritance.rb +0 -32
- data/test/xml/test_node_reparenting.rb +0 -592
- data/test/xml/test_node_set.rb +0 -809
- data/test/xml/test_parse_options.rb +0 -64
- data/test/xml/test_processing_instruction.rb +0 -30
- data/test/xml/test_reader.rb +0 -620
- data/test/xml/test_reader_encoding.rb +0 -134
- data/test/xml/test_relax_ng.rb +0 -60
- data/test/xml/test_schema.rb +0 -142
- data/test/xml/test_syntax_error.rb +0 -36
- data/test/xml/test_text.rb +0 -60
- data/test/xml/test_unparented_node.rb +0 -483
- data/test/xml/test_xinclude.rb +0 -83
- data/test/xml/test_xpath.rb +0 -470
- data/test/xslt/test_custom_functions.rb +0 -133
- data/test/xslt/test_exception_handling.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 91e6ae003618927051f0376df1b2ebf3eece79ac535a15e874c95ec0850e3bd0
|
4
|
+
data.tar.gz: 2f1f1f47c821664706826c4eb46120ef08e8d7f88561ccc43fbf95df463865c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de19599baccd1ef2be9b9db9076996dd6c301e6467891ba06433a55adbc2aec03a377b100178acce4093e5b950533eba7e6298e55f11346edc817093b7fc4947
|
7
|
+
data.tar.gz: da62dac978f94e9cfab0515090cb1c34c27c1bee796efe4d8a010eacb91bcf30536e9edc49412b4d776e61a390801fcc4c5d5ea81b8e001fd2824718a8af5d9a
|
data/README.md
CHANGED
@@ -18,7 +18,6 @@ or CSS3 selectors.
|
|
18
18
|
|
19
19
|
[![Concourse CI](https://ci.nokogiri.org/api/v1/teams/nokogiri-core/pipelines/nokogiri/jobs/ruby-2.4-system/badge)](https://ci.nokogiri.org/teams/nokogiri-core/pipelines/nokogiri?groups=master)
|
20
20
|
[![Code Climate](https://codeclimate.com/github/sparklemotion/nokogiri.svg)](https://codeclimate.com/github/sparklemotion/nokogiri)
|
21
|
-
[![Version Eye](https://www.versioneye.com/ruby/nokogiri/badge.png)](https://www.versioneye.com/ruby/nokogiri)
|
22
21
|
[![Join the chat at https://gitter.im/sparklemotion/nokogiri](https://badges.gitter.im/sparklemotion/nokogiri.svg)](https://gitter.im/sparklemotion/nokogiri?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
23
22
|
|
24
23
|
|
@@ -130,7 +130,9 @@ public class XmlAttr extends XmlNode {
|
|
130
130
|
@JRubyMethod(name = {"value=", "content="})
|
131
131
|
public IRubyObject value_set(ThreadContext context, IRubyObject content){
|
132
132
|
Attr attr = (Attr) node;
|
133
|
-
|
133
|
+
if (content != null && !content.isNil()) {
|
134
|
+
attr.setValue(rubyStringToString(XmlNode.encode_special_chars(context, content)));
|
135
|
+
}
|
134
136
|
setContent(content);
|
135
137
|
return content;
|
136
138
|
}
|
@@ -35,9 +35,11 @@ package nokogiri;
|
|
35
35
|
import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
|
36
36
|
import static nokogiri.internals.NokogiriHelpers.nonEmptyStringOrNil;
|
37
37
|
import static nokogiri.internals.NokogiriHelpers.stringOrNil;
|
38
|
-
import static org.jruby.
|
39
|
-
|
40
|
-
import
|
38
|
+
import static org.jruby.runtime.Helpers.invoke;
|
39
|
+
|
40
|
+
import java.util.ArrayList;
|
41
|
+
import java.util.Arrays;
|
42
|
+
import java.util.List;
|
41
43
|
|
42
44
|
import org.apache.xerces.xni.QName;
|
43
45
|
import org.cyberneko.dtd.DTDConfiguration;
|
@@ -54,6 +56,9 @@ import org.w3c.dom.DocumentType;
|
|
54
56
|
import org.w3c.dom.Element;
|
55
57
|
import org.w3c.dom.Node;
|
56
58
|
|
59
|
+
import nokogiri.internals.NokogiriHelpers;
|
60
|
+
import nokogiri.internals.SaveContextVisitor;
|
61
|
+
|
57
62
|
/**
|
58
63
|
* Class for Nokogiri::XML::DTD
|
59
64
|
*
|
@@ -64,8 +69,6 @@ import org.w3c.dom.Node;
|
|
64
69
|
|
65
70
|
@JRubyClass(name="Nokogiri::XML::DTD", parent="Nokogiri::XML::Node")
|
66
71
|
public class XmlDtd extends XmlNode {
|
67
|
-
protected RubyArray allDecls = null;
|
68
|
-
|
69
72
|
/** cache of children, Nokogiri::XML::NodeSet */
|
70
73
|
protected IRubyObject children = null;
|
71
74
|
|
@@ -369,7 +372,6 @@ public class XmlDtd extends XmlNode {
|
|
369
372
|
Ruby runtime = context.getRuntime();
|
370
373
|
|
371
374
|
// initialize data structures
|
372
|
-
allDecls = RubyArray.newArray(runtime);
|
373
375
|
attributes = RubyHash.newHash(runtime);
|
374
376
|
elements = RubyHash.newHash(runtime);
|
375
377
|
entities = RubyHash.newHash(runtime);
|
@@ -379,10 +381,9 @@ public class XmlDtd extends XmlNode {
|
|
379
381
|
|
380
382
|
// recursively extract decls
|
381
383
|
if (node == null) return; // leave all the decl hash's empty
|
382
|
-
extractDecls(context, node.getFirstChild());
|
383
384
|
|
384
385
|
// convert allDecls to a NodeSet
|
385
|
-
children = XmlNodeSet.newXmlNodeSet(context,
|
386
|
+
children = XmlNodeSet.newXmlNodeSet(context, extractDecls(context, node.getFirstChild()));
|
386
387
|
|
387
388
|
// add attribute decls as attributes to the matching element decl
|
388
389
|
RubyArray keys = attributes.keys();
|
@@ -425,25 +426,26 @@ public class XmlDtd extends XmlNode {
|
|
425
426
|
* subset it extracts everything and assumess <code>node</code>
|
426
427
|
* and all children are part of the external subset.
|
427
428
|
*/
|
428
|
-
protected
|
429
|
+
protected IRubyObject[] extractDecls(ThreadContext context, Node node) {
|
430
|
+
List<IRubyObject> decls = new ArrayList<IRubyObject>();
|
429
431
|
while (node != null) {
|
430
432
|
if (isExternalSubset(node)) {
|
431
|
-
|
433
|
+
break;
|
432
434
|
} else if (isAttributeDecl(node)) {
|
433
435
|
XmlAttributeDecl decl = (XmlAttributeDecl)
|
434
436
|
XmlAttributeDecl.create(context, node);
|
435
437
|
attributes.op_aset(context, decl.attribute_name(context), decl);
|
436
|
-
|
438
|
+
decls.add(decl);
|
437
439
|
} else if (isElementDecl(node)) {
|
438
440
|
XmlElementDecl decl = (XmlElementDecl)
|
439
441
|
XmlElementDecl.create(context, node);
|
440
442
|
elements.op_aset(context, decl.element_name(context), decl);
|
441
|
-
|
443
|
+
decls.add(decl);
|
442
444
|
} else if (isEntityDecl(node)) {
|
443
445
|
XmlEntityDecl decl = (XmlEntityDecl)
|
444
446
|
XmlEntityDecl.create(context, node);
|
445
447
|
entities.op_aset(context, decl.node_name(context), decl);
|
446
|
-
|
448
|
+
decls.add(decl);
|
447
449
|
} else if (isNotationDecl(node)) {
|
448
450
|
XmlNode tmp = (XmlNode)
|
449
451
|
NokogiriHelpers.constructNode(context.getRuntime(), node);
|
@@ -453,7 +455,7 @@ public class XmlDtd extends XmlNode {
|
|
453
455
|
tmp.getAttribute(context, "sysid"));
|
454
456
|
notations.op_aset(context,
|
455
457
|
tmp.getAttribute(context, "name"), decl);
|
456
|
-
|
458
|
+
decls.add(decl);
|
457
459
|
} else if (isContentModel(node)) {
|
458
460
|
XmlElementContent cm =
|
459
461
|
new XmlElementContent(context.getRuntime(),
|
@@ -462,13 +464,15 @@ public class XmlDtd extends XmlNode {
|
|
462
464
|
contentModels.op_aset(context, cm.element_name(context), cm);
|
463
465
|
} else {
|
464
466
|
// recurse
|
465
|
-
extractDecls(context, node.getFirstChild());
|
467
|
+
decls.addAll(Arrays.asList(extractDecls(context, node.getFirstChild())));
|
466
468
|
}
|
467
469
|
|
468
470
|
node = node.getNextSibling();
|
469
471
|
}
|
472
|
+
|
473
|
+
return decls.toArray(new IRubyObject[decls.size()]);
|
470
474
|
}
|
471
|
-
|
475
|
+
|
472
476
|
@Override
|
473
477
|
public void accept(ThreadContext context, SaveContextVisitor visitor) {
|
474
478
|
// since we use nekoDTD to parse dtd, node might be ElementImpl type
|
@@ -32,16 +32,16 @@
|
|
32
32
|
|
33
33
|
package nokogiri;
|
34
34
|
|
35
|
-
import nokogiri.internals.SaveContextVisitor;
|
36
|
-
|
37
35
|
import org.jruby.Ruby;
|
38
|
-
import org.jruby.RubyArray;
|
39
36
|
import org.jruby.RubyClass;
|
40
37
|
import org.jruby.anno.JRubyClass;
|
41
38
|
import org.jruby.runtime.ThreadContext;
|
39
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
42
40
|
import org.w3c.dom.Element;
|
43
41
|
import org.w3c.dom.Node;
|
44
42
|
|
43
|
+
import nokogiri.internals.SaveContextVisitor;
|
44
|
+
|
45
45
|
/**
|
46
46
|
* Class for Nokogiri::XML::Element
|
47
47
|
*
|
@@ -71,9 +71,9 @@ public class XmlElement extends XmlNode {
|
|
71
71
|
visitor.enter((Element) node);
|
72
72
|
XmlNodeSet xmlNodeSet = (XmlNodeSet) children(context);
|
73
73
|
if (xmlNodeSet.length() > 0) {
|
74
|
-
|
75
|
-
for( int i = 0; i < nodes.
|
76
|
-
Object item = nodes
|
74
|
+
IRubyObject[] nodes = XmlNodeSet.getNodes(context, xmlNodeSet);
|
75
|
+
for( int i = 0; i < nodes.length; i++ ) {
|
76
|
+
Object item = nodes[i];
|
77
77
|
if (item instanceof XmlNode) {
|
78
78
|
((XmlNode) item).accept(context, visitor);
|
79
79
|
}
|
@@ -472,10 +472,31 @@ public class XmlNode extends RubyObject {
|
|
472
472
|
String nsURI = e.lookupNamespaceURI(prefix);
|
473
473
|
this.node = NokogiriHelpers.renameNode(e, nsURI, e.getNodeName());
|
474
474
|
|
475
|
-
if (nsURI == null || nsURI
|
475
|
+
if (nsURI == null || nsURI == "") {
|
476
476
|
return;
|
477
477
|
}
|
478
478
|
|
479
|
+
String currentPrefix = e.getParentNode().lookupPrefix(nsURI);
|
480
|
+
String currentURI = e.getParentNode().lookupNamespaceURI(prefix);
|
481
|
+
boolean isDefault = e.getParentNode().isDefaultNamespace(nsURI);
|
482
|
+
|
483
|
+
// add xmlns attribute if this is a new root node or if the node's
|
484
|
+
// namespace isn't a default namespace in the new document
|
485
|
+
if (e.getParentNode().getNodeType() == Node.DOCUMENT_NODE) {
|
486
|
+
// this is the root node, so we must set the namespaces attributes
|
487
|
+
// anyway
|
488
|
+
e.setAttribute(prefix == null ? "xmlns":"xmlns:"+prefix, nsURI);
|
489
|
+
} else if (prefix == null) {
|
490
|
+
if (!isDefault)
|
491
|
+
// this is a default namespace but isn't the default where this
|
492
|
+
// node is being added
|
493
|
+
e.setAttribute("xmlns", nsURI);
|
494
|
+
} else if (currentPrefix != prefix || currentURI != nsURI) {
|
495
|
+
// this is a prefixed namespace but doens't have the same prefix or
|
496
|
+
// the prefix is set to a diffent URI
|
497
|
+
e.setAttribute("xmlns:"+prefix, nsURI);
|
498
|
+
}
|
499
|
+
|
479
500
|
if (e.hasAttributes()) {
|
480
501
|
NamedNodeMap attrs = e.getAttributes();
|
481
502
|
|
@@ -704,7 +725,7 @@ public class XmlNode extends RubyObject {
|
|
704
725
|
|
705
726
|
@JRubyMethod
|
706
727
|
public IRubyObject children(ThreadContext context) {
|
707
|
-
XmlNodeSet xmlNodeSet = XmlNodeSet.
|
728
|
+
XmlNodeSet xmlNodeSet = XmlNodeSet.newEmptyNodeSet(context);
|
708
729
|
|
709
730
|
NodeList nodeList = node.getChildNodes();
|
710
731
|
if (nodeList.getLength() > 0) {
|
@@ -737,8 +758,8 @@ public class XmlNode extends RubyObject {
|
|
737
758
|
public IRubyObject element_children(ThreadContext context) {
|
738
759
|
List<Node> elementNodes = new ArrayList<Node>();
|
739
760
|
addElements(node, elementNodes, false);
|
740
|
-
|
741
|
-
|
761
|
+
IRubyObject[] array = NokogiriHelpers.nodeArrayToArray(context.runtime,
|
762
|
+
elementNodes.toArray(new Node[0]));
|
742
763
|
XmlNodeSet xmlNodeSet = XmlNodeSet.newXmlNodeSet(context, array);
|
743
764
|
return xmlNodeSet;
|
744
765
|
}
|
@@ -839,10 +860,10 @@ public class XmlNode extends RubyObject {
|
|
839
860
|
RubyArray docErrors = getErrorArray(doc);
|
840
861
|
if (isErrorIncreased(documentErrors, docErrors)) {
|
841
862
|
for (int i = 0; i < docErrors.getLength(); i++) {
|
842
|
-
documentErrors.add(docErrors.
|
863
|
+
documentErrors.add(docErrors.entry(i));
|
843
864
|
}
|
844
865
|
document.setInstanceVariable("@errors", documentErrors);
|
845
|
-
XmlNodeSet xmlNodeSet = XmlNodeSet.newXmlNodeSet(context,
|
866
|
+
XmlNodeSet xmlNodeSet = XmlNodeSet.newXmlNodeSet(context, new IRubyObject[0]);
|
846
867
|
return xmlNodeSet;
|
847
868
|
}
|
848
869
|
|
@@ -854,10 +875,9 @@ public class XmlNode extends RubyObject {
|
|
854
875
|
} else {
|
855
876
|
first = doc.node.getFirstChild();
|
856
877
|
}
|
857
|
-
RubyArray nodeArray = RubyArray.newArray(runtime);
|
858
|
-
nodeArray.add(NokogiriHelpers.getCachedNodeOrCreate(runtime, first));
|
859
878
|
|
860
|
-
|
879
|
+
IRubyObject[] nodes = new IRubyObject[]{NokogiriHelpers.getCachedNodeOrCreate(runtime, first)};
|
880
|
+
XmlNodeSet xmlNodeSet = XmlNodeSet.newXmlNodeSet(context, nodes);
|
861
881
|
return xmlNodeSet;
|
862
882
|
}
|
863
883
|
|
@@ -17,10 +17,10 @@
|
|
17
17
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
18
18
|
* permit persons to whom the Software is furnished to do so, subject to
|
19
19
|
* the following conditions:
|
20
|
-
*
|
20
|
+
*
|
21
21
|
* The above copyright notice and this permission notice shall be
|
22
22
|
* included in all copies or substantial portions of the Software.
|
23
|
-
*
|
23
|
+
*
|
24
24
|
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
25
25
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
26
26
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
@@ -36,12 +36,13 @@ import static nokogiri.XmlNode.setDocumentAndDecorate;
|
|
36
36
|
import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
|
37
37
|
import static nokogiri.internals.NokogiriHelpers.nodeListToRubyArray;
|
38
38
|
|
39
|
-
import java.util.
|
39
|
+
import java.util.Arrays;
|
40
40
|
|
41
41
|
import org.jruby.Ruby;
|
42
|
-
import org.jruby.RubyArray;
|
43
42
|
import org.jruby.RubyClass;
|
43
|
+
import org.jruby.RubyFixnum;
|
44
44
|
import org.jruby.RubyObject;
|
45
|
+
import org.jruby.RubyRange;
|
45
46
|
import org.jruby.anno.JRubyClass;
|
46
47
|
import org.jruby.anno.JRubyMethod;
|
47
48
|
import org.jruby.runtime.Block;
|
@@ -59,30 +60,38 @@ import org.w3c.dom.NodeList;
|
|
59
60
|
@JRubyClass(name="Nokogiri::XML::NodeSet")
|
60
61
|
public class XmlNodeSet extends RubyObject implements NodeList {
|
61
62
|
|
62
|
-
|
63
|
-
|
63
|
+
private IRubyObject[] nodes;
|
64
|
+
|
65
|
+
@JRubyMethod(name = "new", meta = true, rest = true)
|
66
|
+
public static IRubyObject rbNew(ThreadContext context, IRubyObject cls,
|
67
|
+
IRubyObject[] args, Block block) {
|
68
|
+
RubyClass klass = (RubyClass) cls;
|
69
|
+
XmlNodeSet set = (XmlNodeSet) klass.allocate();
|
70
|
+
set.setNodes(new IRubyObject[0]);
|
71
|
+
set.callInit(args, block);
|
72
|
+
return set;
|
73
|
+
}
|
74
|
+
|
64
75
|
public XmlNodeSet(Ruby ruby, RubyClass klazz) {
|
65
76
|
super(ruby, klazz);
|
66
77
|
}
|
67
78
|
|
68
|
-
|
79
|
+
private static XmlNodeSet create(final Ruby runtime) {
|
69
80
|
return (XmlNodeSet) NokogiriService.XML_NODESET_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime, "Nokogiri::XML::NodeSet"));
|
70
81
|
}
|
71
82
|
|
72
83
|
public static XmlNodeSet newEmptyNodeSet(ThreadContext context) {
|
73
|
-
|
84
|
+
XmlNodeSet set = create(context.getRuntime());
|
85
|
+
set.nodes = new IRubyObject[0];
|
86
|
+
return set;
|
74
87
|
}
|
75
88
|
|
76
|
-
public static XmlNodeSet newXmlNodeSet(
|
77
|
-
XmlNodeSet xmlNodeSet = create(runtime);
|
89
|
+
public static XmlNodeSet newXmlNodeSet(ThreadContext context, IRubyObject[] nodes) {
|
90
|
+
XmlNodeSet xmlNodeSet = create(context.runtime);
|
78
91
|
xmlNodeSet.setNodes(nodes);
|
79
92
|
return xmlNodeSet;
|
80
93
|
}
|
81
94
|
|
82
|
-
static XmlNodeSet newXmlNodeSet(ThreadContext context, RubyArray nodes) {
|
83
|
-
return newXmlNodeSet(context.getRuntime(), nodes);
|
84
|
-
}
|
85
|
-
|
86
95
|
/**
|
87
96
|
* Create and return a copy of this object.
|
88
97
|
*
|
@@ -93,19 +102,18 @@ public class XmlNodeSet extends RubyObject implements NodeList {
|
|
93
102
|
return super.clone();
|
94
103
|
}
|
95
104
|
|
96
|
-
void setNodes(
|
105
|
+
void setNodes(IRubyObject[] array) {
|
97
106
|
this.nodes = array;
|
98
107
|
|
99
|
-
IRubyObject first = array.
|
100
|
-
initialize(
|
108
|
+
IRubyObject first = array.length > 0 ? array[0] : null;
|
109
|
+
initialize(getRuntime(), first);
|
101
110
|
}
|
102
111
|
|
103
112
|
private void setReference(XmlNodeSet reference) {
|
104
|
-
|
105
|
-
|
106
|
-
initialize(reference.getRuntime(), first);
|
113
|
+
IRubyObject first = reference.nodes.length > 0 ? reference.nodes[0] : null;
|
114
|
+
initialize(getRuntime(), first);
|
107
115
|
}
|
108
|
-
|
116
|
+
|
109
117
|
public void setNodeList(NodeList nodeList) {
|
110
118
|
setNodes(nodeListToRubyArray(getRuntime(), nodeList));
|
111
119
|
}
|
@@ -118,106 +126,280 @@ public class XmlNodeSet extends RubyObject implements NodeList {
|
|
118
126
|
}
|
119
127
|
|
120
128
|
public int length() {
|
121
|
-
|
122
|
-
return nodes.size();
|
129
|
+
return nodes == null ? 0 : nodes.length;
|
123
130
|
}
|
124
131
|
|
125
132
|
public void relink_namespace(ThreadContext context) {
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
if (n.get(i) instanceof XmlNode) {
|
130
|
-
((XmlNode) n.get(i)).relink_namespace(context);
|
133
|
+
for (int i = 0; i < nodes.length; i++) {
|
134
|
+
if (nodes[i] instanceof XmlNode) {
|
135
|
+
((XmlNode) nodes[i]).relink_namespace(context);
|
131
136
|
}
|
132
137
|
}
|
133
138
|
}
|
134
139
|
|
135
140
|
@JRubyMethod(name="&")
|
136
|
-
public IRubyObject
|
137
|
-
|
138
|
-
|
141
|
+
public IRubyObject op_and(ThreadContext context, IRubyObject nodeSet) {
|
142
|
+
IRubyObject[] otherNodes = getNodes(context, nodeSet);
|
143
|
+
|
144
|
+
if (otherNodes == null || otherNodes.length == 0) {
|
145
|
+
return newEmptyNodeSet(context);
|
146
|
+
}
|
147
|
+
|
148
|
+
if (nodes == null || nodes.length == 0) {
|
149
|
+
return newEmptyNodeSet(context);
|
150
|
+
}
|
151
|
+
|
152
|
+
IRubyObject[] curr = nodes;
|
153
|
+
IRubyObject[] other = getNodes(context, nodeSet);
|
154
|
+
IRubyObject[] result = new IRubyObject[nodes.length];
|
155
|
+
|
156
|
+
int last = 0;
|
157
|
+
outer:
|
158
|
+
for (int i = 0; i < curr.length; i++) {
|
159
|
+
IRubyObject n = curr[i];
|
160
|
+
|
161
|
+
for (int j = 0; j < other.length; j++) {
|
162
|
+
if (other[j] == n) {
|
163
|
+
result[last++] = n;
|
164
|
+
continue outer;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
XmlNodeSet newSet = newXmlNodeSet(context, Arrays.copyOf(result, last));
|
170
|
+
newSet.setReference(this);
|
171
|
+
return newSet;
|
139
172
|
}
|
140
173
|
|
141
174
|
@JRubyMethod
|
142
175
|
public IRubyObject delete(ThreadContext context, IRubyObject node_or_namespace) {
|
143
|
-
|
144
|
-
|
145
|
-
|
176
|
+
IRubyObject nodeOrNamespace = asXmlNodeOrNamespace(context, node_or_namespace);
|
177
|
+
|
178
|
+
if (nodes.length == 0) {
|
179
|
+
return context.nil;
|
180
|
+
}
|
181
|
+
|
182
|
+
IRubyObject[] orig = nodes;
|
183
|
+
IRubyObject[] result = new IRubyObject[nodes.length];
|
184
|
+
|
185
|
+
int last = 0;
|
186
|
+
|
187
|
+
for (int i = 0; i < orig.length; i++) {
|
188
|
+
IRubyObject n = orig[i];
|
189
|
+
|
190
|
+
if (n == nodeOrNamespace) {
|
191
|
+
continue;
|
192
|
+
}
|
193
|
+
|
194
|
+
result[last++] = n;
|
146
195
|
}
|
147
|
-
|
196
|
+
|
197
|
+
if (nodeOrNamespace instanceof XmlNamespace) {
|
198
|
+
((XmlNamespace) nodeOrNamespace).deleteHref();
|
199
|
+
}
|
200
|
+
|
201
|
+
nodes = Arrays.copyOf(result, last);
|
202
|
+
|
203
|
+
if (nodes.length < orig.length) {
|
204
|
+
// if we found the node return it
|
205
|
+
return nodeOrNamespace;
|
206
|
+
}
|
207
|
+
|
208
|
+
return context.nil;
|
148
209
|
}
|
149
210
|
|
150
211
|
@JRubyMethod
|
151
|
-
public IRubyObject dup(ThreadContext context){
|
152
|
-
|
153
|
-
return newXmlNodeSet(context, nodes.aryDup());
|
212
|
+
public IRubyObject dup(ThreadContext context) {
|
213
|
+
return newXmlNodeSet(context, nodes);
|
154
214
|
}
|
155
215
|
|
156
216
|
@JRubyMethod(name = "include?")
|
157
217
|
public IRubyObject include_p(ThreadContext context, IRubyObject node_or_namespace) {
|
158
|
-
|
159
|
-
|
160
|
-
|
218
|
+
for (int i = 0; i < nodes.length; i++) {
|
219
|
+
if (nodes[i] == node_or_namespace) {
|
220
|
+
return context.tru;
|
221
|
+
}
|
222
|
+
}
|
223
|
+
|
224
|
+
return context.runtime.getFalse();
|
161
225
|
}
|
162
226
|
|
163
227
|
@JRubyMethod(name = {"length", "size"})
|
164
228
|
public IRubyObject length(ThreadContext context) {
|
165
|
-
return
|
229
|
+
return context.getRuntime().newFixnum(nodes.length);
|
166
230
|
}
|
167
231
|
|
168
232
|
@JRubyMethod(name="-")
|
169
233
|
public IRubyObject op_diff(ThreadContext context, IRubyObject nodeSet) {
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
234
|
+
IRubyObject[] otherNodes = getNodes(context, nodeSet);
|
235
|
+
|
236
|
+
if (otherNodes.length == 0) {
|
237
|
+
return dup(context);
|
238
|
+
}
|
239
|
+
|
240
|
+
if (nodes.length == 0) {
|
241
|
+
return newEmptyNodeSet(context);
|
242
|
+
}
|
243
|
+
|
244
|
+
IRubyObject[] curr = nodes;
|
245
|
+
IRubyObject[] other = getNodes(context, nodeSet);
|
246
|
+
IRubyObject[] result = new IRubyObject[nodes.length];
|
247
|
+
|
248
|
+
int last = 0;
|
249
|
+
outer:
|
250
|
+
for (int i = 0; i < curr.length; i++) {
|
251
|
+
IRubyObject n = curr[i];
|
252
|
+
|
253
|
+
for (int j = 0; j < other.length; j++) {
|
254
|
+
if (other[j] == n) {
|
255
|
+
continue outer;
|
256
|
+
}
|
257
|
+
}
|
258
|
+
|
259
|
+
result[last++] = n;
|
260
|
+
}
|
261
|
+
|
262
|
+
XmlNodeSet newSet = newXmlNodeSet(context, Arrays.copyOf(result, last));
|
263
|
+
newSet.setReference(this);
|
264
|
+
return newSet;
|
174
265
|
}
|
175
266
|
|
176
267
|
@JRubyMethod(name={"|", "+"})
|
177
268
|
public IRubyObject op_or(ThreadContext context, IRubyObject nodeSet) {
|
178
|
-
|
179
|
-
|
269
|
+
IRubyObject[] otherNodes = getNodes(context, nodeSet);
|
270
|
+
|
271
|
+
if (nodes.length == 0) {
|
272
|
+
return ((XmlNodeSet) nodeSet).dup(context);
|
273
|
+
}
|
274
|
+
|
275
|
+
if (otherNodes.length == 0) {
|
276
|
+
return dup(context);
|
277
|
+
}
|
278
|
+
|
279
|
+
IRubyObject[] curr = nodes;
|
280
|
+
IRubyObject[] other = getNodes(context, nodeSet);
|
281
|
+
IRubyObject[] result = Arrays.copyOf(curr, curr.length + other.length);
|
282
|
+
|
283
|
+
int last = curr.length;
|
284
|
+
outer:
|
285
|
+
for (int i = 0; i < other.length; i++) {
|
286
|
+
IRubyObject n = other[i];
|
287
|
+
|
288
|
+
for (int j = 0; j < curr.length; j++) {
|
289
|
+
if (curr[j] == n) {
|
290
|
+
continue outer;
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
294
|
+
result[last++] = n;
|
295
|
+
}
|
296
|
+
|
297
|
+
XmlNodeSet newSet = newXmlNodeSet(context, Arrays.copyOf(result, last));
|
298
|
+
newSet.setReference(this);
|
299
|
+
return newSet;
|
180
300
|
}
|
181
301
|
|
182
302
|
@JRubyMethod(name = {"push", "<<"})
|
183
303
|
public IRubyObject push(ThreadContext context, IRubyObject node_or_namespace) {
|
184
|
-
|
185
|
-
nodes.
|
304
|
+
nodes = Arrays.copyOf(nodes, nodes.length+1);
|
305
|
+
nodes[nodes.length-1] = node_or_namespace;
|
186
306
|
return this;
|
187
307
|
}
|
188
308
|
|
309
|
+
// replace with
|
310
|
+
// https://github.com/jruby/jruby/blame/13a3ec76d883a162b9d46c374c6e9eeea27b3261/core/src/main/java/org/jruby/RubyRange.java#L974
|
311
|
+
// once we upgraded the min JRuby version to >= 9.2
|
312
|
+
private static IRubyObject rangeBeginLength(ThreadContext context, IRubyObject rangeMaybe, int len, int[] begLen) {
|
313
|
+
RubyRange range = (RubyRange) rangeMaybe;
|
314
|
+
int min = range.begin(context).convertToInteger().getIntValue();
|
315
|
+
int max = range.end(context).convertToInteger().getIntValue();
|
316
|
+
|
317
|
+
if (min < 0) {
|
318
|
+
min += len;
|
319
|
+
if (min < 0) {
|
320
|
+
throw context.runtime.newRangeError(min + ".." + (range.isExcludeEnd() ? "." : "") + max + " out of range");
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
if (max < 0) {
|
325
|
+
max += len;
|
326
|
+
}
|
327
|
+
|
328
|
+
if (!range.isExcludeEnd()) {
|
329
|
+
max++;
|
330
|
+
}
|
331
|
+
|
332
|
+
begLen[0] = min;
|
333
|
+
begLen[1] = max;
|
334
|
+
return context.tru;
|
335
|
+
}
|
336
|
+
|
337
|
+
|
189
338
|
@JRubyMethod(name={"[]", "slice"})
|
190
|
-
public IRubyObject slice(ThreadContext context, IRubyObject indexOrRange){
|
191
|
-
if (
|
192
|
-
|
193
|
-
|
194
|
-
|
339
|
+
public IRubyObject slice(ThreadContext context, IRubyObject indexOrRange) {
|
340
|
+
if (indexOrRange instanceof RubyFixnum) {
|
341
|
+
int idx = ((RubyFixnum)indexOrRange).getIntValue();
|
342
|
+
|
343
|
+
if (idx < 0) {
|
344
|
+
idx += nodes.length;
|
345
|
+
}
|
346
|
+
|
347
|
+
if (idx >= nodes.length || idx < 0) {
|
348
|
+
return context.nil;
|
349
|
+
}
|
350
|
+
|
351
|
+
return nodes[idx];
|
195
352
|
}
|
196
|
-
|
353
|
+
|
354
|
+
int[] begLen = new int[2];
|
355
|
+
rangeBeginLength(context, indexOrRange, nodes.length, begLen);
|
356
|
+
int min = begLen[0];
|
357
|
+
int max = begLen[1];
|
358
|
+
return subseq(context, min, max - min);
|
197
359
|
}
|
198
360
|
|
199
361
|
@JRubyMethod(name={"[]", "slice"})
|
200
|
-
public IRubyObject slice(ThreadContext context, IRubyObject start, IRubyObject length){
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
362
|
+
public IRubyObject slice(ThreadContext context, IRubyObject start, IRubyObject length) {
|
363
|
+
int s = ((RubyFixnum) start).getIntValue();
|
364
|
+
int l = ((RubyFixnum) length).getIntValue();
|
365
|
+
|
366
|
+
if (s < 0) {
|
367
|
+
s += nodes.length;
|
205
368
|
}
|
206
|
-
|
369
|
+
|
370
|
+
return subseq(context, s, l);
|
371
|
+
}
|
372
|
+
|
373
|
+
public IRubyObject subseq(ThreadContext context, int start, int length) {
|
374
|
+
if (start > nodes.length) {
|
375
|
+
return context.nil;
|
376
|
+
}
|
377
|
+
|
378
|
+
if (start < 0 || length < 0) {
|
379
|
+
return context.nil;
|
380
|
+
}
|
381
|
+
|
382
|
+
if (start + length > nodes.length) {
|
383
|
+
length = nodes.length - start;
|
384
|
+
}
|
385
|
+
|
386
|
+
int to = start + length;
|
387
|
+
|
388
|
+
IRubyObject[] newNodes = Arrays.copyOfRange(nodes, start, to);
|
389
|
+
|
390
|
+
return newXmlNodeSet(context, newNodes);
|
207
391
|
}
|
208
392
|
|
209
393
|
@JRubyMethod(name = {"to_a", "to_ary"})
|
210
394
|
public IRubyObject to_a(ThreadContext context) {
|
211
|
-
return nodes;
|
395
|
+
return context.runtime.newArrayNoCopy(nodes);
|
212
396
|
}
|
213
397
|
|
214
398
|
@JRubyMethod(name = {"unlink", "remove"})
|
215
|
-
public IRubyObject unlink(ThreadContext context){
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
if (arr[i] instanceof XmlNode) {
|
220
|
-
((XmlNode) arr[i] ).unlink(context);
|
399
|
+
public IRubyObject unlink(ThreadContext context) {
|
400
|
+
for (int i = 0; i < nodes.length; i++) {
|
401
|
+
if (nodes[i] instanceof XmlNode) {
|
402
|
+
((XmlNode) nodes[i] ).unlink(context);
|
221
403
|
}
|
222
404
|
}
|
223
405
|
return this;
|
@@ -226,6 +408,7 @@ public class XmlNodeSet extends RubyObject implements NodeList {
|
|
226
408
|
private static XmlNodeSet newXmlNodeSet(ThreadContext context, XmlNodeSet reference) {
|
227
409
|
XmlNodeSet xmlNodeSet = create(context.getRuntime());
|
228
410
|
xmlNodeSet.setReference(reference);
|
411
|
+
xmlNodeSet.nodes = new IRubyObject[0];
|
229
412
|
return xmlNodeSet;
|
230
413
|
}
|
231
414
|
|
@@ -236,21 +419,19 @@ public class XmlNodeSet extends RubyObject implements NodeList {
|
|
236
419
|
throw context.getRuntime().newArgumentError("node must be a Nokogiri::XML::Node or Nokogiri::XML::Namespace");
|
237
420
|
}
|
238
421
|
|
239
|
-
|
422
|
+
static IRubyObject[] getNodes(ThreadContext context, IRubyObject possibleNodeSet) {
|
240
423
|
if (possibleNodeSet instanceof XmlNodeSet) {
|
241
|
-
|
242
|
-
return nodes == null ? RubyArray.newEmptyArray(context.getRuntime()) : nodes;
|
424
|
+
return ((XmlNodeSet) possibleNodeSet).nodes;
|
243
425
|
}
|
244
426
|
throw context.getRuntime().newArgumentError("node must be a Nokogiri::XML::NodeSet");
|
245
427
|
}
|
246
|
-
|
428
|
+
|
247
429
|
public int getLength() {
|
248
|
-
return nodes
|
430
|
+
return nodes.length;
|
249
431
|
}
|
250
|
-
|
432
|
+
|
251
433
|
public Node item(int index) {
|
252
|
-
|
253
|
-
Object n = nodes.get(index);
|
434
|
+
Object n = nodes[index];
|
254
435
|
if (n instanceof XmlNode) return ((XmlNode)n).node;
|
255
436
|
if (n instanceof XmlNamespace) return ((XmlNamespace)n).getNode();
|
256
437
|
return null;
|