nokogiri 1.11.1-java → 1.11.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.
- checksums.yaml +4 -4
- data/LICENSE-DEPENDENCIES.md +12 -12
- data/LICENSE.md +1 -1
- data/README.md +20 -15
- data/ext/java/nokogiri/EncodingHandler.java +78 -59
- data/ext/java/nokogiri/HtmlDocument.java +137 -114
- data/ext/java/nokogiri/HtmlElementDescription.java +104 -87
- data/ext/java/nokogiri/HtmlEntityLookup.java +31 -26
- data/ext/java/nokogiri/HtmlSaxParserContext.java +220 -192
- data/ext/java/nokogiri/HtmlSaxPushParser.java +164 -139
- data/ext/java/nokogiri/NokogiriService.java +597 -526
- data/ext/java/nokogiri/XmlAttr.java +120 -96
- data/ext/java/nokogiri/XmlAttributeDecl.java +97 -76
- data/ext/java/nokogiri/XmlCdata.java +35 -26
- data/ext/java/nokogiri/XmlComment.java +48 -37
- data/ext/java/nokogiri/XmlDocument.java +642 -540
- data/ext/java/nokogiri/XmlDocumentFragment.java +127 -107
- data/ext/java/nokogiri/XmlDtd.java +450 -384
- data/ext/java/nokogiri/XmlElement.java +25 -18
- data/ext/java/nokogiri/XmlElementContent.java +345 -286
- data/ext/java/nokogiri/XmlElementDecl.java +126 -95
- data/ext/java/nokogiri/XmlEntityDecl.java +121 -97
- data/ext/java/nokogiri/XmlEntityReference.java +51 -42
- data/ext/java/nokogiri/XmlNamespace.java +177 -145
- data/ext/java/nokogiri/XmlNode.java +1843 -1588
- data/ext/java/nokogiri/XmlNodeSet.java +361 -299
- data/ext/java/nokogiri/XmlProcessingInstruction.java +49 -39
- data/ext/java/nokogiri/XmlReader.java +513 -418
- data/ext/java/nokogiri/XmlRelaxng.java +91 -78
- data/ext/java/nokogiri/XmlSaxParserContext.java +330 -285
- data/ext/java/nokogiri/XmlSaxPushParser.java +229 -190
- data/ext/java/nokogiri/XmlSchema.java +328 -263
- data/ext/java/nokogiri/XmlSyntaxError.java +113 -83
- data/ext/java/nokogiri/XmlText.java +57 -46
- data/ext/java/nokogiri/XmlXpathContext.java +240 -206
- data/ext/java/nokogiri/XsltStylesheet.java +282 -239
- data/ext/java/nokogiri/internals/ClosedStreamException.java +5 -2
- data/ext/java/nokogiri/internals/HtmlDomParserContext.java +199 -168
- data/ext/java/nokogiri/internals/IgnoreSchemaErrorsErrorHandler.java +17 -10
- data/ext/java/nokogiri/internals/NokogiriBlockingQueueInputStream.java +43 -16
- data/ext/java/nokogiri/internals/NokogiriDomParser.java +65 -50
- data/ext/java/nokogiri/internals/NokogiriEntityResolver.java +107 -88
- data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +25 -18
- data/ext/java/nokogiri/internals/NokogiriHandler.java +316 -254
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +738 -622
- data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +186 -143
- data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +83 -68
- data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +66 -49
- data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +86 -69
- data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +44 -29
- data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +118 -101
- data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +34 -24
- data/ext/java/nokogiri/internals/NokogiriXPathVariableResolver.java +25 -17
- data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +57 -42
- data/ext/java/nokogiri/internals/ParserContext.java +206 -179
- data/ext/java/nokogiri/internals/ReaderNode.java +478 -371
- data/ext/java/nokogiri/internals/SaveContextVisitor.java +822 -707
- data/ext/java/nokogiri/internals/SchemaErrorHandler.java +28 -19
- data/ext/java/nokogiri/internals/XalanDTMManagerPatch.java +129 -123
- data/ext/java/nokogiri/internals/XmlDeclHandler.java +5 -4
- data/ext/java/nokogiri/internals/XmlDomParserContext.java +208 -177
- data/ext/java/nokogiri/internals/XmlSaxParser.java +24 -17
- data/ext/java/nokogiri/internals/c14n/AttrCompare.java +71 -68
- data/ext/java/nokogiri/internals/c14n/C14nHelper.java +137 -118
- data/ext/java/nokogiri/internals/c14n/CanonicalFilter.java +27 -21
- data/ext/java/nokogiri/internals/c14n/CanonicalizationException.java +74 -61
- data/ext/java/nokogiri/internals/c14n/Canonicalizer.java +230 -205
- data/ext/java/nokogiri/internals/c14n/Canonicalizer11.java +572 -547
- data/ext/java/nokogiri/internals/c14n/Canonicalizer11_OmitComments.java +17 -10
- data/ext/java/nokogiri/internals/c14n/Canonicalizer11_WithComments.java +17 -10
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315.java +323 -302
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315Excl.java +232 -219
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclOmitComments.java +22 -15
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclWithComments.java +23 -16
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315OmitComments.java +23 -16
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315WithComments.java +22 -15
- data/ext/java/nokogiri/internals/c14n/CanonicalizerBase.java +575 -545
- data/ext/java/nokogiri/internals/c14n/CanonicalizerPhysical.java +141 -120
- data/ext/java/nokogiri/internals/c14n/CanonicalizerSpi.java +39 -38
- data/ext/java/nokogiri/internals/c14n/Constants.java +13 -10
- data/ext/java/nokogiri/internals/c14n/ElementProxy.java +279 -247
- data/ext/java/nokogiri/internals/c14n/HelperNodeList.java +66 -53
- data/ext/java/nokogiri/internals/c14n/IgnoreAllErrorHandler.java +44 -37
- data/ext/java/nokogiri/internals/c14n/InclusiveNamespaces.java +135 -120
- data/ext/java/nokogiri/internals/c14n/InvalidCanonicalizerException.java +59 -48
- data/ext/java/nokogiri/internals/c14n/NameSpaceSymbTable.java +384 -334
- data/ext/java/nokogiri/internals/c14n/NodeFilter.java +25 -24
- data/ext/java/nokogiri/internals/c14n/UtfHelpper.java +151 -140
- data/ext/java/nokogiri/internals/c14n/XMLUtils.java +456 -423
- data/ext/java/nokogiri/internals/dom2dtm/DOM2DTM.java +1466 -1500
- data/ext/java/nokogiri/internals/dom2dtm/DOM2DTMdefaultNamespaceDeclarationNode.java +626 -570
- data/ext/nokogiri/depend +34 -474
- data/ext/nokogiri/extconf.rb +253 -183
- data/ext/nokogiri/html_document.c +10 -15
- data/ext/nokogiri/html_element_description.c +84 -71
- data/ext/nokogiri/html_entity_lookup.c +21 -16
- data/ext/nokogiri/html_sax_parser_context.c +66 -65
- data/ext/nokogiri/html_sax_push_parser.c +29 -27
- data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
- data/ext/nokogiri/nokogiri.c +171 -63
- data/ext/nokogiri/test_global_handlers.c +3 -4
- data/ext/nokogiri/xml_attr.c +15 -15
- data/ext/nokogiri/xml_attribute_decl.c +18 -18
- data/ext/nokogiri/xml_cdata.c +13 -18
- data/ext/nokogiri/xml_comment.c +19 -26
- data/ext/nokogiri/xml_document.c +221 -164
- data/ext/nokogiri/xml_document_fragment.c +13 -15
- data/ext/nokogiri/xml_dtd.c +54 -48
- data/ext/nokogiri/xml_element_content.c +30 -27
- data/ext/nokogiri/xml_element_decl.c +22 -22
- data/ext/nokogiri/xml_encoding_handler.c +17 -11
- data/ext/nokogiri/xml_entity_decl.c +32 -30
- data/ext/nokogiri/xml_entity_reference.c +16 -18
- data/ext/nokogiri/xml_namespace.c +56 -49
- data/ext/nokogiri/xml_node.c +338 -286
- data/ext/nokogiri/xml_node_set.c +168 -156
- data/ext/nokogiri/xml_processing_instruction.c +17 -19
- data/ext/nokogiri/xml_reader.c +191 -157
- data/ext/nokogiri/xml_relax_ng.c +29 -23
- data/ext/nokogiri/xml_sax_parser.c +117 -112
- data/ext/nokogiri/xml_sax_parser_context.c +100 -85
- data/ext/nokogiri/xml_sax_push_parser.c +34 -27
- data/ext/nokogiri/xml_schema.c +48 -42
- data/ext/nokogiri/xml_syntax_error.c +21 -23
- data/ext/nokogiri/xml_text.c +13 -17
- data/ext/nokogiri/xml_xpath_context.c +134 -127
- data/ext/nokogiri/xslt_stylesheet.c +157 -157
- data/lib/nokogiri.rb +1 -22
- data/lib/nokogiri/css/parser.rb +1 -1
- data/lib/nokogiri/extension.rb +26 -0
- data/lib/nokogiri/html/document_fragment.rb +15 -15
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/lib/nokogiri/version/constant.rb +1 -1
- data/lib/nokogiri/version/info.rb +31 -8
- data/lib/nokogiri/xml/document.rb +31 -11
- data/lib/nokogiri/xml/node.rb +38 -42
- data/lib/nokogiri/xml/reader.rb +2 -9
- data/lib/nokogiri/xml/xpath.rb +1 -3
- data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -1
- metadata +7 -8
- data/ext/nokogiri/xml_io.c +0 -63
- data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
@@ -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.
|
@@ -51,47 +51,58 @@ import org.w3c.dom.Node;
|
|
51
51
|
* @author Yoko Harada <yokolet@gmail.com>
|
52
52
|
*/
|
53
53
|
|
54
|
-
@JRubyClass(name="Nokogiri::XML::Comment", parent="Nokogiri::XML::CharacterData")
|
55
|
-
public class XmlComment extends XmlNode
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
@JRubyClass(name = "Nokogiri::XML::Comment", parent = "Nokogiri::XML::CharacterData")
|
55
|
+
public class XmlComment extends XmlNode
|
56
|
+
{
|
57
|
+
public
|
58
|
+
XmlComment(Ruby ruby, RubyClass rubyClass, Node node)
|
59
|
+
{
|
60
|
+
super(ruby, rubyClass, node);
|
61
|
+
}
|
59
62
|
|
60
|
-
|
61
|
-
|
63
|
+
public
|
64
|
+
XmlComment(Ruby runtime, RubyClass klass)
|
65
|
+
{
|
66
|
+
super(runtime, klass);
|
67
|
+
}
|
68
|
+
|
69
|
+
@Override
|
70
|
+
protected void
|
71
|
+
init(ThreadContext context, IRubyObject[] args)
|
72
|
+
{
|
73
|
+
if (args.length < 2) {
|
74
|
+
throw getRuntime().newArgumentError(args.length, 2);
|
62
75
|
}
|
63
76
|
|
64
|
-
|
65
|
-
|
66
|
-
if (args.length < 2)
|
67
|
-
throw getRuntime().newArgumentError(args.length, 2);
|
77
|
+
IRubyObject doc = args[0];
|
78
|
+
IRubyObject text = args[1];
|
68
79
|
|
69
|
-
|
70
|
-
|
80
|
+
XmlDocument xmlDoc;
|
81
|
+
if (doc instanceof XmlDocument) {
|
82
|
+
xmlDoc = (XmlDocument) doc;
|
71
83
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
if (xmlDoc != null) {
|
83
|
-
Document document = xmlDoc.getDocument();
|
84
|
-
Node node = document.createComment(rubyStringToString(text));
|
85
|
-
setNode(context.runtime, node);
|
86
|
-
}
|
84
|
+
} else if (doc instanceof XmlNode) {
|
85
|
+
XmlNode xmlNode = (XmlNode) doc;
|
86
|
+
xmlDoc = (XmlDocument)xmlNode.document(context);
|
87
|
+
} else {
|
88
|
+
throw getRuntime().newArgumentError("first argument must be a XML::Document or XML::Node");
|
89
|
+
}
|
90
|
+
if (xmlDoc != null) {
|
91
|
+
Document document = xmlDoc.getDocument();
|
92
|
+
Node node = document.createComment(rubyStringToString(text));
|
93
|
+
setNode(context.runtime, node);
|
87
94
|
}
|
95
|
+
}
|
88
96
|
|
89
|
-
|
90
|
-
|
97
|
+
@Override
|
98
|
+
public boolean
|
99
|
+
isComment() { return true; }
|
91
100
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
101
|
+
@Override
|
102
|
+
public void
|
103
|
+
accept(ThreadContext context, SaveContextVisitor visitor)
|
104
|
+
{
|
105
|
+
visitor.enter((Comment)node);
|
106
|
+
visitor.leave((Comment)node);
|
107
|
+
}
|
97
108
|
}
|
@@ -84,550 +84,652 @@ import nokogiri.internals.c14n.Canonicalizer;
|
|
84
84
|
* @author John Shahid <jvshahid@gmail.com>
|
85
85
|
*/
|
86
86
|
|
87
|
-
@JRubyClass(name="Nokogiri::XML::Document", parent="Nokogiri::XML::Node")
|
88
|
-
public class XmlDocument extends XmlNode
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
String default_href = nsCache.getDefault().getHref();
|
185
|
-
resolveNamespaceIfNecessary(document.getDocumentElement(), default_href);
|
186
|
-
}
|
187
|
-
|
188
|
-
private void resolveNamespaceIfNecessary(Node node, String default_href) {
|
189
|
-
if (node == null) return;
|
190
|
-
String nodePrefix = node.getPrefix();
|
191
|
-
if (nodePrefix == null) { // default namespace
|
192
|
-
NokogiriHelpers.renameNode(node, default_href, node.getNodeName());
|
193
|
-
} else {
|
194
|
-
String href = getNamespaceCache().get(node, nodePrefix).getHref();
|
195
|
-
NokogiriHelpers.renameNode(node, href, node.getNodeName());
|
196
|
-
}
|
197
|
-
resolveNamespaceIfNecessary(node.getNextSibling(), default_href);
|
198
|
-
NodeList children = node.getChildNodes();
|
199
|
-
for (int i=0; i<children.getLength(); i++) {
|
200
|
-
resolveNamespaceIfNecessary(children.item(i), default_href);
|
201
|
-
}
|
202
|
-
}
|
203
|
-
|
204
|
-
public NokogiriNamespaceCache getNamespaceCache() {
|
205
|
-
if (nsCache == null) nsCache = new NokogiriNamespaceCache();
|
206
|
-
return nsCache;
|
207
|
-
}
|
208
|
-
|
209
|
-
public Document getDocument() {
|
210
|
-
return (Document) node;
|
211
|
-
}
|
212
|
-
|
213
|
-
@Override
|
214
|
-
protected IRubyObject getNodeName(ThreadContext context) {
|
215
|
-
if (name == null) name = RubyString.newStringShared(context.runtime, DOCUMENT);
|
216
|
-
return name;
|
217
|
-
}
|
218
|
-
|
219
|
-
public void setUrl(IRubyObject url) {
|
220
|
-
this.url = url;
|
221
|
-
}
|
222
|
-
|
223
|
-
protected IRubyObject getUrl() {
|
224
|
-
return this.url;
|
225
|
-
}
|
226
|
-
|
227
|
-
@JRubyMethod
|
228
|
-
public IRubyObject url(ThreadContext context) {
|
229
|
-
return getUrl();
|
230
|
-
}
|
231
|
-
|
232
|
-
public static Document createNewDocument(final Ruby runtime) {
|
233
|
-
try {
|
234
|
-
return DocumentBuilderFactoryHolder.INSTANCE.newDocumentBuilder().newDocument();
|
235
|
-
} catch (ParserConfigurationException e) {
|
236
|
-
throw asRuntimeError(runtime, null, e);
|
237
|
-
}
|
238
|
-
}
|
239
|
-
|
240
|
-
private static class DocumentBuilderFactoryHolder {
|
241
|
-
static final DocumentBuilderFactory INSTANCE;
|
242
|
-
static {
|
243
|
-
INSTANCE = DocumentBuilderFactory.newInstance(DOCUMENTBUILDERFACTORY_IMPLE_NAME, NokogiriService.class.getClassLoader());
|
244
|
-
}
|
245
|
-
}
|
246
|
-
|
247
|
-
static RaiseException asRuntimeError(Ruby runtime, String message, Exception cause) {
|
248
|
-
if (cause instanceof RaiseException) return (RaiseException) cause;
|
249
|
-
|
250
|
-
if (message == null) message = cause.toString();
|
251
|
-
else message = message + '(' + cause.toString() + ')';
|
252
|
-
RaiseException ex = runtime.newRuntimeError(message);
|
253
|
-
ex.initCause(cause);
|
254
|
-
return ex;
|
255
|
-
}
|
256
|
-
|
257
|
-
/*
|
258
|
-
* call-seq:
|
259
|
-
* new(version = default)
|
260
|
-
*
|
261
|
-
* Create a new document with +version+ (defaults to "1.0")
|
262
|
-
*/
|
263
|
-
@JRubyMethod(name="new", meta = true, rest = true, required=0)
|
264
|
-
public static IRubyObject rbNew(ThreadContext context, IRubyObject klazz, IRubyObject[] args) {
|
265
|
-
final Ruby runtime = context.runtime;
|
266
|
-
XmlDocument xmlDocument;
|
267
|
-
try {
|
268
|
-
Document docNode = createNewDocument(runtime);
|
269
|
-
if ("Nokogiri::HTML::Document".equals(((RubyClass)klazz).getName())) {
|
270
|
-
xmlDocument = new HtmlDocument(context.runtime, (RubyClass) klazz, docNode);
|
271
|
-
} else {
|
272
|
-
xmlDocument = new XmlDocument(context.runtime, (RubyClass) klazz, docNode);
|
273
|
-
}
|
274
|
-
} catch (Exception ex) {
|
275
|
-
throw asRuntimeError(runtime, "couldn't create document: ", ex);
|
276
|
-
}
|
277
|
-
|
278
|
-
Helpers.invoke(context, xmlDocument, "initialize", args);
|
279
|
-
|
280
|
-
return xmlDocument;
|
281
|
-
}
|
282
|
-
|
283
|
-
@JRubyMethod(required=1, optional=4)
|
284
|
-
public IRubyObject create_entity(ThreadContext context, IRubyObject[] argv) {
|
285
|
-
// FIXME: Entity node should be create by some right way.
|
286
|
-
// this impl passes tests, but entity doesn't exists in DTD, which
|
287
|
-
// would cause validation failure.
|
288
|
-
if (argv.length == 0) throw context.runtime.newRuntimeError("Could not create entity");
|
289
|
-
String tagName = rubyStringToString(argv[0]);
|
290
|
-
Node node = getOwnerDocument().createElement(tagName);
|
291
|
-
return XmlEntityDecl.create(context, node, argv);
|
292
|
-
}
|
293
|
-
|
294
|
-
@Override
|
295
|
-
XmlDocument document(Ruby runtime) {
|
296
|
-
return this;
|
297
|
-
}
|
298
|
-
|
299
|
-
@JRubyMethod(name="encoding=")
|
300
|
-
public IRubyObject encoding_set(IRubyObject encoding) {
|
301
|
-
this.encoding = encoding;
|
302
|
-
return this;
|
303
|
-
}
|
304
|
-
|
305
|
-
@JRubyMethod
|
306
|
-
public IRubyObject encoding(ThreadContext context) {
|
307
|
-
if (this.encoding == null || this.encoding.isNil()) {
|
308
|
-
final String enc = getDocument().getXmlEncoding();
|
309
|
-
if (enc == null) {
|
310
|
-
this.encoding = context.nil;
|
311
|
-
} else {
|
312
|
-
this.encoding = context.runtime.newString(enc);
|
313
|
-
}
|
87
|
+
@JRubyClass(name = "Nokogiri::XML::Document", parent = "Nokogiri::XML::Node")
|
88
|
+
public class XmlDocument extends XmlNode
|
89
|
+
{
|
90
|
+
private NokogiriNamespaceCache nsCache;
|
91
|
+
|
92
|
+
/* UserData keys for storing extra info in the document node. */
|
93
|
+
public final static String DTD_RAW_DOCUMENT = "DTD_RAW_DOCUMENT";
|
94
|
+
public final static String DTD_INTERNAL_SUBSET = "DTD_INTERNAL_SUBSET";
|
95
|
+
public final static String DTD_EXTERNAL_SUBSET = "DTD_EXTERNAL_SUBSET";
|
96
|
+
|
97
|
+
/* DocumentBuilderFactory implementation class name. This needs to set a classloader into it.
|
98
|
+
* Setting an appropriate classloader resolves issue 380.
|
99
|
+
*/
|
100
|
+
private static final String DOCUMENTBUILDERFACTORY_IMPLE_NAME = "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
|
101
|
+
|
102
|
+
private static final ByteList DOCUMENT = ByteList.create("document");
|
103
|
+
static { DOCUMENT.setEncoding(USASCIIEncoding.INSTANCE); }
|
104
|
+
|
105
|
+
private static boolean substituteEntities = false;
|
106
|
+
private static boolean loadExternalSubset = false; // TODO: Verify this.
|
107
|
+
|
108
|
+
/** cache variables */
|
109
|
+
protected IRubyObject encoding;
|
110
|
+
protected IRubyObject url;
|
111
|
+
|
112
|
+
public
|
113
|
+
XmlDocument(Ruby runtime, RubyClass klazz)
|
114
|
+
{
|
115
|
+
super(runtime, klazz, createNewDocument(runtime));
|
116
|
+
}
|
117
|
+
|
118
|
+
public
|
119
|
+
XmlDocument(Ruby runtime, Document document)
|
120
|
+
{
|
121
|
+
this(runtime, getNokogiriClass(runtime, "Nokogiri::XML::Document"), document);
|
122
|
+
}
|
123
|
+
|
124
|
+
public
|
125
|
+
XmlDocument(Ruby runtime, RubyClass klass, Document document)
|
126
|
+
{
|
127
|
+
super(runtime, klass, document);
|
128
|
+
init(runtime, document);
|
129
|
+
}
|
130
|
+
|
131
|
+
void
|
132
|
+
init(Ruby runtime, Document document)
|
133
|
+
{
|
134
|
+
stabilizeTextContent(document);
|
135
|
+
if (document.getDocumentElement() != null) {
|
136
|
+
createAndCacheNamespaces(runtime, document.getDocumentElement());
|
137
|
+
}
|
138
|
+
setInstanceVariable("@decorators", runtime.getNil());
|
139
|
+
}
|
140
|
+
|
141
|
+
public final void
|
142
|
+
setDocumentNode(Ruby runtime, Document node)
|
143
|
+
{
|
144
|
+
super.setNode(runtime, node);
|
145
|
+
if (node != null) { init(runtime, node); }
|
146
|
+
else { setInstanceVariable("@decorators", runtime.getNil()); }
|
147
|
+
}
|
148
|
+
|
149
|
+
public void
|
150
|
+
setEncoding(IRubyObject encoding)
|
151
|
+
{
|
152
|
+
this.encoding = encoding;
|
153
|
+
}
|
154
|
+
|
155
|
+
public IRubyObject
|
156
|
+
getEncoding()
|
157
|
+
{
|
158
|
+
return encoding;
|
159
|
+
}
|
160
|
+
|
161
|
+
// not sure, but like attribute values, text value will be lost
|
162
|
+
// unless it is referred once before this document is used.
|
163
|
+
// this seems to happen only when the fragment is parsed from Node#in_context.
|
164
|
+
protected static void
|
165
|
+
stabilizeTextContent(Document document)
|
166
|
+
{
|
167
|
+
if (document.getDocumentElement() != null) { document.getDocumentElement().getTextContent(); }
|
168
|
+
}
|
169
|
+
|
170
|
+
private static void
|
171
|
+
createAndCacheNamespaces(Ruby runtime, Node node)
|
172
|
+
{
|
173
|
+
if (node.hasAttributes()) {
|
174
|
+
NamedNodeMap nodeMap = node.getAttributes();
|
175
|
+
for (int i = 0; i < nodeMap.getLength(); i++) {
|
176
|
+
Node n = nodeMap.item(i);
|
177
|
+
if (n instanceof Attr) {
|
178
|
+
Attr attr = (Attr) n;
|
179
|
+
stabilizeAttr(attr);
|
180
|
+
if (isNamespace(attr.getName())) {
|
181
|
+
// create and cache
|
182
|
+
XmlNamespace.createFromAttr(runtime, attr);
|
183
|
+
}
|
314
184
|
}
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
185
|
+
}
|
186
|
+
}
|
187
|
+
NodeList children = node.getChildNodes();
|
188
|
+
for (int i = 0; i < children.getLength(); i++) {
|
189
|
+
createAndCacheNamespaces(runtime, children.item(i));
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
static void
|
194
|
+
stabilizeAttr(final Attr attr)
|
195
|
+
{
|
196
|
+
// TODO not sure, but need to get value always before document is referred or lose attribute value
|
197
|
+
attr.getValue(); // don't delete this line
|
198
|
+
}
|
199
|
+
|
200
|
+
// When a document is created from fragment with a context (reference) document,
|
201
|
+
// namespace should be resolved based on the context document.
|
202
|
+
public
|
203
|
+
XmlDocument(Ruby ruby, RubyClass klass, Document document, XmlDocument contextDoc)
|
204
|
+
{
|
205
|
+
super(ruby, klass, document);
|
206
|
+
nsCache = contextDoc.getNamespaceCache();
|
207
|
+
String default_href = nsCache.getDefault().getHref();
|
208
|
+
resolveNamespaceIfNecessary(document.getDocumentElement(), default_href);
|
209
|
+
}
|
210
|
+
|
211
|
+
private void
|
212
|
+
resolveNamespaceIfNecessary(Node node, String default_href)
|
213
|
+
{
|
214
|
+
if (node == null) { return; }
|
215
|
+
String nodePrefix = node.getPrefix();
|
216
|
+
if (nodePrefix == null) { // default namespace
|
217
|
+
NokogiriHelpers.renameNode(node, default_href, node.getNodeName());
|
218
|
+
} else {
|
219
|
+
String href = getNamespaceCache().get(node, nodePrefix).getHref();
|
220
|
+
NokogiriHelpers.renameNode(node, href, node.getNodeName());
|
221
|
+
}
|
222
|
+
resolveNamespaceIfNecessary(node.getNextSibling(), default_href);
|
223
|
+
NodeList children = node.getChildNodes();
|
224
|
+
for (int i = 0; i < children.getLength(); i++) {
|
225
|
+
resolveNamespaceIfNecessary(children.item(i), default_href);
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
public NokogiriNamespaceCache
|
230
|
+
getNamespaceCache()
|
231
|
+
{
|
232
|
+
if (nsCache == null) { nsCache = new NokogiriNamespaceCache(); }
|
233
|
+
return nsCache;
|
234
|
+
}
|
235
|
+
|
236
|
+
public Document
|
237
|
+
getDocument()
|
238
|
+
{
|
239
|
+
return (Document) node;
|
240
|
+
}
|
241
|
+
|
242
|
+
@Override
|
243
|
+
protected IRubyObject
|
244
|
+
getNodeName(ThreadContext context)
|
245
|
+
{
|
246
|
+
if (name == null) { name = RubyString.newStringShared(context.runtime, DOCUMENT); }
|
247
|
+
return name;
|
248
|
+
}
|
249
|
+
|
250
|
+
public void
|
251
|
+
setUrl(IRubyObject url)
|
252
|
+
{
|
253
|
+
this.url = url;
|
254
|
+
}
|
255
|
+
|
256
|
+
protected IRubyObject
|
257
|
+
getUrl()
|
258
|
+
{
|
259
|
+
return this.url;
|
260
|
+
}
|
261
|
+
|
262
|
+
@JRubyMethod
|
263
|
+
public IRubyObject
|
264
|
+
url(ThreadContext context)
|
265
|
+
{
|
266
|
+
return getUrl();
|
267
|
+
}
|
268
|
+
|
269
|
+
public static Document
|
270
|
+
createNewDocument(final Ruby runtime)
|
271
|
+
{
|
272
|
+
try {
|
273
|
+
return DocumentBuilderFactoryHolder.INSTANCE.newDocumentBuilder().newDocument();
|
274
|
+
} catch (ParserConfigurationException e) {
|
275
|
+
throw asRuntimeError(runtime, null, e);
|
276
|
+
}
|
277
|
+
}
|
278
|
+
|
279
|
+
private static class DocumentBuilderFactoryHolder
|
280
|
+
{
|
281
|
+
static final DocumentBuilderFactory INSTANCE;
|
282
|
+
static
|
283
|
+
{
|
284
|
+
INSTANCE = DocumentBuilderFactory.newInstance(DOCUMENTBUILDERFACTORY_IMPLE_NAME,
|
285
|
+
NokogiriService.class.getClassLoader());
|
286
|
+
}
|
287
|
+
}
|
288
|
+
|
289
|
+
static RaiseException
|
290
|
+
asRuntimeError(Ruby runtime, String message, Exception cause)
|
291
|
+
{
|
292
|
+
if (cause instanceof RaiseException) { return (RaiseException) cause; }
|
293
|
+
|
294
|
+
if (message == null) { message = cause.toString(); }
|
295
|
+
else { message = message + '(' + cause.toString() + ')'; }
|
296
|
+
RaiseException ex = runtime.newRuntimeError(message);
|
297
|
+
ex.initCause(cause);
|
298
|
+
return ex;
|
299
|
+
}
|
300
|
+
|
301
|
+
/*
|
302
|
+
* call-seq:
|
303
|
+
* new(version = default)
|
304
|
+
*
|
305
|
+
* Create a new document with +version+ (defaults to "1.0")
|
306
|
+
*/
|
307
|
+
@JRubyMethod(name = "new", meta = true, rest = true, required = 0)
|
308
|
+
public static IRubyObject
|
309
|
+
rbNew(ThreadContext context, IRubyObject klazz, IRubyObject[] args)
|
310
|
+
{
|
311
|
+
final Ruby runtime = context.runtime;
|
312
|
+
XmlDocument xmlDocument;
|
313
|
+
try {
|
314
|
+
Document docNode = createNewDocument(runtime);
|
315
|
+
if ("Nokogiri::HTML::Document".equals(((RubyClass)klazz).getName())) {
|
316
|
+
xmlDocument = new HtmlDocument(context.runtime, (RubyClass) klazz, docNode);
|
317
|
+
} else {
|
318
|
+
xmlDocument = new XmlDocument(context.runtime, (RubyClass) klazz, docNode);
|
319
|
+
}
|
320
|
+
} catch (Exception ex) {
|
321
|
+
throw asRuntimeError(runtime, "couldn't create document: ", ex);
|
322
|
+
}
|
323
|
+
|
324
|
+
Helpers.invoke(context, xmlDocument, "initialize", args);
|
325
|
+
|
326
|
+
return xmlDocument;
|
327
|
+
}
|
328
|
+
|
329
|
+
@JRubyMethod(required = 1, optional = 4)
|
330
|
+
public IRubyObject
|
331
|
+
create_entity(ThreadContext context, IRubyObject[] argv)
|
332
|
+
{
|
333
|
+
// FIXME: Entity node should be create by some right way.
|
334
|
+
// this impl passes tests, but entity doesn't exists in DTD, which
|
335
|
+
// would cause validation failure.
|
336
|
+
if (argv.length == 0) { throw context.runtime.newRuntimeError("Could not create entity"); }
|
337
|
+
String tagName = rubyStringToString(argv[0]);
|
338
|
+
Node node = getOwnerDocument().createElement(tagName);
|
339
|
+
return XmlEntityDecl.create(context, node, argv);
|
340
|
+
}
|
341
|
+
|
342
|
+
@Override
|
343
|
+
XmlDocument
|
344
|
+
document(Ruby runtime)
|
345
|
+
{
|
346
|
+
return this;
|
347
|
+
}
|
348
|
+
|
349
|
+
@JRubyMethod(name = "encoding=")
|
350
|
+
public IRubyObject
|
351
|
+
encoding_set(IRubyObject encoding)
|
352
|
+
{
|
353
|
+
this.encoding = encoding;
|
354
|
+
return this;
|
355
|
+
}
|
356
|
+
|
357
|
+
@JRubyMethod
|
358
|
+
public IRubyObject
|
359
|
+
encoding(ThreadContext context)
|
360
|
+
{
|
361
|
+
if (this.encoding == null || this.encoding.isNil()) {
|
362
|
+
final String enc = getDocument().getXmlEncoding();
|
363
|
+
if (enc == null) {
|
364
|
+
this.encoding = context.nil;
|
365
|
+
} else {
|
366
|
+
this.encoding = context.runtime.newString(enc);
|
367
|
+
}
|
368
|
+
}
|
369
|
+
|
370
|
+
return this.encoding.isNil() ? this.encoding : this.encoding.asString().encode(context,
|
371
|
+
context.getRuntime().newString("UTF-8"));
|
372
|
+
}
|
373
|
+
|
374
|
+
@JRubyMethod(meta = true)
|
375
|
+
public static IRubyObject
|
376
|
+
load_external_subsets_set(ThreadContext context, IRubyObject cls, IRubyObject value)
|
377
|
+
{
|
378
|
+
XmlDocument.loadExternalSubset = value.isTrue();
|
379
|
+
return context.nil;
|
380
|
+
}
|
381
|
+
|
382
|
+
@JRubyMethod(meta = true, required = 4)
|
383
|
+
public static IRubyObject
|
384
|
+
read_io(ThreadContext context, IRubyObject klass, IRubyObject[] args)
|
385
|
+
{
|
386
|
+
XmlDomParserContext ctx = new XmlDomParserContext(context.runtime, args[2], args[3]);
|
387
|
+
ctx.setIOInputSource(context, args[0], args[1]);
|
388
|
+
return ctx.parse(context, (RubyClass) klass, args[1]);
|
389
|
+
}
|
390
|
+
|
391
|
+
@JRubyMethod(meta = true, required = 4)
|
392
|
+
public static IRubyObject
|
393
|
+
read_memory(ThreadContext context, IRubyObject klass, IRubyObject[] args)
|
394
|
+
{
|
395
|
+
XmlDomParserContext ctx = new XmlDomParserContext(context.runtime, args[2], args[3]);
|
396
|
+
ctx.setStringInputSource(context, args[0], args[1]);
|
397
|
+
return ctx.parse(context, (RubyClass) klass, args[1]);
|
398
|
+
}
|
399
|
+
|
400
|
+
@JRubyMethod(name = "remove_namespaces!")
|
401
|
+
public IRubyObject
|
402
|
+
remove_namespaces(ThreadContext context)
|
403
|
+
{
|
404
|
+
removeNamespaceRecursively(this);
|
405
|
+
if (nsCache != null) { nsCache.clear(); }
|
406
|
+
clearXpathContext(getNode());
|
407
|
+
return this;
|
408
|
+
}
|
409
|
+
|
410
|
+
private void
|
411
|
+
removeNamespaceRecursively(XmlNode xmlNode)
|
412
|
+
{
|
413
|
+
Node node = xmlNode.node;
|
414
|
+
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
415
|
+
node.setPrefix(null);
|
416
|
+
NokogiriHelpers.renameNode(node, null, node.getLocalName());
|
417
|
+
NamedNodeMap attrs = node.getAttributes();
|
418
|
+
for (int i = 0; i < attrs.getLength(); i++) {
|
419
|
+
Attr attr = (Attr) attrs.item(i);
|
420
|
+
if (isNamespace(attr.getNodeName())) {
|
421
|
+
((org.w3c.dom.Element) node).removeAttributeNode(attr);
|
419
422
|
} else {
|
420
|
-
|
421
|
-
|
423
|
+
attr.setPrefix(null);
|
424
|
+
NokogiriHelpers.renameNode(attr, null, attr.getLocalName());
|
422
425
|
}
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
426
|
+
}
|
427
|
+
}
|
428
|
+
IRubyObject[] nodes = xmlNode.getChildren();
|
429
|
+
for (int i = 0; i < nodes.length; i++) {
|
430
|
+
XmlNode childNode = (XmlNode) nodes[i];
|
431
|
+
removeNamespaceRecursively(childNode);
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
@JRubyMethod
|
436
|
+
public IRubyObject
|
437
|
+
root(ThreadContext context)
|
438
|
+
{
|
439
|
+
Node rootNode = getDocument().getDocumentElement();
|
440
|
+
if (rootNode == null) { return context.nil; }
|
441
|
+
|
442
|
+
Object invalid = rootNode.getUserData(NokogiriHelpers.ROOT_NODE_INVALID);
|
443
|
+
if (invalid != null && ((Boolean) invalid)) { return context.nil; }
|
444
|
+
|
445
|
+
return getCachedNodeOrCreate(context.runtime, rootNode);
|
446
|
+
}
|
447
|
+
|
448
|
+
protected IRubyObject
|
449
|
+
dup_implementation(Ruby runtime, boolean deep)
|
450
|
+
{
|
451
|
+
XmlDocument doc = (XmlDocument) super.dup_implementation(runtime, deep);
|
452
|
+
// Avoid creating a new XmlDocument since we cloned one
|
453
|
+
// already. Otherwise the following test will fail:
|
454
|
+
//
|
455
|
+
// dup = doc.dup
|
456
|
+
// dup.equal?(dup.children[0].document)
|
457
|
+
//
|
458
|
+
// Since `dup.children[0].document' will end up creating a new
|
459
|
+
// XmlDocument. See #1060.
|
460
|
+
doc.resetCache();
|
461
|
+
return doc;
|
462
|
+
}
|
463
|
+
|
464
|
+
@JRubyMethod(name = "root=")
|
465
|
+
public IRubyObject
|
466
|
+
root_set(ThreadContext context, IRubyObject new_root)
|
467
|
+
{
|
468
|
+
// in case of document fragment, temporary root node should be deleted.
|
469
|
+
|
470
|
+
// Java can't have a root whose value is null. Instead of setting null,
|
471
|
+
// the method sets user data so that other methods are able to know the root
|
472
|
+
// should be nil.
|
473
|
+
if (new_root == context.nil) {
|
474
|
+
getDocument().getDocumentElement().setUserData(NokogiriHelpers.ROOT_NODE_INVALID, Boolean.TRUE, null);
|
475
|
+
return new_root;
|
476
|
+
}
|
477
|
+
XmlNode newRoot = asXmlNode(context, new_root);
|
478
|
+
|
479
|
+
IRubyObject root = root(context);
|
480
|
+
if (root.isNil()) {
|
481
|
+
Node newRootNode;
|
482
|
+
if (getDocument() == newRoot.getOwnerDocument()) {
|
483
|
+
newRootNode = newRoot.node;
|
484
|
+
} else {
|
485
|
+
// must copy otherwise newRoot may exist in two places
|
486
|
+
// with different owner document.
|
487
|
+
newRootNode = getDocument().importNode(newRoot.node, true);
|
488
|
+
}
|
489
|
+
add_child_node(context, getCachedNodeOrCreate(context.runtime, newRootNode));
|
490
|
+
} else {
|
491
|
+
Node rootNode = asXmlNode(context, root).node;
|
492
|
+
((XmlNode) getCachedNodeOrCreate(context.runtime, rootNode)).replace_node(context, newRoot);
|
493
|
+
}
|
494
|
+
|
495
|
+
return newRoot;
|
496
|
+
}
|
497
|
+
|
498
|
+
@JRubyMethod
|
499
|
+
public IRubyObject
|
500
|
+
version(ThreadContext context)
|
501
|
+
{
|
502
|
+
return stringOrNil(context.runtime, getDocument().getXmlVersion());
|
503
|
+
}
|
504
|
+
|
505
|
+
@JRubyMethod(meta = true)
|
506
|
+
public static IRubyObject
|
507
|
+
substitute_entities_set(ThreadContext context, IRubyObject cls, IRubyObject value)
|
508
|
+
{
|
509
|
+
XmlDocument.substituteEntities = value.isTrue();
|
510
|
+
return context.nil;
|
511
|
+
}
|
512
|
+
|
513
|
+
public IRubyObject
|
514
|
+
getInternalSubset(ThreadContext context)
|
515
|
+
{
|
516
|
+
IRubyObject dtd = (IRubyObject) node.getUserData(DTD_INTERNAL_SUBSET);
|
517
|
+
|
518
|
+
if (dtd == null) {
|
519
|
+
Document document = getDocument();
|
520
|
+
if (document.getUserData(XmlDocument.DTD_RAW_DOCUMENT) != null) {
|
521
|
+
dtd = XmlDtd.newFromInternalSubset(context.runtime, document);
|
522
|
+
} else if (document.getDoctype() != null) {
|
523
|
+
DocumentType docType = document.getDoctype();
|
524
|
+
IRubyObject name, publicId, systemId;
|
525
|
+
name = publicId = systemId = context.nil;
|
526
|
+
if (docType.getName() != null) {
|
527
|
+
name = context.runtime.newString(docType.getName());
|
464
528
|
}
|
465
|
-
|
466
|
-
|
467
|
-
}
|
468
|
-
|
469
|
-
/**
|
470
|
-
* Assumes XmlNode#internal_subset() has returned nil. (i.e. there
|
471
|
-
* is not already an internal subset).
|
472
|
-
*/
|
473
|
-
public IRubyObject createInternalSubset(ThreadContext context,
|
474
|
-
IRubyObject name,
|
475
|
-
IRubyObject external_id,
|
476
|
-
IRubyObject system_id) {
|
477
|
-
XmlDtd dtd = XmlDtd.newEmpty(context.runtime, getDocument(), name, external_id, system_id);
|
478
|
-
setInternalSubset(dtd);
|
479
|
-
return dtd;
|
480
|
-
}
|
481
|
-
|
482
|
-
protected void setInternalSubset(IRubyObject data) {
|
483
|
-
node.setUserData(DTD_INTERNAL_SUBSET, data, null);
|
484
|
-
}
|
485
|
-
|
486
|
-
public IRubyObject getExternalSubset(ThreadContext context) {
|
487
|
-
IRubyObject dtd = (IRubyObject) node.getUserData(DTD_EXTERNAL_SUBSET);
|
488
|
-
|
489
|
-
if (dtd == null) return context.nil;
|
490
|
-
return dtd;
|
491
|
-
}
|
492
|
-
|
493
|
-
/**
|
494
|
-
* Assumes XmlNode#external_subset() has returned nil. (i.e. there
|
495
|
-
* is not already an external subset).
|
496
|
-
*/
|
497
|
-
public IRubyObject createExternalSubset(ThreadContext context,
|
498
|
-
IRubyObject name,
|
499
|
-
IRubyObject external_id,
|
500
|
-
IRubyObject system_id) {
|
501
|
-
XmlDtd dtd = XmlDtd.newEmpty(context.runtime, getDocument(), name, external_id, system_id);
|
502
|
-
setExternalSubset(dtd);
|
503
|
-
return dtd;
|
504
|
-
}
|
505
|
-
|
506
|
-
protected void setExternalSubset(IRubyObject data) {
|
507
|
-
node.setUserData(DTD_EXTERNAL_SUBSET, data, null);
|
508
|
-
}
|
509
|
-
|
510
|
-
@Override
|
511
|
-
public void accept(ThreadContext context, SaveContextVisitor visitor) {
|
512
|
-
Document document = getDocument();
|
513
|
-
visitor.enter(document);
|
514
|
-
NodeList children = document.getChildNodes();
|
515
|
-
for (int i=0; i<children.getLength(); i++) {
|
516
|
-
Node child = children.item(i);
|
517
|
-
short type = child.getNodeType();
|
518
|
-
if (type == Node.COMMENT_NODE) {
|
519
|
-
XmlComment xmlComment = (XmlComment) getCachedNodeOrCreate(context.runtime, child);
|
520
|
-
xmlComment.accept(context, visitor);
|
521
|
-
} else if (type == Node.DOCUMENT_TYPE_NODE) {
|
522
|
-
XmlDtd xmlDtd = (XmlDtd) getCachedNodeOrCreate(context.runtime, child);
|
523
|
-
xmlDtd.accept(context, visitor);
|
524
|
-
} else if (type == Node.PROCESSING_INSTRUCTION_NODE) {
|
525
|
-
XmlProcessingInstruction xmlProcessingInstruction = (XmlProcessingInstruction) getCachedNodeOrCreate(context.runtime, child);
|
526
|
-
xmlProcessingInstruction.accept(context, visitor);
|
527
|
-
} else if (type == Node.TEXT_NODE) {
|
528
|
-
XmlText xmlText = (XmlText) getCachedNodeOrCreate(context.runtime, child);
|
529
|
-
xmlText.accept(context, visitor);
|
530
|
-
} else if (type == Node.ELEMENT_NODE) {
|
531
|
-
XmlElement xmlElement = (XmlElement) getCachedNodeOrCreate(context.runtime, child);
|
532
|
-
xmlElement.accept(context, visitor);
|
533
|
-
}
|
534
|
-
}
|
535
|
-
visitor.leave(document);
|
536
|
-
}
|
537
|
-
|
538
|
-
@JRubyMethod(meta = true)
|
539
|
-
public static IRubyObject wrap(ThreadContext context, IRubyObject klass, IRubyObject arg) {
|
540
|
-
XmlDocument xmlDocument = new XmlDocument(context.runtime, (RubyClass) klass, (Document) arg.toJava(Document.class));
|
541
|
-
Helpers.invoke(context, xmlDocument, "initialize");
|
542
|
-
return xmlDocument;
|
543
|
-
}
|
544
|
-
|
545
|
-
@Deprecated
|
546
|
-
@JRubyMethod(meta = true, visibility = Visibility.PRIVATE)
|
547
|
-
public static IRubyObject wrapJavaDocument(ThreadContext context, IRubyObject klass, IRubyObject arg) {
|
548
|
-
return wrap(context, klass, arg);
|
549
|
-
}
|
550
|
-
|
551
|
-
@Deprecated // default to_java works (due inherited from XmlNode#toJava)
|
552
|
-
@JRubyMethod(visibility = Visibility.PRIVATE)
|
553
|
-
public IRubyObject toJavaDocument(ThreadContext context) {
|
554
|
-
return JavaUtil.convertJavaToUsableRubyObject(context.getRuntime(), node);
|
555
|
-
}
|
556
|
-
|
557
|
-
/* call-seq:
|
558
|
-
* doc.canonicalize(mode=XML_C14N_1_0,inclusive_namespaces=nil,with_comments=false)
|
559
|
-
* doc.canonicalize { |obj, parent| ... }
|
560
|
-
*
|
561
|
-
* Canonicalize a document and return the results. Takes an optional block
|
562
|
-
* that takes two parameters: the +obj+ and that node's +parent+.
|
563
|
-
* The +obj+ will be either a Nokogiri::XML::Node, or a Nokogiri::XML::Namespace
|
564
|
-
* The block must return a non-nil, non-false value if the +obj+ passed in
|
565
|
-
* should be included in the canonicalized document.
|
566
|
-
*/
|
567
|
-
@JRubyMethod(optional=3)
|
568
|
-
public IRubyObject canonicalize(ThreadContext context, IRubyObject[] args, Block block) {
|
569
|
-
int mode = 0;
|
570
|
-
String inclusive_namespace = null;
|
571
|
-
Boolean with_comments = false;
|
572
|
-
if (args.length > 0 && !(args[0].isNil())) {
|
573
|
-
mode = RubyFixnum.fix2int(args[0]);
|
574
|
-
}
|
575
|
-
if (args.length > 1 ) {
|
576
|
-
if (!args[1].isNil() && !(args[1] instanceof List)) {
|
577
|
-
throw context.runtime.newTypeError("Expected array");
|
578
|
-
}
|
579
|
-
if (!args[1].isNil()) {
|
580
|
-
inclusive_namespace = ((RubyArray)args[1])
|
581
|
-
.join(context, context.runtime.newString(" "))
|
582
|
-
.asString()
|
583
|
-
.asJavaString(); // OMG I wish I knew JRuby better, this is ugly
|
584
|
-
}
|
529
|
+
if (docType.getPublicId() != null) {
|
530
|
+
publicId = context.runtime.newString(docType.getPublicId());
|
585
531
|
}
|
586
|
-
if (
|
587
|
-
|
532
|
+
if (docType.getSystemId() != null) {
|
533
|
+
systemId = context.runtime.newString(docType.getSystemId());
|
588
534
|
}
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
535
|
+
dtd = XmlDtd.newEmpty(context.runtime, document, name, publicId, systemId);
|
536
|
+
} else {
|
537
|
+
dtd = context.nil;
|
538
|
+
}
|
539
|
+
|
540
|
+
setInternalSubset(dtd);
|
541
|
+
}
|
542
|
+
|
543
|
+
return dtd;
|
544
|
+
}
|
545
|
+
|
546
|
+
/**
|
547
|
+
* Assumes XmlNode#internal_subset() has returned nil. (i.e. there
|
548
|
+
* is not already an internal subset).
|
549
|
+
*/
|
550
|
+
public IRubyObject
|
551
|
+
createInternalSubset(ThreadContext context,
|
552
|
+
IRubyObject name,
|
553
|
+
IRubyObject external_id,
|
554
|
+
IRubyObject system_id)
|
555
|
+
{
|
556
|
+
XmlDtd dtd = XmlDtd.newEmpty(context.runtime, getDocument(), name, external_id, system_id);
|
557
|
+
setInternalSubset(dtd);
|
558
|
+
return dtd;
|
559
|
+
}
|
560
|
+
|
561
|
+
protected void
|
562
|
+
setInternalSubset(IRubyObject data)
|
563
|
+
{
|
564
|
+
node.setUserData(DTD_INTERNAL_SUBSET, data, null);
|
565
|
+
}
|
566
|
+
|
567
|
+
public IRubyObject
|
568
|
+
getExternalSubset(ThreadContext context)
|
569
|
+
{
|
570
|
+
IRubyObject dtd = (IRubyObject) node.getUserData(DTD_EXTERNAL_SUBSET);
|
571
|
+
|
572
|
+
if (dtd == null) { return context.nil; }
|
573
|
+
return dtd;
|
574
|
+
}
|
575
|
+
|
576
|
+
/**
|
577
|
+
* Assumes XmlNode#external_subset() has returned nil. (i.e. there
|
578
|
+
* is not already an external subset).
|
579
|
+
*/
|
580
|
+
public IRubyObject
|
581
|
+
createExternalSubset(ThreadContext context,
|
582
|
+
IRubyObject name,
|
583
|
+
IRubyObject external_id,
|
584
|
+
IRubyObject system_id)
|
585
|
+
{
|
586
|
+
XmlDtd dtd = XmlDtd.newEmpty(context.runtime, getDocument(), name, external_id, system_id);
|
587
|
+
setExternalSubset(dtd);
|
588
|
+
return dtd;
|
589
|
+
}
|
590
|
+
|
591
|
+
protected void
|
592
|
+
setExternalSubset(IRubyObject data)
|
593
|
+
{
|
594
|
+
node.setUserData(DTD_EXTERNAL_SUBSET, data, null);
|
595
|
+
}
|
596
|
+
|
597
|
+
@Override
|
598
|
+
public void
|
599
|
+
accept(ThreadContext context, SaveContextVisitor visitor)
|
600
|
+
{
|
601
|
+
Document document = getDocument();
|
602
|
+
visitor.enter(document);
|
603
|
+
NodeList children = document.getChildNodes();
|
604
|
+
for (int i = 0; i < children.getLength(); i++) {
|
605
|
+
Node child = children.item(i);
|
606
|
+
short type = child.getNodeType();
|
607
|
+
if (type == Node.COMMENT_NODE) {
|
608
|
+
XmlComment xmlComment = (XmlComment) getCachedNodeOrCreate(context.runtime, child);
|
609
|
+
xmlComment.accept(context, visitor);
|
610
|
+
} else if (type == Node.DOCUMENT_TYPE_NODE) {
|
611
|
+
XmlDtd xmlDtd = (XmlDtd) getCachedNodeOrCreate(context.runtime, child);
|
612
|
+
xmlDtd.accept(context, visitor);
|
613
|
+
} else if (type == Node.PROCESSING_INSTRUCTION_NODE) {
|
614
|
+
XmlProcessingInstruction xmlProcessingInstruction = (XmlProcessingInstruction) getCachedNodeOrCreate(context.runtime,
|
615
|
+
child);
|
616
|
+
xmlProcessingInstruction.accept(context, visitor);
|
617
|
+
} else if (type == Node.TEXT_NODE) {
|
618
|
+
XmlText xmlText = (XmlText) getCachedNodeOrCreate(context.runtime, child);
|
619
|
+
xmlText.accept(context, visitor);
|
620
|
+
} else if (type == Node.ELEMENT_NODE) {
|
621
|
+
XmlElement xmlElement = (XmlElement) getCachedNodeOrCreate(context.runtime, child);
|
622
|
+
xmlElement.accept(context, visitor);
|
623
|
+
}
|
624
|
+
}
|
625
|
+
visitor.leave(document);
|
626
|
+
}
|
627
|
+
|
628
|
+
@JRubyMethod(meta = true)
|
629
|
+
public static IRubyObject
|
630
|
+
wrap(ThreadContext context, IRubyObject klass, IRubyObject arg)
|
631
|
+
{
|
632
|
+
XmlDocument xmlDocument = new XmlDocument(context.runtime, (RubyClass) klass, (Document) arg.toJava(Document.class));
|
633
|
+
Helpers.invoke(context, xmlDocument, "initialize");
|
634
|
+
return xmlDocument;
|
635
|
+
}
|
636
|
+
|
637
|
+
@Deprecated
|
638
|
+
@JRubyMethod(meta = true, visibility = Visibility.PRIVATE)
|
639
|
+
public static IRubyObject
|
640
|
+
wrapJavaDocument(ThreadContext context, IRubyObject klass, IRubyObject arg)
|
641
|
+
{
|
642
|
+
return wrap(context, klass, arg);
|
643
|
+
}
|
644
|
+
|
645
|
+
@Deprecated // default to_java works (due inherited from XmlNode#toJava)
|
646
|
+
@JRubyMethod(visibility = Visibility.PRIVATE)
|
647
|
+
public IRubyObject
|
648
|
+
toJavaDocument(ThreadContext context)
|
649
|
+
{
|
650
|
+
return JavaUtil.convertJavaToUsableRubyObject(context.getRuntime(), node);
|
651
|
+
}
|
652
|
+
|
653
|
+
/* call-seq:
|
654
|
+
* doc.canonicalize(mode=XML_C14N_1_0,inclusive_namespaces=nil,with_comments=false)
|
655
|
+
* doc.canonicalize { |obj, parent| ... }
|
656
|
+
*
|
657
|
+
* Canonicalize a document and return the results. Takes an optional block
|
658
|
+
* that takes two parameters: the +obj+ and that node's +parent+.
|
659
|
+
* The +obj+ will be either a Nokogiri::XML::Node, or a Nokogiri::XML::Namespace
|
660
|
+
* The block must return a non-nil, non-false value if the +obj+ passed in
|
661
|
+
* should be included in the canonicalized document.
|
662
|
+
*/
|
663
|
+
@JRubyMethod(optional = 3)
|
664
|
+
public IRubyObject
|
665
|
+
canonicalize(ThreadContext context, IRubyObject[] args, Block block)
|
666
|
+
{
|
667
|
+
int mode = 0;
|
668
|
+
String inclusive_namespace = null;
|
669
|
+
Boolean with_comments = false;
|
670
|
+
if (args.length > 0 && !(args[0].isNil())) {
|
671
|
+
mode = RubyFixnum.fix2int(args[0]);
|
672
|
+
}
|
673
|
+
if (args.length > 1) {
|
674
|
+
if (!args[1].isNil() && !(args[1] instanceof List)) {
|
675
|
+
throw context.runtime.newTypeError("Expected array");
|
676
|
+
}
|
677
|
+
if (!args[1].isNil()) {
|
678
|
+
inclusive_namespace = ((RubyArray)args[1])
|
679
|
+
.join(context, context.runtime.newString(" "))
|
680
|
+
.asString()
|
681
|
+
.asJavaString(); // OMG I wish I knew JRuby better, this is ugly
|
682
|
+
}
|
683
|
+
}
|
684
|
+
if (args.length > 2) {
|
685
|
+
with_comments = args[2].isTrue();
|
686
|
+
}
|
687
|
+
String algorithmURI = null;
|
688
|
+
switch (mode) {
|
689
|
+
case 0: // XML_C14N_1_0
|
690
|
+
if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS; }
|
691
|
+
else { algorithmURI = Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS; }
|
692
|
+
break;
|
693
|
+
case 1: // XML_C14N_EXCLUSIVE_1_0
|
694
|
+
if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS; }
|
695
|
+
else { algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; }
|
696
|
+
break;
|
697
|
+
case 2: // XML_C14N_1_1 = 2
|
698
|
+
if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS; }
|
699
|
+
else { algorithmURI = Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS; }
|
700
|
+
}
|
701
|
+
try {
|
702
|
+
Canonicalizer canonicalizer = Canonicalizer.getInstance(algorithmURI);
|
703
|
+
XmlNode startingNode = getStartingNode(block);
|
704
|
+
byte[] result;
|
705
|
+
CanonicalFilter filter = new CanonicalFilter(context, block);
|
706
|
+
if (inclusive_namespace == null) {
|
707
|
+
result = canonicalizer.canonicalizeSubtree(startingNode.getNode(), filter);
|
708
|
+
} else {
|
709
|
+
result = canonicalizer.canonicalizeSubtree(startingNode.getNode(), inclusive_namespace, filter);
|
710
|
+
}
|
711
|
+
return RubyString.newString(context.runtime, new ByteList(result, UTF8Encoding.INSTANCE));
|
712
|
+
} catch (CanonicalizationException e) {
|
713
|
+
// TODO Auto-generated catch block
|
714
|
+
e.printStackTrace();
|
715
|
+
}
|
716
|
+
return context.nil;
|
717
|
+
}
|
718
|
+
|
719
|
+
private XmlNode
|
720
|
+
getStartingNode(Block block)
|
721
|
+
{
|
722
|
+
if (block.isGiven()) {
|
723
|
+
IRubyObject boundSelf = block.getBinding().getSelf();
|
724
|
+
if (boundSelf instanceof XmlNode) { return (XmlNode) boundSelf; }
|
725
|
+
}
|
726
|
+
return this;
|
727
|
+
}
|
728
|
+
|
729
|
+
public void
|
730
|
+
resetNamespaceCache(ThreadContext context)
|
731
|
+
{
|
732
|
+
nsCache = new NokogiriNamespaceCache();
|
733
|
+
createAndCacheNamespaces(context.runtime, node);
|
734
|
+
}
|
633
735
|
}
|