nokogiri 1.10.10-java → 1.11.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 +4 -4
- data/Gemfile +3 -0
- data/LICENSE-DEPENDENCIES.md +1015 -947
- data/README.md +165 -91
- data/ext/java/nokogiri/HtmlDocument.java +34 -46
- data/ext/java/nokogiri/HtmlSaxParserContext.java +88 -58
- data/ext/java/nokogiri/HtmlSaxPushParser.java +1 -1
- data/ext/java/nokogiri/NokogiriService.java +1 -1
- data/ext/java/nokogiri/XmlAttr.java +13 -20
- data/ext/java/nokogiri/XmlAttributeDecl.java +11 -12
- data/ext/java/nokogiri/XmlCdata.java +3 -4
- data/ext/java/nokogiri/XmlComment.java +1 -1
- data/ext/java/nokogiri/XmlDocument.java +148 -175
- data/ext/java/nokogiri/XmlDocumentFragment.java +13 -31
- data/ext/java/nokogiri/XmlDtd.java +5 -8
- data/ext/java/nokogiri/XmlElement.java +1 -20
- data/ext/java/nokogiri/XmlElementDecl.java +23 -28
- data/ext/java/nokogiri/XmlEntityDecl.java +23 -27
- data/ext/java/nokogiri/XmlEntityReference.java +2 -2
- data/ext/java/nokogiri/XmlNamespace.java +72 -89
- data/ext/java/nokogiri/XmlNode.java +303 -406
- data/ext/java/nokogiri/XmlNodeSet.java +70 -76
- data/ext/java/nokogiri/XmlReader.java +12 -13
- data/ext/java/nokogiri/XmlRelaxng.java +10 -3
- data/ext/java/nokogiri/XmlSaxParserContext.java +15 -10
- data/ext/java/nokogiri/XmlSchema.java +87 -27
- data/ext/java/nokogiri/XmlSyntaxError.java +2 -6
- data/ext/java/nokogiri/XmlText.java +12 -9
- data/ext/java/nokogiri/XmlXpathContext.java +55 -25
- data/ext/java/nokogiri/XsltStylesheet.java +7 -15
- data/ext/java/nokogiri/internals/HtmlDomParserContext.java +52 -46
- data/ext/java/nokogiri/internals/NokogiriHandler.java +1 -1
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +71 -135
- data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +90 -58
- data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +9 -2
- data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +67 -10
- data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +4 -2
- data/ext/java/nokogiri/internals/ParserContext.java +27 -73
- data/ext/java/nokogiri/internals/ReaderNode.java +2 -4
- data/ext/java/nokogiri/internals/XmlDomParserContext.java +18 -33
- data/ext/nokogiri/depend +476 -357
- data/ext/nokogiri/extconf.rb +507 -357
- data/ext/nokogiri/html_document.c +79 -78
- data/ext/nokogiri/html_sax_parser_context.c +2 -2
- data/ext/nokogiri/nokogiri.c +34 -40
- data/ext/nokogiri/xml_document.c +18 -4
- data/ext/nokogiri/xml_io.c +8 -6
- data/ext/nokogiri/xml_node.c +21 -1
- data/ext/nokogiri/xml_node_set.c +1 -1
- data/ext/nokogiri/xml_reader.c +6 -17
- data/ext/nokogiri/xml_relax_ng.c +29 -11
- data/ext/nokogiri/xml_sax_parser.c +2 -7
- data/ext/nokogiri/xml_sax_parser_context.c +2 -2
- data/ext/nokogiri/xml_schema.c +55 -13
- data/ext/nokogiri/xml_xpath_context.c +80 -4
- data/ext/nokogiri/xslt_stylesheet.c +1 -8
- data/lib/nokogiri.rb +22 -22
- data/lib/nokogiri/css.rb +1 -0
- data/lib/nokogiri/css/node.rb +1 -0
- data/lib/nokogiri/css/parser.rb +63 -62
- data/lib/nokogiri/css/parser.y +2 -2
- data/lib/nokogiri/css/parser_extras.rb +39 -36
- data/lib/nokogiri/css/syntax_error.rb +1 -0
- data/lib/nokogiri/css/tokenizer.rb +1 -0
- data/lib/nokogiri/css/xpath_visitor.rb +73 -43
- data/lib/nokogiri/decorators/slop.rb +1 -0
- data/lib/nokogiri/html.rb +1 -0
- data/lib/nokogiri/html/builder.rb +1 -0
- data/lib/nokogiri/html/document.rb +13 -26
- data/lib/nokogiri/html/document_fragment.rb +1 -0
- data/lib/nokogiri/html/element_description.rb +1 -0
- data/lib/nokogiri/html/element_description_defaults.rb +1 -0
- data/lib/nokogiri/html/entity_lookup.rb +1 -0
- data/lib/nokogiri/html/sax/parser.rb +1 -0
- data/lib/nokogiri/html/sax/parser_context.rb +1 -0
- data/lib/nokogiri/html/sax/push_parser.rb +1 -0
- data/lib/nokogiri/jruby/dependencies.rb +20 -0
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/lib/nokogiri/syntax_error.rb +1 -0
- data/lib/nokogiri/version.rb +3 -109
- data/lib/nokogiri/version/constant.rb +5 -0
- data/lib/nokogiri/version/info.rb +182 -0
- data/lib/nokogiri/xml.rb +1 -0
- data/lib/nokogiri/xml/attr.rb +1 -0
- data/lib/nokogiri/xml/attribute_decl.rb +1 -0
- data/lib/nokogiri/xml/builder.rb +3 -2
- data/lib/nokogiri/xml/cdata.rb +1 -0
- data/lib/nokogiri/xml/character_data.rb +1 -0
- data/lib/nokogiri/xml/document.rb +20 -15
- data/lib/nokogiri/xml/document_fragment.rb +5 -6
- data/lib/nokogiri/xml/dtd.rb +1 -0
- data/lib/nokogiri/xml/element_content.rb +1 -0
- data/lib/nokogiri/xml/element_decl.rb +1 -0
- data/lib/nokogiri/xml/entity_decl.rb +1 -0
- data/lib/nokogiri/xml/entity_reference.rb +1 -0
- data/lib/nokogiri/xml/namespace.rb +1 -0
- data/lib/nokogiri/xml/node.rb +587 -249
- data/lib/nokogiri/xml/node/save_options.rb +1 -0
- data/lib/nokogiri/xml/node_set.rb +1 -0
- data/lib/nokogiri/xml/notation.rb +1 -0
- data/lib/nokogiri/xml/parse_options.rb +10 -3
- data/lib/nokogiri/xml/pp.rb +1 -0
- data/lib/nokogiri/xml/pp/character_data.rb +1 -0
- data/lib/nokogiri/xml/pp/node.rb +1 -0
- data/lib/nokogiri/xml/processing_instruction.rb +1 -0
- data/lib/nokogiri/xml/reader.rb +7 -3
- data/lib/nokogiri/xml/relax_ng.rb +7 -2
- data/lib/nokogiri/xml/sax.rb +1 -0
- data/lib/nokogiri/xml/sax/document.rb +1 -0
- data/lib/nokogiri/xml/sax/parser.rb +1 -0
- data/lib/nokogiri/xml/sax/parser_context.rb +1 -0
- data/lib/nokogiri/xml/sax/push_parser.rb +1 -0
- data/lib/nokogiri/xml/schema.rb +13 -4
- data/lib/nokogiri/xml/searchable.rb +25 -16
- data/lib/nokogiri/xml/syntax_error.rb +1 -0
- data/lib/nokogiri/xml/text.rb +1 -0
- data/lib/nokogiri/xml/xpath.rb +1 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -0
- data/lib/nokogiri/xml/xpath_context.rb +1 -0
- data/lib/nokogiri/xslt.rb +1 -0
- data/lib/nokogiri/xslt/stylesheet.rb +1 -0
- data/lib/xsd/xmlparser/nokogiri.rb +1 -0
- metadata +86 -159
- data/ext/java/nokogiri/internals/NokogiriEncodingReaderWrapper.java +0 -107
- data/ext/java/nokogiri/internals/UncloseableInputStream.java +0 -102
- data/ext/nokogiri/html_document.h +0 -10
- data/ext/nokogiri/html_element_description.h +0 -10
- data/ext/nokogiri/html_entity_lookup.h +0 -8
- data/ext/nokogiri/html_sax_parser_context.h +0 -11
- data/ext/nokogiri/html_sax_push_parser.h +0 -9
- data/ext/nokogiri/nokogiri.h +0 -121
- data/ext/nokogiri/xml_attr.h +0 -9
- data/ext/nokogiri/xml_attribute_decl.h +0 -9
- data/ext/nokogiri/xml_cdata.h +0 -9
- data/ext/nokogiri/xml_comment.h +0 -9
- data/ext/nokogiri/xml_document.h +0 -23
- data/ext/nokogiri/xml_document_fragment.h +0 -10
- data/ext/nokogiri/xml_dtd.h +0 -10
- data/ext/nokogiri/xml_element_content.h +0 -10
- data/ext/nokogiri/xml_element_decl.h +0 -9
- data/ext/nokogiri/xml_encoding_handler.h +0 -8
- data/ext/nokogiri/xml_entity_decl.h +0 -10
- data/ext/nokogiri/xml_entity_reference.h +0 -9
- data/ext/nokogiri/xml_io.h +0 -11
- data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
- data/ext/nokogiri/xml_namespace.h +0 -14
- data/ext/nokogiri/xml_node.h +0 -13
- data/ext/nokogiri/xml_node_set.h +0 -12
- data/ext/nokogiri/xml_processing_instruction.h +0 -9
- data/ext/nokogiri/xml_reader.h +0 -10
- data/ext/nokogiri/xml_relax_ng.h +0 -9
- data/ext/nokogiri/xml_sax_parser.h +0 -39
- data/ext/nokogiri/xml_sax_parser_context.h +0 -10
- data/ext/nokogiri/xml_sax_push_parser.h +0 -9
- data/ext/nokogiri/xml_schema.h +0 -9
- data/ext/nokogiri/xml_syntax_error.h +0 -13
- data/ext/nokogiri/xml_text.h +0 -9
- data/ext/nokogiri/xml_xpath_context.h +0 -10
- data/ext/nokogiri/xslt_stylesheet.h +0 -14
@@ -46,49 +46,43 @@ import org.w3c.dom.NamedNodeMap;
|
|
46
46
|
import org.w3c.dom.Node;
|
47
47
|
|
48
48
|
/**
|
49
|
-
* Cache of
|
49
|
+
* Cache of namespaces of each node. XmlDocument has one cache of this class.
|
50
50
|
*
|
51
51
|
* @author sergio
|
52
52
|
* @author Yoko Harada <yokolet@gmail.com>
|
53
53
|
*/
|
54
54
|
public class NokogiriNamespaceCache {
|
55
55
|
|
56
|
-
private
|
57
|
-
private Map<String[], CacheEntry> cache; // pair of the index of a given key and entry
|
56
|
+
private final Map<CacheKey, CacheEntry> cache; // pair of the index of a given key and entry
|
58
57
|
private XmlNamespace defaultNamespace = null;
|
59
58
|
|
60
59
|
public NokogiriNamespaceCache() {
|
61
|
-
|
62
|
-
cache = new LinkedHashMap<String[], CacheEntry>();
|
60
|
+
this.cache = new LinkedHashMap<CacheKey, CacheEntry>(4);
|
63
61
|
}
|
64
62
|
|
65
|
-
public
|
66
|
-
|
63
|
+
public NokogiriNamespaceCache(NokogiriNamespaceCache cache) {
|
64
|
+
this.cache = new LinkedHashMap<CacheKey, CacheEntry>(cache.size() + 2);
|
65
|
+
this.cache.putAll(cache.cache);
|
67
66
|
}
|
68
67
|
|
69
|
-
|
70
|
-
|
71
|
-
if (key[0].equals(prefix) && key[1].equals(href)) return key;
|
72
|
-
}
|
73
|
-
return null;
|
68
|
+
public XmlNamespace getDefault() {
|
69
|
+
return defaultNamespace;
|
74
70
|
}
|
75
71
|
|
76
72
|
public XmlNamespace get(String prefix, String href) {
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
if (key != null) {
|
82
|
-
return cache.get(key).namespace;
|
83
|
-
}
|
84
|
-
return null;
|
73
|
+
if (href == null) return null;
|
74
|
+
|
75
|
+
CacheEntry value = cache.get(new CacheKey(prefix, href));
|
76
|
+
return value == null ? null : value.namespace;
|
85
77
|
}
|
86
78
|
|
87
79
|
public XmlNamespace get(Node node, String prefix) {
|
88
80
|
if (prefix == null) return defaultNamespace;
|
89
|
-
for (
|
90
|
-
if (
|
91
|
-
|
81
|
+
for (Map.Entry<CacheKey, CacheEntry> entry : cache.entrySet()) {
|
82
|
+
if (entry.getKey().prefix.equals(prefix)) {
|
83
|
+
if (entry.getValue().isOwner(node)) {
|
84
|
+
return entry.getValue().namespace;
|
85
|
+
}
|
92
86
|
}
|
93
87
|
}
|
94
88
|
return null;
|
@@ -100,9 +94,9 @@ public class NokogiriNamespaceCache {
|
|
100
94
|
namespaces.add(defaultNamespace);
|
101
95
|
return namespaces;
|
102
96
|
}
|
103
|
-
for (
|
104
|
-
if (
|
105
|
-
namespaces.add(
|
97
|
+
for (Map.Entry<CacheKey, CacheEntry> entry : cache.entrySet()) {
|
98
|
+
if (entry.getKey().prefix.equals(prefix)) {
|
99
|
+
namespaces.add(entry.getValue().namespace);
|
106
100
|
}
|
107
101
|
}
|
108
102
|
return namespaces;
|
@@ -110,63 +104,96 @@ public class NokogiriNamespaceCache {
|
|
110
104
|
|
111
105
|
public List<XmlNamespace> get(Node node) {
|
112
106
|
List<XmlNamespace> namespaces = new ArrayList<XmlNamespace>();
|
113
|
-
for (
|
114
|
-
|
115
|
-
|
116
|
-
namespaces.add(entry.namespace);
|
107
|
+
for (Map.Entry<CacheKey, CacheEntry> entry : cache.entrySet()) {
|
108
|
+
if (entry.getValue().isOwner(node)) {
|
109
|
+
namespaces.add(entry.getValue().namespace);
|
117
110
|
}
|
118
111
|
}
|
119
112
|
return namespaces;
|
120
113
|
}
|
121
114
|
|
122
115
|
public void put(XmlNamespace namespace, Node ownerNode) {
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
cache.put(key, entry);
|
132
|
-
if ("".equals(prefixString)) defaultNamespace = namespace;
|
116
|
+
String prefix = namespace.getPrefix();
|
117
|
+
String href = namespace.getHref();
|
118
|
+
if (href == null) return;
|
119
|
+
|
120
|
+
CacheKey key = new CacheKey(prefix, href);
|
121
|
+
if (cache.get(key) != null) return;
|
122
|
+
cache.put(key, new CacheEntry(namespace, ownerNode));
|
123
|
+
if ("".equals(prefix)) defaultNamespace = namespace;
|
133
124
|
}
|
134
125
|
|
135
|
-
public void remove(
|
136
|
-
String
|
137
|
-
|
138
|
-
|
139
|
-
|
126
|
+
public void remove(Node ownerNode) {
|
127
|
+
String prefix = ownerNode.getPrefix();
|
128
|
+
String href = ownerNode.getNamespaceURI();
|
129
|
+
if (href == null) return;
|
130
|
+
|
131
|
+
cache.remove(new CacheKey(prefix, href));
|
132
|
+
}
|
133
|
+
|
134
|
+
public int size() {
|
135
|
+
return cache.size();
|
140
136
|
}
|
141
137
|
|
142
138
|
public void clear() {
|
143
139
|
// removes namespace declarations from node
|
144
|
-
for (
|
145
|
-
CacheEntry entry = cache.get(key);
|
140
|
+
for (CacheEntry entry : cache.values()) {
|
146
141
|
NamedNodeMap attributes = entry.ownerNode.getAttributes();
|
147
142
|
for (int j=0; j<attributes.getLength(); j++) {
|
148
|
-
String name = ((Attr)attributes.item(j)).getName();
|
143
|
+
String name = ((Attr) attributes.item(j)).getName();
|
149
144
|
if (isNamespace(name)) {
|
150
145
|
attributes.removeNamedItem(name);
|
151
146
|
}
|
152
147
|
}
|
153
148
|
}
|
154
|
-
keys.clear();
|
155
149
|
cache.clear();
|
156
150
|
defaultNamespace = null;
|
157
151
|
}
|
158
152
|
|
159
153
|
public void replaceNode(Node oldNode, Node newNode) {
|
160
|
-
for (
|
161
|
-
|
162
|
-
|
163
|
-
|
154
|
+
for (Map.Entry<CacheKey, CacheEntry> entry : cache.entrySet()) {
|
155
|
+
if (entry.getValue().isOwner(oldNode)) {
|
156
|
+
entry.getValue().replaceOwner(newNode);
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
@Override
|
162
|
+
public String toString() {
|
163
|
+
return getClass().getName() + '@' + Integer.toHexString(hashCode()) + '(' + cache + "default=" + defaultNamespace + ')';
|
164
|
+
}
|
165
|
+
|
166
|
+
private static class CacheKey {
|
167
|
+
final String prefix;
|
168
|
+
final String href;
|
169
|
+
|
170
|
+
CacheKey(String prefix, String href) {
|
171
|
+
this.prefix = prefix;
|
172
|
+
this.href = href;
|
173
|
+
}
|
174
|
+
|
175
|
+
@Override
|
176
|
+
public boolean equals(final Object obj) {
|
177
|
+
if (obj instanceof CacheKey) {
|
178
|
+
CacheKey that = (CacheKey) obj;
|
179
|
+
return prefix == null ? that.prefix == null : prefix.equals(that.prefix) && href.equals(that.href);
|
164
180
|
}
|
181
|
+
return false;
|
182
|
+
}
|
183
|
+
|
184
|
+
@Override
|
185
|
+
public int hashCode() {
|
186
|
+
return (prefix == null ? 0 : prefix.hashCode()) + 37 * href.hashCode();
|
187
|
+
}
|
188
|
+
|
189
|
+
@Override
|
190
|
+
public String toString() {
|
191
|
+
return '[' + prefix + ']' + href;
|
165
192
|
}
|
166
193
|
}
|
167
194
|
|
168
|
-
private class CacheEntry {
|
169
|
-
|
195
|
+
private static class CacheEntry {
|
196
|
+
final XmlNamespace namespace;
|
170
197
|
private Node ownerNode;
|
171
198
|
|
172
199
|
CacheEntry(XmlNamespace namespace, Node ownerNode) {
|
@@ -174,12 +201,17 @@ public class NokogiriNamespaceCache {
|
|
174
201
|
this.ownerNode = ownerNode;
|
175
202
|
}
|
176
203
|
|
177
|
-
|
178
|
-
return ownerNode.isSameNode(
|
204
|
+
boolean isOwner(Node node) {
|
205
|
+
return ownerNode.isSameNode(node);
|
179
206
|
}
|
180
207
|
|
181
|
-
|
208
|
+
void replaceOwner(Node newNode) {
|
182
209
|
this.ownerNode = newNode;
|
183
210
|
}
|
211
|
+
|
212
|
+
@Override
|
213
|
+
public String toString() {
|
214
|
+
return namespace.toString();
|
215
|
+
}
|
184
216
|
}
|
185
217
|
}
|
@@ -50,9 +50,15 @@ import javax.xml.namespace.NamespaceContext;
|
|
50
50
|
*/
|
51
51
|
public final class NokogiriNamespaceContext implements NamespaceContext {
|
52
52
|
|
53
|
-
|
53
|
+
/*
|
54
|
+
* these constants have matching declarations in
|
55
|
+
* ext/nokogiri/xml_xpath_context.c
|
56
|
+
*/
|
57
|
+
public static final String NOKOGIRI_PREFIX = "nokogiri";
|
54
58
|
public static final String NOKOGIRI_URI = "http://www.nokogiri.org/default_ns/ruby/extensions_functions";
|
55
|
-
|
59
|
+
|
60
|
+
public static final String NOKOGIRI_BUILTIN_PREFIX = "nokogiri-builtin";
|
61
|
+
public static final String NOKOGIRI_BUILTIN_URI = "https://www.nokogiri.org/default_ns/ruby/builtins";
|
56
62
|
|
57
63
|
private final Map<String,String> register;
|
58
64
|
|
@@ -63,6 +69,7 @@ public final class NokogiriNamespaceContext implements NamespaceContext {
|
|
63
69
|
private NokogiriNamespaceContext() {
|
64
70
|
register = new HashMap<String, String>(6, 1);
|
65
71
|
register.put(NOKOGIRI_PREFIX, NOKOGIRI_URI);
|
72
|
+
register.put(NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
|
66
73
|
register.put("xml", "http://www.w3.org/XML/1998/namespace");
|
67
74
|
register.put("xhtml", "http://www.w3.org/1999/xhtml");
|
68
75
|
}
|
@@ -36,6 +36,7 @@ import java.util.List;
|
|
36
36
|
|
37
37
|
import javax.xml.xpath.XPathFunction;
|
38
38
|
import javax.xml.xpath.XPathFunctionException;
|
39
|
+
import javax.xml.namespace.QName;
|
39
40
|
|
40
41
|
import org.jruby.Ruby;
|
41
42
|
import org.jruby.RubyArray;
|
@@ -53,6 +54,8 @@ import org.w3c.dom.NodeList;
|
|
53
54
|
import nokogiri.XmlNode;
|
54
55
|
import nokogiri.XmlNodeSet;
|
55
56
|
|
57
|
+
import static nokogiri.internals.NokogiriHelpers.nodeListToRubyArray;
|
58
|
+
|
56
59
|
/**
|
57
60
|
* Xpath function handler.
|
58
61
|
*
|
@@ -62,14 +65,14 @@ import nokogiri.XmlNodeSet;
|
|
62
65
|
public class NokogiriXPathFunction implements XPathFunction {
|
63
66
|
|
64
67
|
private final IRubyObject handler;
|
65
|
-
private final
|
68
|
+
private final QName name;
|
66
69
|
private final int arity;
|
67
70
|
|
68
|
-
public static NokogiriXPathFunction create(IRubyObject handler,
|
71
|
+
public static NokogiriXPathFunction create(IRubyObject handler, QName name, int arity) {
|
69
72
|
return new NokogiriXPathFunction(handler, name, arity);
|
70
73
|
}
|
71
74
|
|
72
|
-
private NokogiriXPathFunction(IRubyObject handler,
|
75
|
+
private NokogiriXPathFunction(IRubyObject handler, QName name, int arity) {
|
73
76
|
this.handler = handler;
|
74
77
|
this.name = name;
|
75
78
|
this.arity = arity;
|
@@ -80,11 +83,20 @@ public class NokogiriXPathFunction implements XPathFunction {
|
|
80
83
|
throw new XPathFunctionException("arity does not match");
|
81
84
|
}
|
82
85
|
|
83
|
-
|
84
|
-
|
86
|
+
if (name.getNamespaceURI().equals(NokogiriNamespaceContext.NOKOGIRI_BUILTIN_URI)) {
|
87
|
+
if (name.getLocalPart().equals("css-class")) {
|
88
|
+
return builtinCssClass(args);
|
89
|
+
}
|
90
|
+
}
|
85
91
|
|
86
|
-
|
92
|
+
if (this.handler.isNil()) {
|
93
|
+
throw new XPathFunctionException("no custom function handler declared for '" + name + "'");
|
94
|
+
}
|
87
95
|
|
96
|
+
final Ruby runtime = this.handler.getRuntime();
|
97
|
+
ThreadContext context = runtime.getCurrentContext();
|
98
|
+
IRubyObject result = Helpers.invoke(context, this.handler, this.name.getLocalPart(),
|
99
|
+
fromObjectToRubyArgs(runtime, args));
|
88
100
|
return fromRubyToObject(runtime, result);
|
89
101
|
}
|
90
102
|
|
@@ -99,9 +111,8 @@ public class NokogiriXPathFunction implements XPathFunction {
|
|
99
111
|
private static IRubyObject fromObjectToRuby(final Ruby runtime, Object obj) {
|
100
112
|
// argument object type is one of NodeList, String, Boolean, or Double.
|
101
113
|
if (obj instanceof NodeList) {
|
102
|
-
|
103
|
-
|
104
|
-
return xmlNodeSet;
|
114
|
+
IRubyObject[] nodes = nodeListToRubyArray(runtime, (NodeList) obj);
|
115
|
+
return XmlNodeSet.newNodeSet(runtime, nodes);
|
105
116
|
}
|
106
117
|
return JavaUtil.convertJavaToUsableRubyObject(runtime, obj);
|
107
118
|
}
|
@@ -116,8 +127,54 @@ public class NokogiriXPathFunction implements XPathFunction {
|
|
116
127
|
}
|
117
128
|
if (obj instanceof XmlNodeSet) return obj;
|
118
129
|
if (obj instanceof RubyArray) {
|
119
|
-
return XmlNodeSet.
|
130
|
+
return XmlNodeSet.newNodeSet(runtime, ((RubyArray) obj).toJavaArray());
|
120
131
|
}
|
121
132
|
/*if (o instanceof XmlNode)*/ return ((XmlNode) obj).getNode();
|
122
133
|
}
|
134
|
+
|
135
|
+
private static boolean builtinCssClass(List args) throws XPathFunctionException {
|
136
|
+
if (args.size() != 2) {
|
137
|
+
throw new XPathFunctionException("builtin function nokogiri:css-class takes two arguments");
|
138
|
+
}
|
139
|
+
|
140
|
+
String hay = args.get(0).toString();
|
141
|
+
String needle = args.get(1).toString();
|
142
|
+
|
143
|
+
if (needle.length() == 0) {
|
144
|
+
return true;
|
145
|
+
}
|
146
|
+
|
147
|
+
int j = 0;
|
148
|
+
int j_lim = hay.length() - needle.length();
|
149
|
+
while (j <= j_lim) {
|
150
|
+
int k;
|
151
|
+
for (k = 0; k < needle.length(); k++) {
|
152
|
+
if (needle.charAt(k) != hay.charAt(j+k)) {
|
153
|
+
break;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
if (k == needle.length()) {
|
157
|
+
if ((hay.length() == (j+k)) || isWhitespace(hay.charAt(j+k))) {
|
158
|
+
return true ;
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
/* advance str to whitespace */
|
163
|
+
while (j <= j_lim && !isWhitespace(hay.charAt(j))) {
|
164
|
+
j++;
|
165
|
+
}
|
166
|
+
|
167
|
+
/* advance str to start of next word or end of string */
|
168
|
+
while (j <= j_lim && isWhitespace(hay.charAt(j))) {
|
169
|
+
j++;
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
return false;
|
174
|
+
}
|
175
|
+
|
176
|
+
private static boolean isWhitespace(char subject) {
|
177
|
+
// see libxml2's xmlIsBlank_ch()
|
178
|
+
return ((subject == 0x09) || (subject == 0x0A) || (subject == 0x0D) || (subject == 0x20));
|
179
|
+
}
|
123
180
|
}
|
@@ -50,7 +50,9 @@ public final class NokogiriXPathFunctionResolver implements XPathFunctionResolve
|
|
50
50
|
|
51
51
|
public static NokogiriXPathFunctionResolver create(IRubyObject handler) {
|
52
52
|
NokogiriXPathFunctionResolver freshResolver = new NokogiriXPathFunctionResolver();
|
53
|
-
|
53
|
+
if (!handler.isNil()) {
|
54
|
+
freshResolver.setHandler(handler);
|
55
|
+
}
|
54
56
|
return freshResolver;
|
55
57
|
}
|
56
58
|
|
@@ -65,6 +67,6 @@ public final class NokogiriXPathFunctionResolver implements XPathFunctionResolve
|
|
65
67
|
}
|
66
68
|
|
67
69
|
public XPathFunction resolveFunction(QName name, int arity) {
|
68
|
-
return NokogiriXPathFunction.create(handler, name
|
70
|
+
return NokogiriXPathFunction.create(handler, name, arity);
|
69
71
|
}
|
70
72
|
}
|
@@ -33,27 +33,22 @@
|
|
33
33
|
package nokogiri.internals;
|
34
34
|
|
35
35
|
import static nokogiri.internals.NokogiriHelpers.rubyStringToString;
|
36
|
-
import static org.jruby.runtime.Helpers.invoke;
|
37
36
|
|
38
37
|
import java.io.ByteArrayInputStream;
|
39
38
|
import java.io.File;
|
40
39
|
import java.io.IOException;
|
41
40
|
import java.io.InputStream;
|
42
|
-
import java.io.StringReader;
|
43
41
|
import java.net.URI;
|
44
|
-
import java.nio.charset.Charset;
|
45
|
-
import java.nio.charset.UnsupportedCharsetException;
|
46
42
|
import java.util.concurrent.Callable;
|
47
43
|
|
48
44
|
import org.jruby.Ruby;
|
49
45
|
import org.jruby.RubyClass;
|
50
|
-
import org.jruby.RubyIO;
|
51
46
|
import org.jruby.RubyObject;
|
52
47
|
import org.jruby.RubyString;
|
53
48
|
import org.jruby.runtime.ThreadContext;
|
54
49
|
import org.jruby.runtime.builtin.IRubyObject;
|
55
50
|
import org.jruby.util.ByteList;
|
56
|
-
import org.jruby.util.
|
51
|
+
import org.jruby.util.IOInputStream;
|
57
52
|
import org.xml.sax.InputSource;
|
58
53
|
|
59
54
|
/**
|
@@ -67,6 +62,7 @@ public abstract class ParserContext extends RubyObject {
|
|
67
62
|
protected InputSource source = null;
|
68
63
|
protected IRubyObject detected_encoding = null;
|
69
64
|
protected int stringDataSize = -1;
|
65
|
+
protected String java_encoding;
|
70
66
|
|
71
67
|
public ParserContext(Ruby runtime) {
|
72
68
|
// default to class 'Object' because this class isn't exposed to Ruby
|
@@ -81,68 +77,42 @@ public abstract class ParserContext extends RubyObject {
|
|
81
77
|
return source;
|
82
78
|
}
|
83
79
|
|
84
|
-
|
85
|
-
* Set the InputSource from <code>url</code> or <code>data</code>,
|
86
|
-
* which may be an IO object, a String, or a StringIO.
|
87
|
-
*/
|
88
|
-
public void setInputSource(ThreadContext context, IRubyObject data, IRubyObject url) {
|
80
|
+
public void setIOInputSource(ThreadContext context, IRubyObject data, IRubyObject url) {
|
89
81
|
source = new InputSource();
|
90
|
-
|
91
|
-
Ruby ruby = context.getRuntime();
|
92
|
-
|
93
82
|
ParserContext.setUrl(context, source, url);
|
94
83
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
RubyString stringData = null;
|
101
|
-
if (invoke(context, data, "respond_to?", ruby.newSymbol("to_io")).isTrue()) {
|
102
|
-
RubyIO io =
|
103
|
-
(RubyIO) TypeConverter.convertToType(data,
|
104
|
-
ruby.getIO(),
|
105
|
-
"to_io");
|
106
|
-
// use unclosedable input stream to fix #495
|
107
|
-
source.setByteStream(new UncloseableInputStream(io.getInStream()));
|
108
|
-
|
109
|
-
} else if (invoke(context, data, "respond_to?", ruby.newSymbol("read")).isTrue()) {
|
110
|
-
stringData = invoke(context, data, "read").convertToString();
|
84
|
+
source.setByteStream(new IOInputStream(data));
|
85
|
+
if (java_encoding != null) {
|
86
|
+
source.setEncoding(java_encoding);
|
87
|
+
}
|
88
|
+
}
|
111
89
|
|
112
|
-
|
113
|
-
|
90
|
+
public void setStringInputSource(ThreadContext context, IRubyObject data, IRubyObject url) {
|
91
|
+
source = new InputSource();
|
92
|
+
ParserContext.setUrl(context, source, url);
|
114
93
|
|
115
|
-
|
116
|
-
stringData = (RubyString) data;
|
94
|
+
Ruby ruby = context.getRuntime();
|
117
95
|
|
118
|
-
|
119
|
-
throw ruby.newArgumentError("must be kind_of String
|
96
|
+
if (!(data instanceof RubyString)) {
|
97
|
+
throw ruby.newArgumentError("must be kind_of String");
|
120
98
|
}
|
121
99
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
Charset charset = null;
|
100
|
+
RubyString stringData = (RubyString) data;
|
101
|
+
|
102
|
+
if (stringData.encoding(context) != null) {
|
103
|
+
RubyString stringEncoding = stringData.encoding(context).asString();
|
104
|
+
String encName = NokogiriHelpers.getValidEncodingOrNull(stringEncoding);
|
128
105
|
if (encName != null) {
|
129
|
-
|
130
|
-
charset = Charset.forName(encName);
|
131
|
-
} catch (UnsupportedCharsetException e) {
|
132
|
-
// do nothing;
|
133
|
-
}
|
134
|
-
}
|
135
|
-
ByteList bytes = stringData.getByteList();
|
136
|
-
if (charset != null) {
|
137
|
-
StringReader reader = new StringReader(new String(bytes.unsafeBytes(), bytes.begin(), bytes.length(), charset));
|
138
|
-
source.setCharacterStream(reader);
|
139
|
-
source.setEncoding(charset.name());
|
140
|
-
} else {
|
141
|
-
stringDataSize = bytes.length() - bytes.begin();
|
142
|
-
ByteArrayInputStream stream = new ByteArrayInputStream(bytes.unsafeBytes(), bytes.begin(), bytes.length());
|
143
|
-
source.setByteStream(stream);
|
106
|
+
java_encoding = encName;
|
144
107
|
}
|
145
108
|
}
|
109
|
+
|
110
|
+
ByteList bytes = stringData.getByteList();
|
111
|
+
|
112
|
+
stringDataSize = bytes.length() - bytes.begin();
|
113
|
+
ByteArrayInputStream stream = new ByteArrayInputStream(bytes.unsafeBytes(), bytes.begin(), bytes.length());
|
114
|
+
source.setByteStream(stream);
|
115
|
+
source.setEncoding(java_encoding);
|
146
116
|
}
|
147
117
|
|
148
118
|
public static void setUrl(ThreadContext context, InputSource source, IRubyObject url) {
|
@@ -171,22 +141,6 @@ public abstract class ParserContext extends RubyObject {
|
|
171
141
|
}
|
172
142
|
}
|
173
143
|
|
174
|
-
private boolean setEncoding(ThreadContext context, IRubyObject data) {
|
175
|
-
if (data.getType().respondsTo("detect_encoding")) {
|
176
|
-
// in case of EncodingReader is used
|
177
|
-
// since EncodingReader won't respond to :to_io
|
178
|
-
NokogiriEncodingReaderWrapper reader = new NokogiriEncodingReaderWrapper(context, (RubyObject) data);
|
179
|
-
source.setByteStream(reader);
|
180
|
-
// data is EnocodingReader
|
181
|
-
if(reader.detectEncoding()) {
|
182
|
-
detected_encoding = reader.getEncoding();
|
183
|
-
source.setEncoding(detected_encoding.asJavaString());
|
184
|
-
}
|
185
|
-
return true;
|
186
|
-
}
|
187
|
-
return false;
|
188
|
-
}
|
189
|
-
|
190
144
|
protected void setEncoding(String encoding) {
|
191
145
|
source.setEncoding(encoding);
|
192
146
|
}
|