@xmldom/xmldom 0.9.0-beta.3 → 0.9.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/lib/.eslintrc.yml +1 -0
- package/lib/conventions.js +27 -29
- package/lib/dom-parser.js +141 -139
- package/lib/dom.js +859 -716
- package/lib/entities.js +250 -244
- package/lib/index.js +5 -5
- package/lib/sax.js +442 -437
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.9.0-beta.4](https://github.com/xmldom/xmldom/compare/0.9.0-beta.3...0.9.0-beta.4)
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Security: Prevent inserting DOM nodes when they are not well-formed [`CVE-2022-39353`](https://github.com/xmldom/xmldom/security/advisories/GHSA-crh6-fp67-6883)
|
|
12
|
+
In case such a DOM would be created, the part that is not well-formed will be transformed into text nodes, in which xml specific characters like `<` and `>` are encoded accordingly.
|
|
13
|
+
In the upcoming version 0.9.0 those text nodes will no longer be added and an error will be thrown instead.
|
|
14
|
+
This change can break your code, if you relied on this behavior, e.g. multiple root elements in the past. We consider it more important to align with the specs that we want to be aligned with, considering the potential security issues that might derive from people not being aware of the difference in behavior.
|
|
15
|
+
Related Spec: <https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity>
|
|
16
|
+
|
|
17
|
+
### Chore
|
|
18
|
+
|
|
19
|
+
- update multiple devDependencies
|
|
20
|
+
- Add eslint-plugin-node for `lib` [`#448`](https://github.com/xmldom/xmldom/pull/448) / [`#190`](https://github.com/xmldom/xmldom/issues/190)
|
|
21
|
+
- style: Apply prettier to all code [`#447`](https://github.com/xmldom/xmldom/pull/447) / [`#29`](https://github.com/xmldom/xmldom/issues/29) / [`#130`](https://github.com/xmldom/xmldom/issues/130)
|
|
22
|
+
|
|
23
|
+
Thank you, [@XhmikosR](https://github.com/XhmikosR), [@awwright](https://github.com/awwright), [@frumioj](https://github.com/frumioj), [@cjbarth](https://github.com/cjbarth), [@markgollnick](https://github.com/markgollnick) for your contributions
|
|
24
|
+
|
|
7
25
|
## [0.9.0-beta.3](https://github.com/xmldom/xmldom/compare/0.9.0-beta.2...0.9.0-beta.3)
|
|
8
26
|
|
|
9
27
|
### Fixed
|
package/lib/.eslintrc.yml
CHANGED
package/lib/conventions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* "Shallow freezes" an object to render it immutable.
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
*/
|
|
18
18
|
function freeze(object, oc) {
|
|
19
19
|
if (oc === undefined) {
|
|
20
|
-
oc = Object
|
|
20
|
+
oc = Object;
|
|
21
21
|
}
|
|
22
|
-
return oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object
|
|
22
|
+
return oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -37,14 +37,14 @@ function freeze(object, oc) {
|
|
|
37
37
|
*/
|
|
38
38
|
function assign(target, source) {
|
|
39
39
|
if (target === null || typeof target !== 'object') {
|
|
40
|
-
throw new TypeError('target is not an object')
|
|
40
|
+
throw new TypeError('target is not an object');
|
|
41
41
|
}
|
|
42
42
|
for (var key in source) {
|
|
43
43
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
44
|
-
target[key] = source[key]
|
|
44
|
+
target[key] = source[key];
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
return target
|
|
47
|
+
return target;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
@@ -87,7 +87,7 @@ var HTML_BOOLEAN_ATTRIBUTES = freeze({
|
|
|
87
87
|
required: true,
|
|
88
88
|
reversed: true,
|
|
89
89
|
selected: true,
|
|
90
|
-
})
|
|
90
|
+
});
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
93
|
* Check if `name` is matching one of the HTML boolean attribute names.
|
|
@@ -100,7 +100,7 @@ var HTML_BOOLEAN_ATTRIBUTES = freeze({
|
|
|
100
100
|
* @see https://html.spec.whatwg.org/#attributes-3
|
|
101
101
|
*/
|
|
102
102
|
function isHTMLBooleanAttribute(name) {
|
|
103
|
-
return HTML_BOOLEAN_ATTRIBUTES.hasOwnProperty(name.toLowerCase())
|
|
103
|
+
return HTML_BOOLEAN_ATTRIBUTES.hasOwnProperty(name.toLowerCase());
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
/**
|
|
@@ -131,7 +131,7 @@ var HTML_VOID_ELEMENTS = freeze({
|
|
|
131
131
|
source: true,
|
|
132
132
|
track: true,
|
|
133
133
|
wbr: true,
|
|
134
|
-
})
|
|
134
|
+
});
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
137
|
* Check if `tagName` is matching one of the HTML void element names.
|
|
@@ -144,7 +144,7 @@ var HTML_VOID_ELEMENTS = freeze({
|
|
|
144
144
|
* @see https://html.spec.whatwg.org/#void-elements
|
|
145
145
|
*/
|
|
146
146
|
function isHTMLVoidElement(tagName) {
|
|
147
|
-
return HTML_VOID_ELEMENTS.hasOwnProperty(tagName.toLowerCase())
|
|
147
|
+
return HTML_VOID_ELEMENTS.hasOwnProperty(tagName.toLowerCase());
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
/**
|
|
@@ -161,7 +161,7 @@ var HTML_RAW_TEXT_ELEMENTS = freeze({
|
|
|
161
161
|
style: false,
|
|
162
162
|
textarea: true,
|
|
163
163
|
title: true,
|
|
164
|
-
})
|
|
164
|
+
});
|
|
165
165
|
|
|
166
166
|
/**
|
|
167
167
|
* Check if `tagName` is matching one of the HTML raw text element names.
|
|
@@ -227,7 +227,7 @@ var MIME_TYPE = freeze({
|
|
|
227
227
|
* @see [`DOMParser.parseFromString` @ HTML Specification](https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring)
|
|
228
228
|
*/
|
|
229
229
|
isHTML: function (value) {
|
|
230
|
-
return value === MIME_TYPE.HTML
|
|
230
|
+
return value === MIME_TYPE.HTML;
|
|
231
231
|
},
|
|
232
232
|
|
|
233
233
|
/**
|
|
@@ -242,9 +242,7 @@ var MIME_TYPE = freeze({
|
|
|
242
242
|
* @see https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
|
|
243
243
|
*/
|
|
244
244
|
hasDefaultHTMLNamespace: function (mimeType) {
|
|
245
|
-
return (
|
|
246
|
-
MIME_TYPE.isHTML(mimeType) || mimeType === MIME_TYPE.XML_XHTML_APPLICATION
|
|
247
|
-
)
|
|
245
|
+
return MIME_TYPE.isHTML(mimeType) || mimeType === MIME_TYPE.XML_XHTML_APPLICATION;
|
|
248
246
|
},
|
|
249
247
|
|
|
250
248
|
/**
|
|
@@ -283,7 +281,7 @@ var MIME_TYPE = freeze({
|
|
|
283
281
|
* @see https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Wikipedia
|
|
284
282
|
*/
|
|
285
283
|
XML_SVG_IMAGE: 'image/svg+xml',
|
|
286
|
-
})
|
|
284
|
+
});
|
|
287
285
|
|
|
288
286
|
/**
|
|
289
287
|
* Namespaces that are used in this code base.
|
|
@@ -306,7 +304,7 @@ var NAMESPACE = freeze({
|
|
|
306
304
|
* @see NAMESPACE.HTML
|
|
307
305
|
*/
|
|
308
306
|
isHTML: function (uri) {
|
|
309
|
-
return uri === NAMESPACE.HTML
|
|
307
|
+
return uri === NAMESPACE.HTML;
|
|
310
308
|
},
|
|
311
309
|
|
|
312
310
|
/**
|
|
@@ -329,16 +327,16 @@ var NAMESPACE = freeze({
|
|
|
329
327
|
* @see https://www.w3.org/2000/xmlns/
|
|
330
328
|
*/
|
|
331
329
|
XMLNS: 'http://www.w3.org/2000/xmlns/',
|
|
332
|
-
})
|
|
330
|
+
});
|
|
333
331
|
|
|
334
|
-
exports.assign = assign
|
|
335
|
-
exports.freeze = freeze
|
|
336
|
-
exports.HTML_BOOLEAN_ATTRIBUTES = HTML_BOOLEAN_ATTRIBUTES
|
|
337
|
-
exports.HTML_RAW_TEXT_ELEMENTS = HTML_RAW_TEXT_ELEMENTS
|
|
338
|
-
exports.HTML_VOID_ELEMENTS = HTML_VOID_ELEMENTS
|
|
339
|
-
exports.isHTMLBooleanAttribute = isHTMLBooleanAttribute
|
|
340
|
-
exports.isHTMLRawTextElement = isHTMLRawTextElement
|
|
341
|
-
exports.isHTMLEscapableRawTextElement = isHTMLEscapableRawTextElement
|
|
342
|
-
exports.isHTMLVoidElement = isHTMLVoidElement
|
|
343
|
-
exports.MIME_TYPE = MIME_TYPE
|
|
344
|
-
exports.NAMESPACE = NAMESPACE
|
|
332
|
+
exports.assign = assign;
|
|
333
|
+
exports.freeze = freeze;
|
|
334
|
+
exports.HTML_BOOLEAN_ATTRIBUTES = HTML_BOOLEAN_ATTRIBUTES;
|
|
335
|
+
exports.HTML_RAW_TEXT_ELEMENTS = HTML_RAW_TEXT_ELEMENTS;
|
|
336
|
+
exports.HTML_VOID_ELEMENTS = HTML_VOID_ELEMENTS;
|
|
337
|
+
exports.isHTMLBooleanAttribute = isHTMLBooleanAttribute;
|
|
338
|
+
exports.isHTMLRawTextElement = isHTMLRawTextElement;
|
|
339
|
+
exports.isHTMLEscapableRawTextElement = isHTMLEscapableRawTextElement;
|
|
340
|
+
exports.isHTMLVoidElement = isHTMLVoidElement;
|
|
341
|
+
exports.MIME_TYPE = MIME_TYPE;
|
|
342
|
+
exports.NAMESPACE = NAMESPACE;
|
package/lib/dom-parser.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
|
-
var conventions = require(
|
|
4
|
-
var dom = require('./dom')
|
|
3
|
+
var conventions = require('./conventions');
|
|
4
|
+
var dom = require('./dom');
|
|
5
5
|
var entities = require('./entities');
|
|
6
6
|
var sax = require('./sax');
|
|
7
7
|
|
|
@@ -35,9 +35,7 @@ var XMLReader = sax.XMLReader;
|
|
|
35
35
|
* @returns {string}
|
|
36
36
|
*/
|
|
37
37
|
function normalizeLineEndings(input) {
|
|
38
|
-
return input
|
|
39
|
-
.replace(/\r[\n\u0085]/g, '\n')
|
|
40
|
-
.replace(/[\r\u0085\u2028]/g, '\n')
|
|
38
|
+
return input.replace(/\r[\n\u0085]/g, '\n').replace(/[\r\u0085\u2028]/g, '\n');
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
/**
|
|
@@ -85,9 +83,8 @@ function normalizeLineEndings(input) {
|
|
|
85
83
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
|
|
86
84
|
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-parsing-and-serialization
|
|
87
85
|
*/
|
|
88
|
-
function DOMParser(options){
|
|
89
|
-
|
|
90
|
-
options = options || {locator:true};
|
|
86
|
+
function DOMParser(options) {
|
|
87
|
+
options = options || { locator: true };
|
|
91
88
|
|
|
92
89
|
/**
|
|
93
90
|
* The method to use instead of `Object.assign` (or if not available `conventions.assign`),
|
|
@@ -98,7 +95,7 @@ function DOMParser(options){
|
|
|
98
95
|
* @private
|
|
99
96
|
* @see conventions.assign
|
|
100
97
|
*/
|
|
101
|
-
this.assign = options.assign || Object.assign || conventions.assign
|
|
98
|
+
this.assign = options.assign || Object.assign || conventions.assign;
|
|
102
99
|
|
|
103
100
|
/**
|
|
104
101
|
* For internal testing: The class for creating an instance for handling events from the SAX parser.
|
|
@@ -108,7 +105,7 @@ function DOMParser(options){
|
|
|
108
105
|
* @readonly
|
|
109
106
|
* @private
|
|
110
107
|
*/
|
|
111
|
-
this.domHandler = options.domHandler || DOMHandler
|
|
108
|
+
this.domHandler = options.domHandler || DOMHandler;
|
|
112
109
|
|
|
113
110
|
/**
|
|
114
111
|
* A function that can be invoked as the errorHandler instead of the default ones.
|
|
@@ -123,7 +120,7 @@ function DOMParser(options){
|
|
|
123
120
|
* @type {(string) => string}
|
|
124
121
|
* @readonly
|
|
125
122
|
*/
|
|
126
|
-
this.normalizeLineEndings = options.normalizeLineEndings || normalizeLineEndings
|
|
123
|
+
this.normalizeLineEndings = options.normalizeLineEndings || normalizeLineEndings;
|
|
127
124
|
|
|
128
125
|
/**
|
|
129
126
|
* Configures if the nodes created during parsing
|
|
@@ -133,7 +130,7 @@ function DOMParser(options){
|
|
|
133
130
|
* @type {boolean}
|
|
134
131
|
* @readonly
|
|
135
132
|
*/
|
|
136
|
-
this.locator = !!options.locator
|
|
133
|
+
this.locator = !!options.locator;
|
|
137
134
|
|
|
138
135
|
/**
|
|
139
136
|
* The default namespace can be provided by the key that is the empty string.
|
|
@@ -143,7 +140,7 @@ function DOMParser(options){
|
|
|
143
140
|
* @type {Readonly<object>}
|
|
144
141
|
* @readonly
|
|
145
142
|
*/
|
|
146
|
-
this.xmlns = options.xmlns || {}
|
|
143
|
+
this.xmlns = options.xmlns || {};
|
|
147
144
|
}
|
|
148
145
|
|
|
149
146
|
/**
|
|
@@ -175,55 +172,63 @@ function DOMParser(options){
|
|
|
175
172
|
* @see https://html.spec.whatwg.org/#dom-domparser-parsefromstring-dev
|
|
176
173
|
*/
|
|
177
174
|
DOMParser.prototype.parseFromString = function (source, mimeType) {
|
|
178
|
-
var defaultNSMap = this.assign({}, this.xmlns)
|
|
179
|
-
var entityMap = entities.XML_ENTITIES
|
|
180
|
-
var defaultNamespace = defaultNSMap[''] || null
|
|
175
|
+
var defaultNSMap = this.assign({}, this.xmlns);
|
|
176
|
+
var entityMap = entities.XML_ENTITIES;
|
|
177
|
+
var defaultNamespace = defaultNSMap[''] || null;
|
|
181
178
|
if (MIME_TYPE.hasDefaultHTMLNamespace(mimeType)) {
|
|
182
|
-
entityMap = entities.HTML_ENTITIES
|
|
183
|
-
defaultNamespace = NAMESPACE.HTML
|
|
179
|
+
entityMap = entities.HTML_ENTITIES;
|
|
180
|
+
defaultNamespace = NAMESPACE.HTML;
|
|
184
181
|
} else if (mimeType === MIME_TYPE.XML_SVG_IMAGE) {
|
|
185
|
-
defaultNamespace = NAMESPACE.SVG
|
|
182
|
+
defaultNamespace = NAMESPACE.SVG;
|
|
186
183
|
}
|
|
187
|
-
defaultNSMap[''] = defaultNamespace
|
|
188
|
-
defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML
|
|
184
|
+
defaultNSMap[''] = defaultNamespace;
|
|
185
|
+
defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML;
|
|
189
186
|
|
|
190
187
|
var domBuilder = new this.domHandler({
|
|
191
188
|
mimeType: mimeType,
|
|
192
189
|
defaultNamespace: defaultNamespace,
|
|
193
|
-
})
|
|
190
|
+
});
|
|
194
191
|
var locator = this.locator ? {} : undefined;
|
|
195
192
|
if (this.locator) {
|
|
196
|
-
domBuilder.setDocumentLocator(locator)
|
|
193
|
+
domBuilder.setDocumentLocator(locator);
|
|
197
194
|
}
|
|
198
195
|
|
|
199
|
-
var sax = new XMLReader()
|
|
200
|
-
sax.errorHandler = buildErrorHandler(this.errorHandler, domBuilder, locator)
|
|
201
|
-
sax.domBuilder = domBuilder
|
|
196
|
+
var sax = new XMLReader();
|
|
197
|
+
sax.errorHandler = buildErrorHandler(this.errorHandler, domBuilder, locator);
|
|
198
|
+
sax.domBuilder = domBuilder;
|
|
202
199
|
if (source && typeof source === 'string') {
|
|
203
|
-
sax.parse(this.normalizeLineEndings(source), defaultNSMap, entityMap)
|
|
200
|
+
sax.parse(this.normalizeLineEndings(source), defaultNSMap, entityMap);
|
|
204
201
|
} else {
|
|
205
|
-
sax.errorHandler.error('invalid doc source')
|
|
202
|
+
sax.errorHandler.error('invalid doc source');
|
|
206
203
|
}
|
|
207
|
-
return domBuilder.doc
|
|
208
|
-
}
|
|
209
|
-
function buildErrorHandler(errorImpl,domBuilder,locator){
|
|
210
|
-
if(!errorImpl){
|
|
211
|
-
if(domBuilder instanceof DOMHandler){
|
|
204
|
+
return domBuilder.doc;
|
|
205
|
+
};
|
|
206
|
+
function buildErrorHandler(errorImpl, domBuilder, locator) {
|
|
207
|
+
if (!errorImpl) {
|
|
208
|
+
if (domBuilder instanceof DOMHandler) {
|
|
212
209
|
return domBuilder;
|
|
213
210
|
}
|
|
214
|
-
errorImpl = domBuilder
|
|
211
|
+
errorImpl = domBuilder;
|
|
215
212
|
}
|
|
216
|
-
var errorHandler = {}
|
|
213
|
+
var errorHandler = {};
|
|
217
214
|
var isCallback = errorImpl instanceof Function;
|
|
218
|
-
locator = locator||{}
|
|
219
|
-
function build(key){
|
|
215
|
+
locator = locator || {};
|
|
216
|
+
function build(key) {
|
|
220
217
|
var fn = errorImpl[key];
|
|
221
|
-
if(!fn && isCallback){
|
|
222
|
-
fn =
|
|
218
|
+
if (!fn && isCallback) {
|
|
219
|
+
fn =
|
|
220
|
+
errorImpl.length == 2
|
|
221
|
+
? function (msg) {
|
|
222
|
+
errorImpl(key, msg);
|
|
223
|
+
}
|
|
224
|
+
: errorImpl;
|
|
223
225
|
}
|
|
224
|
-
errorHandler[key] =
|
|
225
|
-
fn
|
|
226
|
-
|
|
226
|
+
errorHandler[key] =
|
|
227
|
+
(fn &&
|
|
228
|
+
function (msg) {
|
|
229
|
+
fn('[xmldom ' + key + ']\t' + msg + _locator(locator));
|
|
230
|
+
}) ||
|
|
231
|
+
function () {};
|
|
227
232
|
}
|
|
228
233
|
build('warning');
|
|
229
234
|
build('error');
|
|
@@ -247,7 +252,7 @@ function buildErrorHandler(errorImpl,domBuilder,locator){
|
|
|
247
252
|
* @see http://www.saxproject.org/apidoc/org/xml/sax/ext/DefaultHandler2.html
|
|
248
253
|
*/
|
|
249
254
|
function DOMHandler(options) {
|
|
250
|
-
var opt = options || {}
|
|
255
|
+
var opt = options || {};
|
|
251
256
|
/**
|
|
252
257
|
* The mime type is used to determine if the DOM handler will create an XML or HTML document.
|
|
253
258
|
* Only if it is set to `text/html` it will create an HTML document.
|
|
@@ -257,7 +262,7 @@ function DOMHandler(options) {
|
|
|
257
262
|
* @readonly
|
|
258
263
|
* @see MIME_TYPE
|
|
259
264
|
*/
|
|
260
|
-
this.mimeType = opt.mimeType || MIME_TYPE.XML_APPLICATION
|
|
265
|
+
this.mimeType = opt.mimeType || MIME_TYPE.XML_APPLICATION;
|
|
261
266
|
|
|
262
267
|
/**
|
|
263
268
|
* The namespace to use to create an XML document.
|
|
@@ -273,14 +278,13 @@ function DOMHandler(options) {
|
|
|
273
278
|
* @readonly
|
|
274
279
|
* @private
|
|
275
280
|
*/
|
|
276
|
-
this.defaultNamespace = opt.defaultNamespace || null
|
|
281
|
+
this.defaultNamespace = opt.defaultNamespace || null;
|
|
277
282
|
|
|
278
283
|
/**
|
|
279
284
|
* @private
|
|
280
285
|
* @type {boolean}
|
|
281
286
|
*/
|
|
282
|
-
this.cdata = false
|
|
283
|
-
|
|
287
|
+
this.cdata = false;
|
|
284
288
|
|
|
285
289
|
/**
|
|
286
290
|
* The last `Element` that was created by `startElement`.
|
|
@@ -291,7 +295,7 @@ function DOMHandler(options) {
|
|
|
291
295
|
* @type {Element | Node | undefined}
|
|
292
296
|
* @private
|
|
293
297
|
*/
|
|
294
|
-
this.currentElement = undefined
|
|
298
|
+
this.currentElement = undefined;
|
|
295
299
|
|
|
296
300
|
/**
|
|
297
301
|
* The Document that is created as part of `startDocument`,
|
|
@@ -300,7 +304,7 @@ function DOMHandler(options) {
|
|
|
300
304
|
* @type {Document | undefined}
|
|
301
305
|
* @readonly
|
|
302
306
|
*/
|
|
303
|
-
this.doc = undefined
|
|
307
|
+
this.doc = undefined;
|
|
304
308
|
|
|
305
309
|
/**
|
|
306
310
|
* The locator is stored as part of setDocumentLocator.
|
|
@@ -313,9 +317,9 @@ function DOMHandler(options) {
|
|
|
313
317
|
* @readonly (the sax parser currently sometimes set's it)
|
|
314
318
|
* @private
|
|
315
319
|
*/
|
|
316
|
-
this.locator = undefined
|
|
320
|
+
this.locator = undefined;
|
|
317
321
|
}
|
|
318
|
-
function position(locator,node){
|
|
322
|
+
function position(locator, node) {
|
|
319
323
|
node.lineNumber = locator.lineNumber;
|
|
320
324
|
node.columnNumber = locator.columnNumber;
|
|
321
325
|
}
|
|
@@ -328,67 +332,59 @@ DOMHandler.prototype = {
|
|
|
328
332
|
*
|
|
329
333
|
* @see http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
|
|
330
334
|
*/
|
|
331
|
-
startDocument
|
|
332
|
-
var impl = new DOMImplementation()
|
|
333
|
-
this.doc = MIME_TYPE.isHTML(this.mimeType)
|
|
334
|
-
? impl.createHTMLDocument(false)
|
|
335
|
-
: impl.createDocument(this.defaultNamespace, '')
|
|
335
|
+
startDocument: function () {
|
|
336
|
+
var impl = new DOMImplementation();
|
|
337
|
+
this.doc = MIME_TYPE.isHTML(this.mimeType) ? impl.createHTMLDocument(false) : impl.createDocument(this.defaultNamespace, '');
|
|
336
338
|
},
|
|
337
|
-
startElement:function(namespaceURI, localName, qName, attrs) {
|
|
339
|
+
startElement: function (namespaceURI, localName, qName, attrs) {
|
|
338
340
|
var doc = this.doc;
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
341
|
+
var el = doc.createElementNS(namespaceURI, qName || localName);
|
|
342
|
+
var len = attrs.length;
|
|
343
|
+
appendElement(this, el);
|
|
344
|
+
this.currentElement = el;
|
|
343
345
|
|
|
344
|
-
this.locator && position(this.locator,el)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
346
|
+
this.locator && position(this.locator, el);
|
|
347
|
+
for (var i = 0; i < len; i++) {
|
|
348
|
+
var namespaceURI = attrs.getURI(i);
|
|
349
|
+
var value = attrs.getValue(i);
|
|
350
|
+
var qName = attrs.getQName(i);
|
|
349
351
|
var attr = doc.createAttributeNS(namespaceURI, qName);
|
|
350
|
-
this.locator &&position(attrs.getLocator(i),attr);
|
|
352
|
+
this.locator && position(attrs.getLocator(i), attr);
|
|
351
353
|
attr.value = attr.nodeValue = value;
|
|
352
|
-
el.setAttributeNode(attr)
|
|
353
|
-
|
|
354
|
-
},
|
|
355
|
-
endElement:function(namespaceURI, localName, qName) {
|
|
356
|
-
var current = this.currentElement
|
|
357
|
-
var tagName = current.tagName;
|
|
358
|
-
this.currentElement = current.parentNode;
|
|
359
|
-
},
|
|
360
|
-
startPrefixMapping:function(prefix, uri) {
|
|
361
|
-
},
|
|
362
|
-
endPrefixMapping:function(prefix) {
|
|
354
|
+
el.setAttributeNode(attr);
|
|
355
|
+
}
|
|
363
356
|
},
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
this.locator && position(this.locator,ins)
|
|
367
|
-
appendElement(this, ins);
|
|
357
|
+
endElement: function (namespaceURI, localName, qName) {
|
|
358
|
+
this.currentElement = this.currentElement.parentNode;
|
|
368
359
|
},
|
|
369
|
-
|
|
360
|
+
startPrefixMapping: function (prefix, uri) {},
|
|
361
|
+
endPrefixMapping: function (prefix) {},
|
|
362
|
+
processingInstruction: function (target, data) {
|
|
363
|
+
var ins = this.doc.createProcessingInstruction(target, data);
|
|
364
|
+
this.locator && position(this.locator, ins);
|
|
365
|
+
appendElement(this, ins);
|
|
370
366
|
},
|
|
371
|
-
|
|
372
|
-
|
|
367
|
+
ignorableWhitespace: function (ch, start, length) {},
|
|
368
|
+
characters: function (chars, start, length) {
|
|
369
|
+
chars = _toString.apply(this, arguments);
|
|
373
370
|
//console.log(chars)
|
|
374
|
-
if(chars){
|
|
371
|
+
if (chars) {
|
|
375
372
|
if (this.cdata) {
|
|
376
373
|
var charNode = this.doc.createCDATASection(chars);
|
|
377
374
|
} else {
|
|
378
375
|
var charNode = this.doc.createTextNode(chars);
|
|
379
376
|
}
|
|
380
|
-
if(this.currentElement){
|
|
377
|
+
if (this.currentElement) {
|
|
381
378
|
this.currentElement.appendChild(charNode);
|
|
382
|
-
}else if(/^\s*$/.test(chars)){
|
|
379
|
+
} else if (/^\s*$/.test(chars)) {
|
|
383
380
|
this.doc.appendChild(charNode);
|
|
384
381
|
//process xml
|
|
385
382
|
}
|
|
386
|
-
this.locator && position(this.locator,charNode)
|
|
383
|
+
this.locator && position(this.locator, charNode);
|
|
387
384
|
}
|
|
388
385
|
},
|
|
389
|
-
skippedEntity:function(name) {
|
|
390
|
-
|
|
391
|
-
endDocument:function() {
|
|
386
|
+
skippedEntity: function (name) {},
|
|
387
|
+
endDocument: function () {
|
|
392
388
|
this.doc.normalize();
|
|
393
389
|
},
|
|
394
390
|
/**
|
|
@@ -397,62 +393,63 @@ DOMHandler.prototype = {
|
|
|
397
393
|
*
|
|
398
394
|
* @param {Locator} locator
|
|
399
395
|
*/
|
|
400
|
-
setDocumentLocator:function (locator) {
|
|
396
|
+
setDocumentLocator: function (locator) {
|
|
401
397
|
if (locator) {
|
|
402
|
-
locator.lineNumber = 0
|
|
398
|
+
locator.lineNumber = 0;
|
|
403
399
|
}
|
|
404
|
-
this.locator = locator
|
|
400
|
+
this.locator = locator;
|
|
405
401
|
},
|
|
406
402
|
//LexicalHandler
|
|
407
|
-
comment:function(chars, start, length) {
|
|
408
|
-
chars = _toString.apply(this,arguments)
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
403
|
+
comment: function (chars, start, length) {
|
|
404
|
+
chars = _toString.apply(this, arguments);
|
|
405
|
+
var comm = this.doc.createComment(chars);
|
|
406
|
+
this.locator && position(this.locator, comm);
|
|
407
|
+
appendElement(this, comm);
|
|
412
408
|
},
|
|
413
409
|
|
|
414
|
-
startCDATA:function() {
|
|
415
|
-
|
|
416
|
-
|
|
410
|
+
startCDATA: function () {
|
|
411
|
+
//used in characters() methods
|
|
412
|
+
this.cdata = true;
|
|
417
413
|
},
|
|
418
|
-
endCDATA:function() {
|
|
419
|
-
|
|
414
|
+
endCDATA: function () {
|
|
415
|
+
this.cdata = false;
|
|
420
416
|
},
|
|
421
417
|
|
|
422
|
-
startDTD:function(name, publicId, systemId) {
|
|
418
|
+
startDTD: function (name, publicId, systemId) {
|
|
423
419
|
var impl = this.doc.implementation;
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
420
|
+
if (impl && impl.createDocumentType) {
|
|
421
|
+
var dt = impl.createDocumentType(name, publicId, systemId);
|
|
422
|
+
this.locator && position(this.locator, dt);
|
|
423
|
+
appendElement(this, dt);
|
|
424
|
+
this.doc.doctype = dt;
|
|
425
|
+
}
|
|
430
426
|
},
|
|
431
427
|
/**
|
|
432
428
|
* @see org.xml.sax.ErrorHandler
|
|
433
429
|
* @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
|
|
434
430
|
*/
|
|
435
|
-
warning:function(error) {
|
|
436
|
-
console.warn('[xmldom warning]\t'+error,_locator(this.locator));
|
|
431
|
+
warning: function (error) {
|
|
432
|
+
console.warn('[xmldom warning]\t' + error, _locator(this.locator));
|
|
437
433
|
},
|
|
438
|
-
error:function(error) {
|
|
439
|
-
console.error('[xmldom error]\t'+error,_locator(this.locator));
|
|
434
|
+
error: function (error) {
|
|
435
|
+
console.error('[xmldom error]\t' + error, _locator(this.locator));
|
|
440
436
|
},
|
|
441
|
-
fatalError:function(error) {
|
|
437
|
+
fatalError: function (error) {
|
|
442
438
|
throw new ParseError(error, this.locator);
|
|
439
|
+
},
|
|
440
|
+
};
|
|
441
|
+
function _locator(l) {
|
|
442
|
+
if (l) {
|
|
443
|
+
return '\n@#[line:' + l.lineNumber + ',col:' + l.columnNumber + ']';
|
|
443
444
|
}
|
|
444
445
|
}
|
|
445
|
-
function
|
|
446
|
-
if(
|
|
447
|
-
return
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
return chars.substr(start,length)
|
|
453
|
-
}else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
|
|
454
|
-
if(chars.length >= start+length || start){
|
|
455
|
-
return new java.lang.String(chars,start,length)+'';
|
|
446
|
+
function _toString(chars, start, length) {
|
|
447
|
+
if (typeof chars == 'string') {
|
|
448
|
+
return chars.substr(start, length);
|
|
449
|
+
} else {
|
|
450
|
+
//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
|
|
451
|
+
if (chars.length >= start + length || start) {
|
|
452
|
+
return new java.lang.String(chars, start, length) + '';
|
|
456
453
|
}
|
|
457
454
|
return chars;
|
|
458
455
|
}
|
|
@@ -489,18 +486,23 @@ function _toString(chars,start,length){
|
|
|
489
486
|
* #notationDecl(name, publicId, systemId) {};
|
|
490
487
|
* #unparsedEntityDecl(name, publicId, systemId, notationName) {};
|
|
491
488
|
*/
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
489
|
+
'endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl'.replace(
|
|
490
|
+
/\w+/g,
|
|
491
|
+
function (key) {
|
|
492
|
+
DOMHandler.prototype[key] = function () {
|
|
493
|
+
return null;
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
);
|
|
495
497
|
|
|
496
498
|
/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
|
|
497
|
-
function appendElement
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
}//appendChild and setAttributeNS are preformance key
|
|
499
|
+
function appendElement(hander, node) {
|
|
500
|
+
if (!hander.currentElement) {
|
|
501
|
+
hander.doc.appendChild(node);
|
|
502
|
+
} else {
|
|
503
|
+
hander.currentElement.appendChild(node);
|
|
504
|
+
}
|
|
505
|
+
} //appendChild and setAttributeNS are preformance key
|
|
504
506
|
|
|
505
507
|
exports.__DOMHandler = DOMHandler;
|
|
506
508
|
exports.normalizeLineEndings = normalizeLineEndings;
|