nokogiri 1.6.1-java → 1.6.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.

Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +17 -0
  3. data/.travis.yml +6 -6
  4. data/CHANGELOG.ja.rdoc +61 -8
  5. data/CHANGELOG.rdoc +58 -3
  6. data/Gemfile +3 -3
  7. data/Manifest.txt +57 -1
  8. data/README.ja.rdoc +22 -17
  9. data/README.rdoc +23 -18
  10. data/ROADMAP.md +1 -2
  11. data/Rakefile +162 -58
  12. data/build_all +56 -31
  13. data/dependencies.yml +3 -3
  14. data/ext/java/nokogiri/NokogiriService.java +9 -5
  15. data/ext/java/nokogiri/XmlDocument.java +95 -54
  16. data/ext/java/nokogiri/XmlNode.java +93 -42
  17. data/ext/java/nokogiri/XmlReader.java +1 -1
  18. data/ext/java/nokogiri/XmlSaxParserContext.java +33 -0
  19. data/ext/java/nokogiri/XmlSchema.java +4 -2
  20. data/ext/java/nokogiri/XmlXpathContext.java +118 -76
  21. data/ext/java/nokogiri/internals/IgnoreSchemaErrorsErrorHandler.java +20 -0
  22. data/ext/java/nokogiri/internals/NokogiriHandler.java +3 -10
  23. data/ext/java/nokogiri/internals/NokogiriHelpers.java +40 -23
  24. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +59 -54
  25. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +1 -1
  26. data/ext/java/nokogiri/internals/ParserContext.java +1 -4
  27. data/ext/java/nokogiri/internals/SaveContextVisitor.java +6 -2
  28. data/ext/java/nokogiri/internals/c14n/AttrCompare.java +119 -0
  29. data/ext/java/nokogiri/internals/c14n/C14nHelper.java +159 -0
  30. data/ext/java/nokogiri/internals/c14n/CanonicalFilter.java +37 -0
  31. data/ext/java/nokogiri/internals/c14n/CanonicalizationException.java +93 -0
  32. data/ext/java/nokogiri/internals/c14n/Canonicalizer.java +252 -0
  33. data/ext/java/nokogiri/internals/c14n/Canonicalizer11.java +639 -0
  34. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_OmitComments.java +38 -0
  35. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_WithComments.java +38 -0
  36. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315.java +368 -0
  37. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315Excl.java +295 -0
  38. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclOmitComments.java +40 -0
  39. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclWithComments.java +44 -0
  40. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315OmitComments.java +44 -0
  41. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315WithComments.java +43 -0
  42. data/ext/java/nokogiri/internals/c14n/CanonicalizerBase.java +630 -0
  43. data/ext/java/nokogiri/internals/c14n/CanonicalizerPhysical.java +173 -0
  44. data/ext/java/nokogiri/internals/c14n/CanonicalizerSpi.java +76 -0
  45. data/ext/java/nokogiri/internals/c14n/Constants.java +42 -0
  46. data/ext/java/nokogiri/internals/c14n/ElementProxy.java +293 -0
  47. data/ext/java/nokogiri/internals/c14n/HelperNodeList.java +93 -0
  48. data/ext/java/nokogiri/internals/c14n/IgnoreAllErrorHandler.java +79 -0
  49. data/ext/java/nokogiri/internals/c14n/InclusiveNamespaces.java +165 -0
  50. data/ext/java/nokogiri/internals/c14n/InvalidCanonicalizerException.java +76 -0
  51. data/ext/java/nokogiri/internals/c14n/NameSpaceSymbTable.java +402 -0
  52. data/ext/java/nokogiri/internals/c14n/NodeFilter.java +51 -0
  53. data/ext/java/nokogiri/internals/c14n/UtfHelpper.java +179 -0
  54. data/ext/java/nokogiri/internals/c14n/XMLUtils.java +507 -0
  55. data/ext/nokogiri/extconf.rb +429 -128
  56. data/ext/nokogiri/html_document.c +2 -2
  57. data/ext/nokogiri/nokogiri.c +6 -1
  58. data/ext/nokogiri/xml_document.c +5 -4
  59. data/ext/nokogiri/xml_node.c +76 -7
  60. data/ext/nokogiri/xml_reader.c +1 -1
  61. data/ext/nokogiri/xml_sax_parser_context.c +40 -0
  62. data/ext/nokogiri/xml_syntax_error.c +10 -5
  63. data/ext/nokogiri/xml_syntax_error.h +1 -1
  64. data/ext/nokogiri/xml_xpath_context.c +2 -14
  65. data/ext/nokogiri/xslt_stylesheet.c +1 -1
  66. data/lib/nokogiri.rb +31 -22
  67. data/lib/nokogiri/css/node.rb +0 -50
  68. data/lib/nokogiri/css/parser.rb +213 -218
  69. data/lib/nokogiri/css/parser.y +21 -30
  70. data/lib/nokogiri/css/xpath_visitor.rb +62 -14
  71. data/lib/nokogiri/html/document.rb +97 -18
  72. data/lib/nokogiri/html/sax/parser.rb +2 -2
  73. data/lib/nokogiri/nokogiri.jar +0 -0
  74. data/lib/nokogiri/version.rb +1 -1
  75. data/lib/nokogiri/xml/builder.rb +1 -1
  76. data/lib/nokogiri/xml/document.rb +2 -2
  77. data/lib/nokogiri/xml/dtd.rb +10 -0
  78. data/lib/nokogiri/xml/node.rb +26 -1
  79. data/lib/nokogiri/xml/sax/parser.rb +1 -1
  80. data/ports/patches/libxml2/0001-Fix-parser-local-buffers-size-problems.patch +265 -0
  81. data/ports/patches/libxml2/0002-Fix-entities-local-buffers-size-problems.patch +102 -0
  82. data/ports/patches/libxml2/0003-Fix-an-error-in-previous-commit.patch +26 -0
  83. data/ports/patches/libxml2/0004-Fix-potential-out-of-bound-access.patch +26 -0
  84. data/ports/patches/libxml2/0005-Detect-excessive-entities-expansion-upon-replacement.patch +158 -0
  85. data/ports/patches/libxml2/0006-Do-not-fetch-external-parsed-entities.patch +78 -0
  86. data/ports/patches/libxml2/0007-Enforce-XML_PARSER_EOF-state-handling-through-the-pa.patch +480 -0
  87. data/ports/patches/libxml2/0008-Improve-handling-of-xmlStopParser.patch +315 -0
  88. data/ports/patches/libxml2/0009-Fix-a-couple-of-return-without-value.patch +37 -0
  89. data/ports/patches/libxslt/0001-Adding-doc-update-related-to-1.1.28.patch +222 -0
  90. data/ports/patches/libxslt/0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch +53 -0
  91. data/ports/patches/libxslt/0003-Initialize-pseudo-random-number-generator-with-curre.patch +60 -0
  92. data/ports/patches/libxslt/0004-EXSLT-function-str-replace-is-broken-as-is.patch +42 -0
  93. data/ports/patches/libxslt/0006-Fix-str-padding-to-work-with-UTF-8-strings.patch +164 -0
  94. data/ports/patches/libxslt/0007-Separate-function-for-predicate-matching-in-patterns.patch +587 -0
  95. data/ports/patches/libxslt/0008-Fix-direct-pattern-matching.patch +80 -0
  96. data/ports/patches/libxslt/0009-Fix-certain-patterns-with-predicates.patch +185 -0
  97. data/ports/patches/libxslt/0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch +126 -0
  98. data/ports/patches/libxslt/0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch +25 -0
  99. data/ports/patches/libxslt/0014-Fix-for-bug-436589.patch +43 -0
  100. data/ports/patches/libxslt/0015-Fix-mkdir-for-mingw.patch +41 -0
  101. data/suppressions/README.txt +1 -0
  102. data/suppressions/nokogiri_ree-1.8.7.358.supp +61 -0
  103. data/suppressions/nokogiri_ruby-1.8.7.370.supp +0 -0
  104. data/suppressions/nokogiri_ruby-1.9.2.320.supp +28 -0
  105. data/suppressions/nokogiri_ruby-1.9.3.327.supp +28 -0
  106. data/test/css/test_nthiness.rb +65 -2
  107. data/test/css/test_parser.rb +27 -10
  108. data/test/css/test_tokenizer.rb +1 -1
  109. data/test/css/test_xpath_visitor.rb +6 -1
  110. data/test/files/atom.xml +344 -0
  111. data/test/files/shift_jis_no_charset.html +9 -0
  112. data/test/helper.rb +10 -0
  113. data/test/html/test_document.rb +74 -7
  114. data/test/html/test_document_encoding.rb +10 -0
  115. data/test/html/test_document_fragment.rb +9 -3
  116. data/test/namespaces/test_namespaces_aliased_default.rb +24 -0
  117. data/test/namespaces/test_namespaces_in_cloned_doc.rb +31 -0
  118. data/test/namespaces/test_namespaces_preservation.rb +31 -0
  119. data/test/test_nokogiri.rb +6 -0
  120. data/test/test_reader.rb +7 -4
  121. data/test/test_xslt_transforms.rb +25 -0
  122. data/test/xml/sax/test_parser.rb +16 -0
  123. data/test/xml/sax/test_parser_context.rb +9 -0
  124. data/test/xml/test_builder.rb +9 -0
  125. data/test/xml/test_c14n.rb +12 -2
  126. data/test/xml/test_document.rb +66 -0
  127. data/test/xml/test_document_fragment.rb +5 -0
  128. data/test/xml/test_dtd.rb +84 -0
  129. data/test/xml/test_entity_reference.rb +3 -3
  130. data/test/xml/test_node.rb +21 -3
  131. data/test/xml/test_node_attributes.rb +17 -0
  132. data/test/xml/test_schema.rb +26 -0
  133. data/test/xml/test_text.rb +15 -0
  134. data/test/xml/test_xpath.rb +87 -0
  135. data/test_all +3 -3
  136. metadata +119 -68
  137. data/tasks/cross_compile.rb +0 -134
@@ -244,7 +244,7 @@ public class XmlReader extends RubyObject {
244
244
  // use the default options RECOVER | NONET
245
245
  options = new ParserContext.Options(2048 | 1);
246
246
  }
247
- IRubyObject stringIO = NokogiriService.nokogiriClassCache.get("StringIO").newInstance(context, args[0], Block.NULL_BLOCK);
247
+ IRubyObject stringIO = NokogiriService.getNokogiriClassCache(context.getRuntime()).get("StringIO").newInstance(context, args[0], Block.NULL_BLOCK);
248
248
  InputStream in = new UncloseableInputStream(new IOInputStream(stringIO));
249
249
  reader.setInput(context, in, url, options);
250
250
  return reader;
@@ -75,11 +75,14 @@ public class XmlSaxParserContext extends ParserContext {
75
75
  "http://xml.org/sax/features/namespace-prefixes";
76
76
  protected static final String FEATURE_LOAD_EXTERNAL_DTD =
77
77
  "http://apache.org/xml/features/nonvalidating/load-external-dtd";
78
+ protected static final String FEATURE_CONTINUE_AFTER_FATAL_ERROR =
79
+ "http://apache.org/xml/features/continue-after-fatal-error";
78
80
 
79
81
  protected AbstractSAXParser parser;
80
82
 
81
83
  protected NokogiriHandler handler = null;
82
84
  private IRubyObject replaceEntities;
85
+ private IRubyObject recovery;
83
86
 
84
87
  public XmlSaxParserContext(final Ruby ruby, RubyClass rubyClass) {
85
88
  super(ruby, rubyClass);
@@ -87,6 +90,7 @@ public class XmlSaxParserContext extends ParserContext {
87
90
 
88
91
  protected void initialize(Ruby runtime) {
89
92
  replaceEntities = runtime.getTrue();
93
+ recovery = runtime.getFalse();
90
94
  try {
91
95
  parser = createParser();
92
96
  } catch (SAXException se) {
@@ -199,6 +203,13 @@ public class XmlSaxParserContext extends ParserContext {
199
203
  IRubyObject handlerRuby,
200
204
  NokogiriHandler handler) {
201
205
  ((XmlSaxParser) parser).setXmlDeclHandler(handler);
206
+ if(recovery.isTrue()) {
207
+ try {
208
+ ((XmlSaxParser) parser).setFeature(FEATURE_CONTINUE_AFTER_FATAL_ERROR, true);
209
+ } catch(Exception e) {
210
+ throw RaiseException.createNativeRaiseException(context.getRuntime(), e);
211
+ }
212
+ }
202
213
  }
203
214
 
204
215
  protected void postParse(ThreadContext context,
@@ -290,6 +301,28 @@ public class XmlSaxParserContext extends ParserContext {
290
301
  return replaceEntities;
291
302
  }
292
303
 
304
+ /**
305
+ * Can take a boolean assignment.
306
+ *
307
+ * @param context
308
+ * @param value
309
+ * @return
310
+ */
311
+ @JRubyMethod(name = "recovery=")
312
+ public IRubyObject set_recovery(ThreadContext context,
313
+ IRubyObject value) {
314
+ if (!value.isTrue()) recovery = context.getRuntime().getFalse();
315
+ else recovery = context.getRuntime().getTrue();
316
+
317
+ return this;
318
+ }
319
+
320
+ @JRubyMethod(name="recovery")
321
+ public IRubyObject get_recovery(ThreadContext context) {
322
+ return recovery;
323
+ }
324
+
325
+
293
326
 
294
327
  /**
295
328
  * If the handler's document is a FragmentHandler, attempt to trim
@@ -32,8 +32,8 @@
32
32
 
33
33
  package nokogiri;
34
34
 
35
- import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
36
35
  import static nokogiri.internals.NokogiriHelpers.adjustSystemIdIfNecessary;
36
+ import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
37
37
 
38
38
  import java.io.IOException;
39
39
  import java.io.InputStream;
@@ -48,6 +48,7 @@ import javax.xml.validation.Schema;
48
48
  import javax.xml.validation.SchemaFactory;
49
49
  import javax.xml.validation.Validator;
50
50
 
51
+ import nokogiri.internals.IgnoreSchemaErrorsErrorHandler;
51
52
  import nokogiri.internals.SchemaErrorHandler;
52
53
  import nokogiri.internals.XmlDomParserContext;
53
54
 
@@ -95,7 +96,8 @@ public class XmlSchema extends RubyObject {
95
96
  private Schema getSchema(Source source, String currentDir, String scriptFileName) throws SAXException {
96
97
  SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
97
98
  SchemaResourceResolver resourceResolver = new SchemaResourceResolver(currentDir, scriptFileName, null);
98
- schemaFactory.setResourceResolver(resourceResolver);
99
+ schemaFactory.setResourceResolver(resourceResolver);
100
+ schemaFactory.setErrorHandler(new IgnoreSchemaErrorsErrorHandler());
99
101
  return schemaFactory.newSchema(source);
100
102
  }
101
103
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2012:
4
+ * Copyright (c) 2008 - 2014:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -34,13 +34,11 @@ package nokogiri;
34
34
 
35
35
  import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
36
36
 
37
+ import java.lang.reflect.Constructor;
38
+ import java.lang.reflect.InvocationTargetException;
37
39
  import java.util.Set;
38
- import java.util.regex.Matcher;
39
- import java.util.regex.Pattern;
40
40
 
41
- import javax.xml.xpath.XPath;
42
- import javax.xml.xpath.XPathConstants;
43
- import javax.xml.xpath.XPathExpression;
41
+ import javax.xml.transform.TransformerException;
44
42
  import javax.xml.xpath.XPathExpressionException;
45
43
  import javax.xml.xpath.XPathFactory;
46
44
 
@@ -49,40 +47,82 @@ import nokogiri.internals.NokogiriXPathFunctionResolver;
49
47
  import nokogiri.internals.NokogiriXPathVariableResolver;
50
48
 
51
49
  import org.jruby.Ruby;
52
- import org.jruby.RubyBoolean;
53
50
  import org.jruby.RubyClass;
54
51
  import org.jruby.RubyException;
55
- import org.jruby.RubyFloat;
56
52
  import org.jruby.RubyObject;
57
- import org.jruby.RubyString;
58
53
  import org.jruby.anno.JRubyClass;
59
54
  import org.jruby.anno.JRubyMethod;
60
55
  import org.jruby.exceptions.RaiseException;
61
56
  import org.jruby.runtime.ThreadContext;
62
57
  import org.jruby.runtime.builtin.IRubyObject;
58
+ import org.w3c.dom.Node;
63
59
  import org.w3c.dom.NodeList;
64
60
 
61
+ import com.sun.org.apache.xml.internal.dtm.DTM;
62
+ import com.sun.org.apache.xml.internal.utils.PrefixResolver;
63
+ import com.sun.org.apache.xpath.internal.XPathContext;
64
+ import com.sun.org.apache.xpath.internal.jaxp.JAXPExtensionsProvider;
65
+ import com.sun.org.apache.xpath.internal.jaxp.JAXPPrefixResolver;
66
+ import com.sun.org.apache.xpath.internal.jaxp.JAXPVariableStack;
67
+ import com.sun.org.apache.xpath.internal.objects.XObject;
68
+
65
69
  /**
66
70
  * Class for Nokogiri::XML::XpathContext
67
71
  *
68
72
  * @author sergio
69
73
  * @author Yoko Harada <yokolet@gmail.com>
74
+ * @author John Shahid <jvshahid@gmail.com>
70
75
  */
71
76
  @JRubyClass(name="Nokogiri::XML::XPathContext")
72
77
  public class XmlXpathContext extends RubyObject {
78
+ public final static String XPATH_CONTEXT = "CACHCED_XPATH_CONTEXT";
79
+
73
80
  private XmlNode context;
74
- private XPath xpath;
75
-
81
+ private final NokogiriXPathFunctionResolver functionResolver;
82
+ private final NokogiriXPathVariableResolver variableResolver;
83
+ private PrefixResolver prefixResolver;
84
+ private XPathContext xpathSupport = null;
85
+ private NokogiriNamespaceContext nsContext;
86
+
76
87
  public XmlXpathContext(Ruby ruby, RubyClass rubyClass) {
77
88
  super(ruby, rubyClass);
89
+ functionResolver = NokogiriXPathFunctionResolver.create(ruby.getCurrentContext().nil);
90
+ variableResolver = NokogiriXPathVariableResolver.create();
78
91
  }
79
-
80
- public void setNode(XmlNode node) {
92
+
93
+ private void setNode(XmlNode node) throws IllegalArgumentException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
94
+ Node doc = node.getNode().getOwnerDocument();
95
+ if (doc == null) {
96
+ doc = node.getNode();
97
+ }
98
+ xpathSupport = (XPathContext) doc.getUserData(XPATH_CONTEXT);
99
+
100
+ if (xpathSupport == null) {
101
+ JAXPExtensionsProvider jep = getProviderInstance();
102
+ xpathSupport = new XPathContext(jep);
103
+ xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
104
+ doc.setUserData(XPATH_CONTEXT, xpathSupport, null);
105
+ }
106
+
81
107
  context = node;
82
- xpath.setNamespaceContext(NokogiriNamespaceContext.create());
83
- xpath.setXPathVariableResolver(NokogiriXPathVariableResolver.create());
108
+ nsContext = NokogiriNamespaceContext.create();
109
+ prefixResolver = new JAXPPrefixResolver(nsContext);
110
+ }
111
+
112
+ private JAXPExtensionsProvider getProviderInstance() throws ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
113
+ Class<?> clazz = Class.forName("com.sun.org.apache.xpath.internal.jaxp.JAXPExtensionsProvider");
114
+ Constructor[] constructors = clazz.getDeclaredConstructors();
115
+ for (int i = 0; i < constructors.length; i++) {
116
+ Class[] parameterTypes = constructors[i].getParameterTypes();
117
+ if (parameterTypes.length == 2) {
118
+ return (JAXPExtensionsProvider) constructors[i].newInstance(functionResolver, false);
119
+ } else if (parameterTypes.length == 1) {
120
+ return (JAXPExtensionsProvider) constructors[i].newInstance(functionResolver);
121
+ }
122
+ }
123
+ return null;
84
124
  }
85
-
125
+
86
126
  /**
87
127
  * Create and return a copy of this object.
88
128
  *
@@ -97,83 +137,86 @@ public class XmlXpathContext extends RubyObject {
97
137
  public static IRubyObject rbNew(ThreadContext thread_context, IRubyObject klazz, IRubyObject node) {
98
138
  XmlNode xmlNode = (XmlNode)node;
99
139
  XmlXpathContext xmlXpathContext = (XmlXpathContext) NokogiriService.XML_XPATHCONTEXT_ALLOCATOR.allocate(thread_context.getRuntime(), (RubyClass)klazz);
100
- xmlXpathContext.xpath = XPathFactory.newInstance().newXPath();
101
- xmlXpathContext.setNode(xmlNode);
140
+ XPathFactory.newInstance().newXPath();
141
+ try {
142
+ xmlXpathContext.setNode(xmlNode);
143
+ } catch (IllegalArgumentException e) {
144
+ throw thread_context.getRuntime().newRuntimeError(e.getMessage());
145
+ } catch (ClassNotFoundException e) {
146
+ throw thread_context.getRuntime().newRuntimeError(e.getMessage());
147
+ } catch (InstantiationException e) {
148
+ throw thread_context.getRuntime().newRuntimeError(e.getMessage());
149
+ } catch (IllegalAccessException e) {
150
+ throw thread_context.getRuntime().newRuntimeError(e.getMessage());
151
+ } catch (InvocationTargetException e) {
152
+ throw thread_context.getRuntime().newRuntimeError(e.getMessage());
153
+ }
102
154
  return xmlXpathContext;
103
155
  }
104
156
 
105
157
  @JRubyMethod
106
158
  public IRubyObject evaluate(ThreadContext thread_context, IRubyObject expr, IRubyObject handler) {
159
+ functionResolver.setHandler(handler);
107
160
  String src = (String) expr.toJava(String.class);
108
- try {
109
- if(!handler.isNil()) {
110
- if (!isContainsPrefix(src)) {
111
- Set<String> methodNames = handler.getMetaClass().getMethods().keySet();
112
- for (String name : methodNames) {
113
- src = src.replaceAll(name, NokogiriNamespaceContext.NOKOGIRI_PREFIX+":"+name);
114
- }
161
+ if(!handler.isNil()) {
162
+ if (!isContainsPrefix(src)) {
163
+ Set<String> methodNames = handler.getMetaClass().getMethods().keySet();
164
+ for (String name : methodNames) {
165
+ src = src.replaceAll(name, NokogiriNamespaceContext.NOKOGIRI_PREFIX+":"+name);
115
166
  }
116
- xpath.setXPathFunctionResolver(NokogiriXPathFunctionResolver.create(handler));
117
167
  }
118
- XPathExpression xpathExpression = xpath.compile(src);
119
- return node_set(thread_context, xpathExpression);
120
- } catch (XPathExpressionException xpee) {
121
- xpee = new XPathExpressionException(src);
122
- RubyException e = XmlSyntaxError.createXPathSyntaxError(getRuntime(), xpee);
123
- throw new RaiseException(e);
124
168
  }
169
+ return node_set(thread_context, src);
125
170
  }
126
171
 
127
- protected IRubyObject node_set(ThreadContext thread_context, XPathExpression xpathExpression) {
128
- XmlNodeSet result = null;
129
- try {
130
- result = tryGetNodeSet(thread_context, xpathExpression);
131
- return result;
172
+ protected IRubyObject node_set(ThreadContext thread_context, String expr) {
173
+ try {
174
+ return tryGetNodeSet(thread_context, expr);
132
175
  } catch (XPathExpressionException xpee) {
133
- try {
134
- return tryGetOpaqueValue(xpathExpression);
135
- } catch (XPathExpressionException xpee_opaque) {
136
- RubyException e = XmlSyntaxError.createXPathSyntaxError(getRuntime(), xpee_opaque);
137
- throw new RaiseException(e);
138
- }
176
+ RubyException e = XmlSyntaxError.createXPathSyntaxError(getRuntime(), xpee);
177
+ throw new RaiseException(e);
139
178
  }
140
179
  }
141
-
142
- private XmlNodeSet tryGetNodeSet(ThreadContext thread_context, XPathExpression xpathExpression) throws XPathExpressionException {
143
- NodeList nodeList = (NodeList)xpathExpression.evaluate(context.node, XPathConstants.NODESET);
144
- XmlNodeSet xmlNodeSet = (XmlNodeSet) NokogiriService.XML_NODESET_ALLOCATOR.allocate(getRuntime(), getNokogiriClass(getRuntime(), "Nokogiri::XML::NodeSet"));
145
- xmlNodeSet.setNodeList(nodeList);
146
- xmlNodeSet.initialize(thread_context.getRuntime(), context);
147
- return xmlNodeSet;
148
- }
149
180
 
150
- private static Pattern boolean_pattern = Pattern.compile("true|false");
151
-
152
- private IRubyObject tryGetOpaqueValue(XPathExpression xpathExpression) throws XPathExpressionException {
153
- String string = (String)xpathExpression.evaluate(context.node, XPathConstants.STRING);
154
- Double value = null;
155
- if ((value = getDoubleValue(string)) != null) {
156
- return new RubyFloat(getRuntime(), value);
157
- }
158
- if (doesMatch(boolean_pattern, string.toLowerCase())) return RubyBoolean.newBoolean(getRuntime(), Boolean.parseBoolean(string));
159
- return RubyString.newString(getRuntime(), string);
160
- }
161
-
162
- private Double getDoubleValue(String value) {
181
+ private IRubyObject tryGetNodeSet(ThreadContext thread_context, String expr) throws XPathExpressionException {
182
+ XObject xobj = null;
183
+
184
+ Node contextNode = context.node;
185
+
163
186
  try {
164
- return Double.valueOf(value);
165
- } catch (NumberFormatException e) {
166
- return null;
187
+ com.sun.org.apache.xpath.internal.XPath xpathInternal = new com.sun.org.apache.xpath.internal.XPath (expr, null,
188
+ prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT );
189
+
190
+ // We always need to have a ContextNode with Xalan XPath implementation
191
+ // To allow simple expression evaluation like 1+1 we are setting
192
+ // dummy Document as Context Node
193
+
194
+ if ( contextNode == null )
195
+ xobj = xpathInternal.execute(xpathSupport, DTM.NULL, prefixResolver);
196
+ else
197
+ xobj = xpathInternal.execute(xpathSupport, contextNode, prefixResolver);
198
+
199
+ switch (xobj.getType()) {
200
+ case XObject.CLASS_BOOLEAN:
201
+ return thread_context.getRuntime().newBoolean(xobj.bool());
202
+ case XObject.CLASS_NUMBER:
203
+ return thread_context.getRuntime().newFloat(xobj.num());
204
+ case XObject.CLASS_NODESET:
205
+ NodeList nodeList = xobj.nodelist();
206
+ XmlNodeSet xmlNodeSet = (XmlNodeSet) NokogiriService.XML_NODESET_ALLOCATOR.allocate(getRuntime(), getNokogiriClass(getRuntime(), "Nokogiri::XML::NodeSet"));
207
+ xmlNodeSet.setNodeList(nodeList);
208
+ xmlNodeSet.initialize(thread_context.getRuntime(), context);
209
+ return xmlNodeSet;
210
+ default:
211
+ return thread_context.getRuntime().newString(xobj.str());
212
+ }
213
+ } catch(TransformerException ex) {
214
+ throw new XPathExpressionException(expr);
167
215
  }
168
216
  }
169
-
170
- private boolean doesMatch(Pattern pattern, String string) {
171
- Matcher m = pattern.matcher(string);
172
- return m.matches();
173
- }
174
217
 
175
218
  private boolean isContainsPrefix(String str) {
176
- Set<String> prefixes = ((NokogiriNamespaceContext)xpath.getNamespaceContext()).getAllPrefixes();
219
+ Set<String> prefixes = nsContext.getAllPrefixes();
177
220
  for (String prefix : prefixes) {
178
221
  if (str.contains(prefix + ":")) {
179
222
  return true;
@@ -190,14 +233,13 @@ public class XmlXpathContext extends RubyObject {
190
233
 
191
234
  @JRubyMethod
192
235
  public IRubyObject register_ns(ThreadContext context, IRubyObject prefix, IRubyObject uri) {
193
- ((NokogiriNamespaceContext) xpath.getNamespaceContext()).registerNamespace((String)prefix.toJava(String.class), (String)uri.toJava(String.class));
236
+ nsContext.registerNamespace((String)prefix.toJava(String.class), (String)uri.toJava(String.class));
194
237
  return this;
195
238
  }
196
239
 
197
240
  @JRubyMethod
198
241
  public IRubyObject register_variable(ThreadContext context, IRubyObject name, IRubyObject value) {
199
- ((NokogiriXPathVariableResolver) xpath.getXPathVariableResolver()).
200
- registerVariable((String)name.toJava(String.class), (String)value.toJava(String.class));
242
+ variableResolver.registerVariable((String)name.toJava(String.class), (String)value.toJava(String.class));
201
243
  return this;
202
244
  }
203
245
  }
@@ -0,0 +1,20 @@
1
+ package nokogiri.internals;
2
+
3
+ import org.xml.sax.ErrorHandler;
4
+ import org.xml.sax.SAXException;
5
+ import org.xml.sax.SAXParseException;
6
+
7
+ public class IgnoreSchemaErrorsErrorHandler implements ErrorHandler {
8
+
9
+ @Override
10
+ public void warning(SAXParseException exception) throws SAXException {
11
+ }
12
+
13
+ @Override
14
+ public void error(SAXParseException exception) throws SAXException {
15
+ }
16
+
17
+ @Override
18
+ public void fatalError(SAXParseException exception) throws SAXException {
19
+ }
20
+ }
@@ -76,8 +76,6 @@ public class NokogiriHandler extends DefaultHandler2 implements XmlDeclHandler {
76
76
  private final LinkedList<XmlSyntaxError> errors = new LinkedList<XmlSyntaxError>();
77
77
 
78
78
  private Locator locator;
79
- private final ArrayDeque<Integer> lines;
80
- private final ArrayDeque<Integer> columns;
81
79
  private static String htmlParserName = "Nokogiri::HTML::SAX::Parser";
82
80
  private boolean needEmptyAttrCheck = false;
83
81
 
@@ -85,8 +83,6 @@ public class NokogiriHandler extends DefaultHandler2 implements XmlDeclHandler {
85
83
  this.ruby = runtime;
86
84
  this.attrClass = (RubyClass) runtime.getClassFromPath("Nokogiri::XML::SAX::Parser::Attribute");
87
85
  this.object = object;
88
- lines = new ArrayDeque<Integer>();
89
- columns = new ArrayDeque<Integer>();
90
86
  String objectName = object.getMetaClass().getName();
91
87
  if (htmlParserName.equals(objectName)) needEmptyAttrCheck = true;
92
88
  }
@@ -141,10 +137,7 @@ public class NokogiriHandler extends DefaultHandler2 implements XmlDeclHandler {
141
137
 
142
138
  ThreadContext context = ruby.getCurrentContext();
143
139
  boolean fromFragmentHandler = false; // isFromFragmentHandler();
144
-
145
- lines.add(locator.getLineNumber());
146
- columns.add(locator.getColumnNumber() - 1); // libxml counts from 0 while java does from 1
147
-
140
+
148
141
  for (int i = 0; i < attrs.getLength(); i++) {
149
142
  String u = attrs.getURI(i);
150
143
  String qn = attrs.getQName(i);
@@ -208,11 +201,11 @@ public class NokogiriHandler extends DefaultHandler2 implements XmlDeclHandler {
208
201
  }
209
202
 
210
203
  public Integer getLine() {
211
- return lines.pop();
204
+ return locator.getLineNumber();
212
205
  }
213
206
 
214
207
  public Integer getColumn() {
215
- return columns.pop();
208
+ return locator.getColumnNumber() - 1;
216
209
  }
217
210
 
218
211
  private boolean isFromFragmentHandler() {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * (The MIT License)
3
3
  *
4
- * Copyright (c) 2008 - 2012:
4
+ * Copyright (c) 2008 - 2014:
5
5
  *
6
6
  * * {Aaron Patterson}[http://tenderlovemaking.com]
7
7
  * * {Mike Dalessio}[http://mike.daless.io]
@@ -60,6 +60,7 @@ import nokogiri.XmlNamespace;
60
60
  import nokogiri.XmlNode;
61
61
  import nokogiri.XmlProcessingInstruction;
62
62
  import nokogiri.XmlText;
63
+ import nokogiri.XmlXpathContext;
63
64
 
64
65
  import org.jcodings.specific.UTF8Encoding;
65
66
  import org.jruby.Ruby;
@@ -93,6 +94,20 @@ public class NokogiriHelpers {
93
94
  return (XmlNode) node.getUserData(CACHED_NODE);
94
95
  }
95
96
 
97
+ public static void clearCachedNode(Node node) {
98
+ node.setUserData(CACHED_NODE, null, null);
99
+ }
100
+
101
+ public static void clearXpathContext(Node node) {
102
+ if (node == null) return;
103
+
104
+ Node ownerDocument = node.getOwnerDocument();
105
+ if (ownerDocument == null) {
106
+ ownerDocument = node;
107
+ }
108
+ ownerDocument.setUserData(XmlXpathContext.XPATH_CONTEXT, null, null);
109
+ }
110
+
96
111
  /**
97
112
  * Get the XmlNode associated with the underlying
98
113
  * <code>node</code>. Creates a new XmlNode (or appropriate subclass)
@@ -175,7 +190,7 @@ public class NokogiriHelpers {
175
190
  }
176
191
 
177
192
  public static RubyClass getNokogiriClass(Ruby ruby, String name) {
178
- return NokogiriService.nokogiriClassCache.get(name);
193
+ return NokogiriService.getNokogiriClassCache(ruby).get(name);
179
194
  }
180
195
 
181
196
  public static IRubyObject stringOrNil(Ruby runtime, String s) {
@@ -542,7 +557,7 @@ public class NokogiriHelpers {
542
557
  private static Pattern decoded_pattern = Pattern.compile("&|>|<|\r");
543
558
  private static String[] encoded = {"&amp;", "&gt;", "&lt;", "&#13;"};
544
559
  private static String[] decoded = {"&", ">", "<", "\r"};
545
-
560
+
546
561
  private static String convert(Pattern ptn, String input, String[] oldChars, String[] newChars) {
547
562
  Matcher matcher = ptn.matcher(input);
548
563
  boolean result = matcher.find();
@@ -562,11 +577,11 @@ public class NokogiriHelpers {
562
577
  matcher.appendTail(sb);
563
578
  return sb.toString();
564
579
  }
565
-
580
+
566
581
  public static String encodeJavaString(String s) {
567
582
  return convert(decoded_pattern, s, decoded, encoded);
568
583
  }
569
-
584
+
570
585
  public static String decodeJavaString(String s) {
571
586
  return convert(encoded_pattern, s, encoded, decoded);
572
587
  }
@@ -602,7 +617,7 @@ public class NokogiriHelpers {
602
617
  public static boolean isXmlBase(String attrName) {
603
618
  return "xml:base".equals(attrName) || "xlink:href".equals(attrName);
604
619
  }
605
-
620
+
606
621
  public static boolean isWhitespaceText(ThreadContext context, IRubyObject obj) {
607
622
  if (obj == null || obj.isNil()) return false;
608
623
 
@@ -613,11 +628,11 @@ public class NokogiriHelpers {
613
628
  String content = rubyStringToString(node.content(context));
614
629
  return content.trim().length() == 0;
615
630
  }
616
-
631
+
617
632
  public static boolean isWhitespaceText(String s) {
618
633
  return s.trim().length() == 0;
619
634
  }
620
-
635
+
621
636
  public static String canonicalizeWhitespce(String s) {
622
637
  StringBuilder sb = new StringBuilder();
623
638
  char[] chars = s.toCharArray();
@@ -648,14 +663,14 @@ public class NokogiriHelpers {
648
663
  RubyArray array = RubyArray.newArray(ruby, nodes.getLength());
649
664
  return nodeListToRubyArray(ruby, nodes, array);
650
665
  }
651
-
666
+
652
667
  public static RubyArray nodeListToRubyArray(Ruby ruby, NodeList nodes, RubyArray array) {
653
668
  for(int i = 0; i < nodes.getLength(); i++) {
654
669
  array.append(NokogiriHelpers.getCachedNodeOrCreate(ruby, nodes.item(i)));
655
670
  }
656
671
  return array;
657
672
  }
658
-
673
+
659
674
  public static RubyArray nodeArrayToRubyArray(Ruby ruby, Node[] nodes) {
660
675
  RubyArray n = RubyArray.newArray(ruby, nodes.length);
661
676
  for(int i = 0; i < nodes.length; i++) {
@@ -663,7 +678,7 @@ public class NokogiriHelpers {
663
678
  }
664
679
  return n;
665
680
  }
666
-
681
+
667
682
  public static RubyArray namedNodeMapToRubyArray(Ruby ruby, NamedNodeMap map) {
668
683
  RubyArray n = RubyArray.newArray(ruby, map.getLength());
669
684
  for(int i = 0; i < map.getLength(); i++) {
@@ -671,7 +686,7 @@ public class NokogiriHelpers {
671
686
  }
672
687
  return n;
673
688
  }
674
-
689
+
675
690
  public static String getValidEncoding(Ruby runtime, IRubyObject encoding) {
676
691
  if (encoding.isNil()) {
677
692
  return guessEncoding();
@@ -679,7 +694,7 @@ public class NokogiriHelpers {
679
694
  return ignoreInvalidEncoding(runtime, encoding);
680
695
  }
681
696
  }
682
-
697
+
683
698
  private static String guessEncoding() {
684
699
  String name = null;
685
700
  if (name == null) name = System.getProperty("file.encoding");
@@ -694,7 +709,7 @@ public class NokogiriHelpers {
694
709
  if (charsetNames.contains(givenEncoding)) return givenEncoding;
695
710
  else return guessEncoding();
696
711
  }
697
-
712
+
698
713
  public static String adjustSystemIdIfNecessary(String currentDir, String scriptFileName, String baseURI, String systemId) {
699
714
  if (systemId == null) return systemId;
700
715
  File file = new File(systemId);
@@ -705,7 +720,7 @@ public class NokogiriHelpers {
705
720
  if (path != null) return path;
706
721
  return resolveSystemId(scriptFileName, systemId);
707
722
  }
708
-
723
+
709
724
  private static String resolveSystemId(String baseName, String systemId) {
710
725
  if (baseName == null || baseName.length() < 1) return null;
711
726
  String parentName = null;
@@ -719,13 +734,13 @@ public class NokogiriHelpers {
719
734
  if (dtdFile.exists()) return dtdFile.getPath();
720
735
  return null;
721
736
  }
722
-
737
+
723
738
  public static boolean isUTF8(String encoding) {
724
739
  if (encoding == null) return true; // no need to convert encoding
725
740
  int ret = Charset.forName(encoding).compareTo(Charset.forName("UTF-8"));
726
741
  return ret == 0;
727
742
  }
728
-
743
+
729
744
  public static byte[] convertEncoding(Charset output_charset, String input_string) throws CharacterCodingException {
730
745
  CharsetEncoder encoder = output_charset.newEncoder();
731
746
  CharBuffer charBuffer = CharBuffer.wrap(input_string);
@@ -746,7 +761,6 @@ public class NokogiriHelpers {
746
761
  } else {
747
762
  return NokogiriHelpers.nkf(runtime, ruby_encoding, thing);
748
763
  }
749
-
750
764
  }
751
765
 
752
766
  // This method is used from HTML documents. HTML meta tag with encoding specification
@@ -775,7 +789,7 @@ public class NokogiriHelpers {
775
789
  } catch (ClassNotFoundException e1) {
776
790
  try {
777
791
  // Before JRuby 1.7
778
- nkfClass = runtime.getClassLoader().loadClass("org.jruby.RubyNKF");
792
+ nkfClass = runtime.getClassLoader().loadClass("org.jruby.RubyNKF");
779
793
  } catch (ClassNotFoundException e2) {
780
794
  return thing;
781
795
  }
@@ -798,7 +812,7 @@ public class NokogiriHelpers {
798
812
  return thing;
799
813
  }
800
814
  }
801
-
815
+
802
816
  private static Charset shift_jis = Charset.forName("Shift_JIS");
803
817
  private static Charset jis = Charset.forName("ISO-2022-JP");
804
818
  private static Charset euc_jp = Charset.forName("EUC-JP");
@@ -812,11 +826,14 @@ public class NokogiriHelpers {
812
826
  return !shouldEncode(text);
813
827
  }
814
828
 
829
+ public static NokogiriNamespaceCache getNamespaceCacheFormNode(Node n) {
830
+ XmlDocument xmlDoc = (XmlDocument)getCachedNode(n.getOwnerDocument());
831
+ return xmlDoc.getNamespaceCache();
832
+ }
833
+
815
834
  public static Node renameNode(Node n, String namespaceURI, String qualifiedName) throws DOMException {
816
835
  Document doc = n.getOwnerDocument();
817
- XmlDocument xmlDoc = (XmlDocument)getCachedNode(doc);
818
- NokogiriNamespaceCache nsCache = xmlDoc.getNamespaceCache();
819
- int oldHash = n.hashCode();
836
+ NokogiriNamespaceCache nsCache = getNamespaceCacheFormNode(n);
820
837
  Node result = doc.renameNode(n, namespaceURI, qualifiedName);
821
838
  if (result != n) {
822
839
  nsCache.replaceNode(n, result);