nokogiri 1.5.0.beta.1-java → 1.5.0.beta.2-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.
- data/CHANGELOG.ja.rdoc +28 -8
- data/CHANGELOG.rdoc +23 -0
- data/Manifest.txt +68 -1
- data/README.ja.rdoc +1 -1
- data/README.rdoc +22 -4
- data/Rakefile +6 -2
- data/ext/java/nokogiri/EncodingHandler.java +92 -0
- data/ext/java/nokogiri/HtmlDocument.java +116 -0
- data/ext/java/nokogiri/HtmlElementDescription.java +111 -0
- data/ext/java/nokogiri/HtmlEntityLookup.java +45 -0
- data/ext/java/nokogiri/HtmlSaxParserContext.java +218 -0
- data/ext/java/nokogiri/NokogiriService.java +370 -0
- data/ext/java/nokogiri/XmlAttr.java +147 -0
- data/ext/java/nokogiri/XmlAttributeDecl.java +98 -0
- data/ext/java/nokogiri/XmlCdata.java +50 -0
- data/ext/java/nokogiri/XmlComment.java +47 -0
- data/ext/java/nokogiri/XmlDocument.java +463 -0
- data/ext/java/nokogiri/XmlDocumentFragment.java +207 -0
- data/ext/java/nokogiri/XmlDtd.java +427 -0
- data/ext/java/nokogiri/XmlElement.java +172 -0
- data/ext/java/nokogiri/XmlElementContent.java +350 -0
- data/ext/java/nokogiri/XmlElementDecl.java +115 -0
- data/ext/java/nokogiri/XmlEntityDecl.java +129 -0
- data/ext/java/nokogiri/XmlEntityReference.java +42 -0
- data/ext/java/nokogiri/XmlNamespace.java +77 -0
- data/ext/java/nokogiri/XmlNode.java +1399 -0
- data/ext/java/nokogiri/XmlNodeSet.java +248 -0
- data/ext/java/nokogiri/XmlProcessingInstruction.java +70 -0
- data/ext/java/nokogiri/XmlReader.java +373 -0
- data/ext/java/nokogiri/XmlRelaxng.java +166 -0
- data/ext/java/nokogiri/XmlSaxParserContext.java +308 -0
- data/ext/java/nokogiri/XmlSaxPushParser.java +146 -0
- data/ext/java/nokogiri/XmlSchema.java +142 -0
- data/ext/java/nokogiri/XmlSyntaxError.java +84 -0
- data/ext/java/nokogiri/XmlText.java +96 -0
- data/ext/java/nokogiri/XmlXpathContext.java +130 -0
- data/ext/java/nokogiri/XsltStylesheet.java +126 -0
- data/ext/java/nokogiri/internals/HtmlDomParserContext.java +181 -0
- data/ext/java/nokogiri/internals/NokogiriDocumentCache.java +39 -0
- data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +42 -0
- data/ext/java/nokogiri/internals/NokogiriHandler.java +251 -0
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +526 -0
- data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +136 -0
- data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +80 -0
- data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +37 -0
- data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +54 -0
- data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +49 -0
- data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +88 -0
- data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +23 -0
- data/ext/java/nokogiri/internals/ParserContext.java +235 -0
- data/ext/java/nokogiri/internals/PushInputStream.java +381 -0
- data/ext/java/nokogiri/internals/ReaderNode.java +431 -0
- data/ext/java/nokogiri/internals/SaveContext.java +249 -0
- data/ext/java/nokogiri/internals/SchemaErrorHandler.java +35 -0
- data/ext/java/nokogiri/internals/XmlDeclHandler.java +10 -0
- data/ext/java/nokogiri/internals/XmlDomParser.java +45 -0
- data/ext/java/nokogiri/internals/XmlDomParserContext.java +201 -0
- data/ext/java/nokogiri/internals/XmlSaxParser.java +33 -0
- data/ext/nokogiri/depend +32 -0
- data/ext/nokogiri/extconf.rb +61 -32
- data/ext/nokogiri/libcharset-1.dll +0 -0
- data/ext/nokogiri/libexslt.dll +0 -0
- data/ext/nokogiri/libiconv-2.dll +0 -0
- data/ext/nokogiri/libxml2.dll +0 -0
- data/ext/nokogiri/libxslt.dll +0 -0
- data/ext/nokogiri/nokogiri.c +0 -5
- data/ext/nokogiri/nokogiri.h +2 -2
- data/ext/nokogiri/xml_document.c +5 -0
- data/ext/nokogiri/xml_libxml2_hacks.c +112 -0
- data/ext/nokogiri/xml_libxml2_hacks.h +12 -0
- data/ext/nokogiri/xml_node.c +56 -16
- data/ext/nokogiri/xml_node_set.c +7 -7
- data/ext/nokogiri/xml_reader.c +20 -1
- data/ext/nokogiri/xml_relax_ng.c +0 -7
- data/ext/nokogiri/xml_xpath_context.c +2 -0
- data/ext/nokogiri/zlib1.dll +0 -0
- data/lib/nokogiri.rb +1 -2
- data/lib/nokogiri/css/generated_parser.rb +155 -148
- data/lib/nokogiri/css/generated_tokenizer.rb +2 -1
- data/lib/nokogiri/css/parser.y +3 -0
- data/lib/nokogiri/css/xpath_visitor.rb +1 -7
- data/lib/nokogiri/html.rb +2 -2
- data/lib/nokogiri/html/document_fragment.rb +7 -4
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/lib/nokogiri/version.rb +3 -6
- data/lib/nokogiri/xml/builder.rb +1 -1
- data/lib/nokogiri/xml/document.rb +1 -2
- data/lib/nokogiri/xml/document_fragment.rb +7 -0
- data/lib/nokogiri/xml/node.rb +5 -3
- data/lib/nokogiri/xml/node_set.rb +25 -0
- data/lib/nokogiri/xml/reader.rb +2 -0
- data/lib/nokogiri/xml/sax/document.rb +3 -1
- data/spec/helper.rb +3 -0
- data/spec/xml/reader_spec.rb +307 -0
- data/tasks/test.rb +1 -1
- data/test/css/test_parser.rb +11 -1
- data/test/html/sax/test_parser_context.rb +2 -2
- data/test/html/test_document.rb +2 -2
- data/test/html/test_document_fragment.rb +34 -6
- data/test/test_memory_leak.rb +2 -2
- data/test/test_reader.rb +28 -6
- data/test/test_xslt_transforms.rb +2 -3
- data/test/xml/test_attr.rb +31 -4
- data/test/xml/test_builder.rb +5 -5
- data/test/xml/test_cdata.rb +3 -3
- data/test/xml/test_document.rb +8 -8
- data/test/xml/test_document_fragment.rb +4 -12
- data/test/xml/test_node.rb +1 -1
- data/test/xml/test_node_reparenting.rb +26 -11
- data/test/xml/test_node_set.rb +38 -2
- data/test/xml/test_text.rb +11 -2
- data/test/xml/test_unparented_node.rb +1 -1
- data/test/xml/test_xpath.rb +11 -7
- metadata +159 -100
- data.tar.gz.sig +0 -0
- data/lib/nokogiri/version_warning.rb +0 -14
- metadata.gz.sig +0 -0
@@ -0,0 +1,136 @@
|
|
1
|
+
package nokogiri.internals;
|
2
|
+
|
3
|
+
import static nokogiri.internals.NokogiriHelpers.isNamespace;
|
4
|
+
|
5
|
+
import java.util.ArrayList;
|
6
|
+
import java.util.HashMap;
|
7
|
+
import java.util.List;
|
8
|
+
import java.util.Map;
|
9
|
+
|
10
|
+
import nokogiri.XmlDocument;
|
11
|
+
import nokogiri.XmlNamespace;
|
12
|
+
|
13
|
+
import org.jruby.Ruby;
|
14
|
+
import org.jruby.runtime.ThreadContext;
|
15
|
+
import org.w3c.dom.Attr;
|
16
|
+
import org.w3c.dom.NamedNodeMap;
|
17
|
+
import org.w3c.dom.Node;
|
18
|
+
|
19
|
+
/**
|
20
|
+
*
|
21
|
+
* @author sergio
|
22
|
+
* @author Yoko Harada <yokolet@gmail.com>
|
23
|
+
*/
|
24
|
+
public class NokogiriNamespaceCache {
|
25
|
+
|
26
|
+
private List<Long> keys; // order matters.
|
27
|
+
private Map<Integer, CacheEntry> cache; // pair of the index of a given key and entry
|
28
|
+
private XmlNamespace defaultNamespace = null;
|
29
|
+
|
30
|
+
public NokogiriNamespaceCache() {
|
31
|
+
keys = new ArrayList<Long>();
|
32
|
+
cache = new HashMap<Integer, CacheEntry>();
|
33
|
+
}
|
34
|
+
|
35
|
+
private Long hashCode(String prefix, String href) {
|
36
|
+
long prefix_hash = prefix.hashCode();
|
37
|
+
long href_hash = href.hashCode();
|
38
|
+
return prefix_hash << 31 | href_hash;
|
39
|
+
}
|
40
|
+
|
41
|
+
public XmlNamespace get(String prefix, String href) {
|
42
|
+
// prefix should not be null.
|
43
|
+
// In case of a default namespace, an empty string should be given to prefix argument.
|
44
|
+
if (prefix == null || href == null) return null;
|
45
|
+
Long hash = hashCode(prefix, href);
|
46
|
+
Integer index = keys.indexOf(hash);
|
47
|
+
if (index != -1) return cache.get(index).namespace;
|
48
|
+
return null;
|
49
|
+
}
|
50
|
+
|
51
|
+
public XmlNamespace getDefault() {
|
52
|
+
return defaultNamespace;
|
53
|
+
}
|
54
|
+
|
55
|
+
public XmlNamespace get(String prefix) {
|
56
|
+
if (prefix == null) return defaultNamespace;
|
57
|
+
long h = prefix.hashCode();
|
58
|
+
Long hash = h << 31;
|
59
|
+
Long mask = 0xFF00L;
|
60
|
+
for (int i=0; i < keys.size(); i++) {
|
61
|
+
if ((keys.get(i) & mask) == hash) {
|
62
|
+
return cache.get(i).namespace;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
return null;
|
66
|
+
}
|
67
|
+
|
68
|
+
public List<XmlNamespace> get(Node node) {
|
69
|
+
List<XmlNamespace> namespaces = new ArrayList<XmlNamespace>();
|
70
|
+
for (int i=0; i < keys.size(); i++) {
|
71
|
+
CacheEntry entry = cache.get(i);
|
72
|
+
if (entry.node == node) {
|
73
|
+
namespaces.add(entry.namespace);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
return namespaces;
|
77
|
+
}
|
78
|
+
|
79
|
+
public XmlNamespace put(Ruby ruby, String prefix, String href, Node node, XmlDocument document) {
|
80
|
+
// prefix should not be null.
|
81
|
+
// In case of a default namespace, an empty string should be given to prefix argument.
|
82
|
+
if (prefix == null || href == null) return null;
|
83
|
+
Long hash = hashCode(prefix, href);
|
84
|
+
Integer index;
|
85
|
+
if ((index = keys.indexOf(hash)) != -1) {
|
86
|
+
return cache.get(index).namespace;
|
87
|
+
} else {
|
88
|
+
keys.add(hash);
|
89
|
+
index = keys.size() - 1;
|
90
|
+
String actualPrefix = (prefix.equals("")) ? null : prefix;
|
91
|
+
XmlNamespace namespace = new XmlNamespace(ruby, actualPrefix, href);
|
92
|
+
namespace.setDocument(document);
|
93
|
+
CacheEntry entry = new CacheEntry(namespace, node);
|
94
|
+
cache.put(index, entry);
|
95
|
+
if ("".equals(prefix)) defaultNamespace = namespace;
|
96
|
+
return namespace;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
public void remove(String prefix, String href) {
|
101
|
+
if (prefix == null || href == null) return;
|
102
|
+
Long hash = hashCode(prefix, href);
|
103
|
+
Integer index = keys.indexOf(hash);
|
104
|
+
if (index != -1) {
|
105
|
+
cache.remove(index);
|
106
|
+
}
|
107
|
+
keys.remove(index);
|
108
|
+
}
|
109
|
+
|
110
|
+
public void clear() {
|
111
|
+
// removes namespace declarations from node
|
112
|
+
for (int i=0; i < keys.size(); i++) {
|
113
|
+
CacheEntry entry = cache.get(i);
|
114
|
+
NamedNodeMap attributes = entry.node.getAttributes();
|
115
|
+
for (int j=0; j<attributes.getLength(); j++) {
|
116
|
+
String name = ((Attr)attributes.item(j)).getName();
|
117
|
+
if (isNamespace(name)) {
|
118
|
+
attributes.removeNamedItem(name);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}
|
122
|
+
keys.clear();
|
123
|
+
cache.clear();
|
124
|
+
defaultNamespace = null;
|
125
|
+
}
|
126
|
+
|
127
|
+
private class CacheEntry {
|
128
|
+
private XmlNamespace namespace;
|
129
|
+
private Node node;
|
130
|
+
|
131
|
+
CacheEntry(XmlNamespace namespace, Node node) {
|
132
|
+
this.namespace = namespace;
|
133
|
+
this.node = node;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
@@ -0,0 +1,80 @@
|
|
1
|
+
package nokogiri.internals;
|
2
|
+
|
3
|
+
import java.util.ArrayList;
|
4
|
+
import java.util.Enumeration;
|
5
|
+
import java.util.Hashtable;
|
6
|
+
import java.util.Iterator;
|
7
|
+
import java.util.List;
|
8
|
+
import java.util.Set;
|
9
|
+
import java.util.Map.Entry;
|
10
|
+
|
11
|
+
import javax.xml.XMLConstants;
|
12
|
+
import javax.xml.namespace.NamespaceContext;
|
13
|
+
|
14
|
+
public class NokogiriNamespaceContext implements NamespaceContext {
|
15
|
+
public static final String NOKOGIRI_PREFIX = "nokogiri";
|
16
|
+
public static final String NOKOGIRI_URI = "http://www.nokogiri.org/default_ns/ruby/extensions_functions";
|
17
|
+
public static final String NOKOGIRI_TEMPORARY_ROOT_TAG = "nokogiri-temporary-root-tag";
|
18
|
+
|
19
|
+
private Hashtable<String,String> register;
|
20
|
+
|
21
|
+
public NokogiriNamespaceContext() {
|
22
|
+
this.register = new Hashtable<String,String>();
|
23
|
+
register.put(NOKOGIRI_PREFIX, NOKOGIRI_URI);
|
24
|
+
register.put("xml", "http://www.w3.org/XML/1998/namespace");
|
25
|
+
register.put("xhtml", "http://www.w3.org/1999/xhtml");
|
26
|
+
}
|
27
|
+
|
28
|
+
public String getNamespaceURI(String prefix) {
|
29
|
+
if (prefix == null) {
|
30
|
+
throw new IllegalArgumentException();
|
31
|
+
}
|
32
|
+
String uri = this.register.get(prefix);
|
33
|
+
if (uri != null) {
|
34
|
+
return uri;
|
35
|
+
}
|
36
|
+
|
37
|
+
if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) {
|
38
|
+
uri = this.register.get(XMLConstants.XMLNS_ATTRIBUTE);
|
39
|
+
return (uri == null) ? XMLConstants.XMLNS_ATTRIBUTE_NS_URI : uri;
|
40
|
+
}
|
41
|
+
|
42
|
+
return XMLConstants.NULL_NS_URI;
|
43
|
+
}
|
44
|
+
|
45
|
+
public String getPrefix(String uri) {
|
46
|
+
if (uri == null) {
|
47
|
+
throw new IllegalArgumentException("uri is null");
|
48
|
+
} else {
|
49
|
+
Set<Entry<String, String>> entries = register.entrySet();
|
50
|
+
for (Entry<String, String> entry : entries) {
|
51
|
+
if (uri.equals(entry.getValue())) {
|
52
|
+
return entry.getKey();
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
return null;
|
57
|
+
}
|
58
|
+
|
59
|
+
public Iterator<String> getPrefixes(String uri) {
|
60
|
+
if (register == null) return null;
|
61
|
+
Set<Entry<String, String>> entries = register.entrySet();
|
62
|
+
List<String> list = new ArrayList<String>();
|
63
|
+
for (Entry<String, String> entry : entries) {
|
64
|
+
if (uri.equals(entry.getValue())) {
|
65
|
+
list.add(entry.getKey());
|
66
|
+
}
|
67
|
+
}
|
68
|
+
return list.iterator();
|
69
|
+
}
|
70
|
+
|
71
|
+
public Set<String> getAllPrefixes() {
|
72
|
+
if (register == null) return null;
|
73
|
+
return register.keySet();
|
74
|
+
}
|
75
|
+
|
76
|
+
public void registerNamespace(String prefix, String uri) {
|
77
|
+
if("xmlns".equals(prefix)) prefix = "";
|
78
|
+
this.register.put(prefix, uri);
|
79
|
+
}
|
80
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
package nokogiri.internals;
|
2
|
+
|
3
|
+
import org.apache.xerces.xni.parser.XMLParseException;
|
4
|
+
import org.xml.sax.SAXException;
|
5
|
+
import org.xml.sax.SAXParseException;
|
6
|
+
|
7
|
+
/**
|
8
|
+
*
|
9
|
+
* @author sergio
|
10
|
+
*/
|
11
|
+
public class NokogiriNonStrictErrorHandler extends NokogiriErrorHandler{
|
12
|
+
|
13
|
+
public void warning(SAXParseException ex) throws SAXException {
|
14
|
+
this.errors.add(ex);
|
15
|
+
}
|
16
|
+
|
17
|
+
public void error(SAXParseException ex) throws SAXException {
|
18
|
+
this.errors.add(ex);
|
19
|
+
}
|
20
|
+
|
21
|
+
public void fatalError(SAXParseException ex) throws SAXException {
|
22
|
+
this.errors.add(ex);
|
23
|
+
}
|
24
|
+
|
25
|
+
public void error(String domain, String key, XMLParseException e) {
|
26
|
+
addError(e);
|
27
|
+
}
|
28
|
+
|
29
|
+
public void fatalError(String domain, String key, XMLParseException e) {
|
30
|
+
addError(e);
|
31
|
+
}
|
32
|
+
|
33
|
+
public void warning(String domain, String key, XMLParseException e) {
|
34
|
+
addError(e);
|
35
|
+
}
|
36
|
+
|
37
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
package nokogiri.internals;
|
2
|
+
|
3
|
+
import org.apache.xerces.xni.parser.XMLParseException;
|
4
|
+
import org.xml.sax.SAXException;
|
5
|
+
import org.xml.sax.SAXParseException;
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Non-strict error handler for NekoHtml.
|
9
|
+
*
|
10
|
+
* NekoHtml adds too many warnings, which makes later processing hard. For example,
|
11
|
+
* Nokogiri wants to know whether number of errors have been increased or not to judge
|
12
|
+
* availability of creating NodeSet from a given fragment. When the fragment nodes
|
13
|
+
* are to be created from HTML document, which means NekoHtml is used, always errors
|
14
|
+
* increases. As a result, even though the given fragment is correct HTML, NodeSet
|
15
|
+
* base on the given fragment won't be created. This is why warnings are eliminated.
|
16
|
+
*
|
17
|
+
* @author Yoko Harada <yokolet@gmail.com>
|
18
|
+
*/
|
19
|
+
public class NokogiriNonStrictErrorHandler4NekoHtml extends NokogiriErrorHandler {
|
20
|
+
private boolean noerror;
|
21
|
+
|
22
|
+
public NokogiriNonStrictErrorHandler4NekoHtml() {
|
23
|
+
this.noerror = false;
|
24
|
+
}
|
25
|
+
|
26
|
+
public NokogiriNonStrictErrorHandler4NekoHtml(boolean noerror) {
|
27
|
+
this.noerror = noerror;
|
28
|
+
}
|
29
|
+
|
30
|
+
public void warning(SAXParseException ex) throws SAXException {
|
31
|
+
//noop. NekoHtml adds too many warnings.
|
32
|
+
}
|
33
|
+
|
34
|
+
public void error(SAXParseException ex) throws SAXException {
|
35
|
+
if (!noerror) this.errors.add(ex);
|
36
|
+
}
|
37
|
+
|
38
|
+
public void fatalError(SAXParseException ex) throws SAXException {
|
39
|
+
this.errors.add(ex);
|
40
|
+
}
|
41
|
+
|
42
|
+
public void error(String domain, String key, XMLParseException e) {
|
43
|
+
if (!noerror) addError(e);
|
44
|
+
}
|
45
|
+
|
46
|
+
public void fatalError(String domain, String key, XMLParseException e) {
|
47
|
+
addError(e);
|
48
|
+
}
|
49
|
+
|
50
|
+
public void warning(String domain, String key, XMLParseException e) {
|
51
|
+
//noop. NekoHtml adds too many warnings.
|
52
|
+
}
|
53
|
+
|
54
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
package nokogiri.internals;
|
2
|
+
|
3
|
+
import java.util.ArrayList;
|
4
|
+
import java.util.List;
|
5
|
+
import org.apache.xerces.xni.parser.XMLParseException;
|
6
|
+
import org.jruby.runtime.ThreadContext;
|
7
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
8
|
+
import org.xml.sax.SAXException;
|
9
|
+
import org.xml.sax.SAXParseException;
|
10
|
+
|
11
|
+
/**
|
12
|
+
*
|
13
|
+
* @author sergio
|
14
|
+
*/
|
15
|
+
public class NokogiriStrictErrorHandler extends NokogiriErrorHandler{
|
16
|
+
|
17
|
+
@Override
|
18
|
+
public List<IRubyObject> getErrorsReadyForRuby(ThreadContext context){
|
19
|
+
return new ArrayList<IRubyObject>();
|
20
|
+
}
|
21
|
+
|
22
|
+
public void warning(SAXParseException spex) throws SAXException {
|
23
|
+
throw spex;
|
24
|
+
}
|
25
|
+
|
26
|
+
public void error(SAXParseException spex) throws SAXException {
|
27
|
+
throw spex;
|
28
|
+
}
|
29
|
+
|
30
|
+
public void fatalError(SAXParseException spex) throws SAXException {
|
31
|
+
throw spex;
|
32
|
+
}
|
33
|
+
|
34
|
+
public void error(String domain, String key, XMLParseException e)
|
35
|
+
throws XMLParseException {
|
36
|
+
throw e;
|
37
|
+
}
|
38
|
+
|
39
|
+
public void fatalError(String domain, String key, XMLParseException e)
|
40
|
+
throws XMLParseException {
|
41
|
+
throw e;
|
42
|
+
}
|
43
|
+
|
44
|
+
public void warning(String domain, String key, XMLParseException e)
|
45
|
+
throws XMLParseException {
|
46
|
+
throw e;
|
47
|
+
}
|
48
|
+
|
49
|
+
}
|
@@ -0,0 +1,88 @@
|
|
1
|
+
package nokogiri.internals;
|
2
|
+
|
3
|
+
import java.util.List;
|
4
|
+
|
5
|
+
import javax.xml.xpath.XPathFunction;
|
6
|
+
import javax.xml.xpath.XPathFunctionException;
|
7
|
+
|
8
|
+
import nokogiri.XmlNode;
|
9
|
+
import nokogiri.XmlNodeSet;
|
10
|
+
|
11
|
+
import org.jruby.Ruby;
|
12
|
+
import org.jruby.RubyArray;
|
13
|
+
import org.jruby.RubyBoolean;
|
14
|
+
import org.jruby.RubyFloat;
|
15
|
+
import org.jruby.RubyString;
|
16
|
+
import org.jruby.javasupport.JavaUtil;
|
17
|
+
import org.jruby.javasupport.util.RuntimeHelpers;
|
18
|
+
import org.jruby.runtime.ThreadContext;
|
19
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
20
|
+
import org.w3c.dom.Node;
|
21
|
+
import org.w3c.dom.NodeList;
|
22
|
+
|
23
|
+
/**
|
24
|
+
*
|
25
|
+
* @author sergio
|
26
|
+
*/
|
27
|
+
public class NokogiriXPathFunction implements XPathFunction {
|
28
|
+
private final IRubyObject handler;
|
29
|
+
private final String name;
|
30
|
+
private final int arity;
|
31
|
+
|
32
|
+
public NokogiriXPathFunction(IRubyObject handler, String name, int arity) {
|
33
|
+
this.handler = handler;
|
34
|
+
this.name = name;
|
35
|
+
this.arity = arity;
|
36
|
+
}
|
37
|
+
|
38
|
+
public Object evaluate(List args) throws XPathFunctionException {
|
39
|
+
if(args.size() != this.arity) {
|
40
|
+
throw new XPathFunctionException("arity does not match");
|
41
|
+
}
|
42
|
+
|
43
|
+
Ruby ruby = this.handler.getRuntime();
|
44
|
+
ThreadContext context = ruby.getCurrentContext();
|
45
|
+
|
46
|
+
IRubyObject result = RuntimeHelpers.invoke(context, this.handler,
|
47
|
+
this.name, fromObjectToRubyArgs(args));
|
48
|
+
|
49
|
+
return fromRubyToObject(result);
|
50
|
+
}
|
51
|
+
|
52
|
+
private IRubyObject[] fromObjectToRubyArgs(List args) {
|
53
|
+
IRubyObject[] newArgs = new IRubyObject[args.size()];
|
54
|
+
for(int i = 0; i < args.size(); i++) {
|
55
|
+
newArgs[i] = fromObjectToRuby(args.get(i));
|
56
|
+
}
|
57
|
+
return newArgs;
|
58
|
+
}
|
59
|
+
|
60
|
+
private IRubyObject fromObjectToRuby(Object o) {
|
61
|
+
// argument object type is one of NodeList, String, Boolean, or Double.
|
62
|
+
Ruby ruby = this.handler.getRuntime();
|
63
|
+
if (o instanceof NodeList) {
|
64
|
+
return new XmlNodeSet(ruby, (NodeList) o);
|
65
|
+
//} else if (o instanceof Node) {
|
66
|
+
// return NokogiriHelpers.getCachedNodeOrCreate(ruby, (Node) o);
|
67
|
+
} else {
|
68
|
+
return JavaUtil.convertJavaToUsableRubyObject(ruby, o);
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
private Object fromRubyToObject(IRubyObject o) {
|
73
|
+
Ruby ruby = this.handler.getRuntime();
|
74
|
+
if(o instanceof RubyString) {
|
75
|
+
return o.toJava(String.class);
|
76
|
+
} else if (o instanceof RubyFloat) {
|
77
|
+
return o.toJava(Double.class);
|
78
|
+
} else if (o instanceof RubyBoolean) {
|
79
|
+
return o.toJava(Boolean.class);
|
80
|
+
} else if (o instanceof XmlNodeSet) {
|
81
|
+
return ((XmlNodeSet) o).toNodeList(ruby);
|
82
|
+
} else if (o instanceof RubyArray) {
|
83
|
+
return (new XmlNodeSet(ruby, (RubyArray) o)).toNodeList(ruby);
|
84
|
+
} else /*if (o instanceof XmlNode)*/ {
|
85
|
+
return ((XmlNode) o).getNode();
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|