Add capacitorjs runtime

This commit is contained in:
olcxja 2026-05-03 17:09:55 +02:00
commit f90c0e6c40
8362 changed files with 1502407 additions and 1 deletions

13
node_modules/mergexml/LICENSE generated vendored Normal file
View file

@ -0,0 +1,13 @@
Copyright (c) 2015, Vallo Reima <vallo@vregistry.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

166
node_modules/mergexml/README.md generated vendored Normal file
View file

@ -0,0 +1,166 @@
JS MergeXML [![npm version](https://badge.fury.io/js/mergexml.svg)](https://badge.fury.io/js/mergexml)
==================
MergeXML merges the XML sources (files, strings, objects) into single DOM XML object.
The merging is performed recursively on the node level adding new elements and replacing existing ones.
The nodes with the same path/name are replaced/added sequentially and the modification can be controlled by the options.
MergeXML could be useful in cases where it is necessary to gather XML data from multiple sources.
For example, to combine configuration files of different subsystems depending on the application logic.
Main browsers (Chrome, Edge, IE, Firefox, Safari, Opera) and NodeJS (see below) are supported. The MergeXML is realized also in PHP (see [php-merge-xml]).
The usage
-----
MergeXML class can be included:
1. loading as a CommonJS module:
**`const MergeXML = require('./mergexml');`**
2. as a global script:
**`<script src="mergexml.js"></script>`**
The class instantiation:
>var oMX = new MergeXML([opts]);
or loading and instantiating at once:
>const oMX = new (require('./mergexml.js'))([opts]);
**opts** - the options object:
- join - common root name if any source has different root name (default is *root*, specifying *false* denies different names)
- updn - traverse the nodes by name sequence (*true*, default) or overall sequence (*false*)
- stay - the *stay* attribute value to deny overwriting of specific node (default is *all*, can be array of values or empty)
- path - require path to NodeJS modules (default is looking from *node_modules*, N/A for browsers)
**oMX.AddSource(source)**;
> source - XML string or DOM object
**oMX.AddFile(elem)**;
> elem - FileList element of the XML file (browsers only)
The methods merge a sequent source and return the final object or *false* if failed (see *error* property below).
**oMX.Init([opts])**;
Clear existing result to restart.
> opts - the options object as above (except *path*)
You can search in the result object:
**oMX.Query(expr)**;
> expr - XPath query expression
You can get the XML result tree:
**oMX.Get([0|1|2])**;
- 0 - object (default)
- 1 - text
- 2 - html
The result object can be accessed also via *oMX.dom* property. The properties available:
- **dom** - result XML DOM object (in older IE browsers this is an ActiveX Object, not a standard XML Document)
- **nsp** - namespaces list object (prefix:URI)
- **count** - number of sources merged
- **error** - error information
- error.code ('' is ok)
- error.text
The sources must have the same default namespace (if have at all).
Prefix '_' is reserved to handle the default namespace.
IE doesn't allow replacement of the root node attributes.
Installation
------------
Run from the appropriate directory:
>npm install mergexml
Or manually download the [js-merge-xml] package from Github and unzip the files into installation directory.
Run the sample in your browser (**HTML5** compatible):
1. open *example.html*
2. choose the *xml* files to be merged (*test* folder)
3. click *Merge* button
4. the merged *xml* is displayed...
The tests
--------
To run the browsers' tests from the CLI:
1. go to installation directory
2. install framework: `npm install --dev`
3. run the tests: `npm test`
4. the results are displayed...
5. to remove the test modules: `npm prune --prod`
NodeJS
------
The browser window objects' (*DOMParser, XPathEvaluator, XMLSerializer*) functionality is implemented by the *xpath, xmldom* modules as node global objects. The sample requires also the *formidable* module.
Install the dependent modules:
>npm install --prod
Start NodeJS with the sample script:
>node examplen.js
Run the sample in your browser:
>http://localhost:3000
The package
------
The following files are included:
1. *mergexml.js* - MergeXML class supporting the browser and NodeJS environments;
2. *example.html* - multi-selects the xml files and displays result (browser);
3. *example.js* - passes the xml data and returns result (browser);
4. *examplen.htm* - client-side template to multi-select the xml files and display result (NodeJS);
5. *examplen.js* - server-side module to receive requests and response results (NodeJS);
6. *package.json, bower.json* - package details;
7. *test* - a folder with the (browser) testing files.
ChangeLog
---------
June/July 2015 (Martijn van de Rijdt)
- *mergexml.js*
- the wrapper is added for a compatibility with the AMD/CommonJS-like environments
- *test*
- automated browser tests
October 2016 (Martijn van de Rijdt)
- *mergexml.js*
- cloning the namespaced attributes correctly
- mixing sources of undeclared encoding
August 2019 (Vallo Reima)
- *mergexml.js*
- NodeJS environment support
- *examplen.js, examplen.htm*
- NodeJS usage sample
September 2021 (eyelidlessness)
- *mergexml.js*
- Upgrade xmldom to @xmldom/xmldom
[php-merge-xml]: http://www.github.com/hareko/php-merge-xml
[js-merge-xml]: http://www.github.com/hareko/js-merge-xml

25
node_modules/mergexml/bower.json generated vendored Normal file
View file

@ -0,0 +1,25 @@
{
"name": "mergexml",
"version": "1.2.4",
"description": "Merge multiple XML sources",
"main": "mergexml.js",
"moduleType": [
"amd",
"globals",
"node"
],
"keywords": [
"xml",
"merge"
],
"authors": [
"Vallo Reima"
],
"license": "ISC",
"homepage": "vregistry.com",
"ignore": [
"**/.*",
"node_modules",
"bower_components"
]
}

47
node_modules/mergexml/example.html generated vendored Normal file
View file

@ -0,0 +1,47 @@
<!--
/**
* JS MergeXML browser usage sample
* merge multi-select local xml files
*
* @package MergeXML
* @author Vallo Reima
* @copyright (C)2014
*/
-->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>JS MergeXML usage sample</title>
<style>
button, p {
font-weight: bold;
}
span {
font-weight: normal;
}
div {
font-family: monospace;
width: 600px;
height: 600px;
border: 1px solid grey;
overflow: auto;
padding: 5px;
}
</style>
<script src="mergexml.js"></script>
<script src="example.js"></script>
<script>
window.onload = Example;
</script>
</head>
<body>
<h3>JS MergeXML class to merge multiple XML sources</h3>
<label for="files">Multi-select:</label>
<input type="file" id="files" name="files[]" multiple>
<button type="button" id="merge">Merge XMLs</button>
<p>Result: <span id="result"></span></p>
<div id="output"></div>
</body>
</html>

111
node_modules/mergexml/example.js generated vendored Normal file
View file

@ -0,0 +1,111 @@
/**
* JS MergeXML usage sample
* merge multi-selected local xml files
*
* @package MergeXML
* @author Vallo Reima
* @copyright (C)2014
*/
function Example() {
var oMX = new MergeXML(); /* instantiate the class */
var fls = []; /* output files info */
/**
* get element object
* @param {string} id
*/
var $ = function(id) {
return document.getElementById(id);
};
/**
* add event handler
* @param {string} evt
* @param {string} id
* @param {function} fnc
*/
var AddEvent = function(evt, id, fnc) {
var elem = $(id);
if (elem.addEventListener) // W3C DOM
elem.addEventListener(evt, fnc, false);
else if (elem.attachEvent) { // IE DOM
elem.attachEvent('on' + evt, fnc);
}
else { // No much to do
elem[evt] = fnc;
}
};
/**
* FileList objects handler
* @param {object} evt
*/
var FileSelect = function(evt) {
$('output').innerHTML = '';
$('result').innerHTML = '';
oMX.Init(); /* begin with new objects */
fls = [];
var cnt = 0;
var files = evt.target.files; /* FileList object */
for (var i = 0; i < files.length; i++) { /* loop the selected files */
var reader = new FileReader();
reader.onload = function(file) {
fls[cnt + 1] = oMX.AddFile(file) ? true : false; /* get a file */
var c = $('result').innerHTML;
if (c !== '') {
c += ', ';
}
$('result').innerHTML = c + fls[cnt];
cnt += 2;
};
fls.push(files[i].name, null);
reader.readAsText(files[i]);
}
};
/**
* Check results
* @return {mixed} array -- files list
* string -- error
* null -- loading yet
*/
var FileCheck = function() {
var r = [];
for (var i = 0; i < fls.length; i += 2) {
if (fls[i + 1]) {
r.push(fls[i]);
} else {
r = fls[i + 1] === false ? fls[i] : null;
break;
}
}
return r;
};
/**
* Show results
*/
var FileMerge = function() {
var err = '';
var r = FileCheck();
if (typeof r === 'string') {
err = oMX.error.text + ': ' + r;
} else if (r === null) {
err = 'Files are not loaded yet';
} else if (oMX.count < 2) {
err = 'Minimum 2 files are required';
}
$('output').innerHTML = err ? err : oMX.Get(2);
};
if (oMX.error.code !== '') {
$('output').innerHTML = oMX.error.text; /* no DOM support */
} else if (!window.File || !window.FileList || !window.FileReader) {
$('output').innerHTML = 'Sorry, the demo needs a browser supporting FileReader API';
} else {
AddEvent('change', 'files', FileSelect);
AddEvent('click', 'merge', FileMerge);
}
}

55
node_modules/mergexml/examplen.htm generated vendored Normal file
View file

@ -0,0 +1,55 @@
<!--
/**
* JS MergeXML NodeJS usage sample
* multi-select local xml files
*
* @package MergeXML
* @author Vallo Reima
* @copyright (C) 2019
*/
-->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>NodeJS MergeXML usage sample</title>
<style>
button, p {
font-weight: bold;
}
span {
font-weight: normal;
}
iframe {
width: 600px;
height: 650px;
border: 1px solid grey;
overflow: auto;
}
</style>
</head>
<body>
<h3>NodeJS MergeXML class to merge multiple XML sources</h3>
<form action="%url%" method="post" enctype="multipart/form-data" target="output">
<label for="files">Multi-select:</label>
<input type="file" id="files" name="files[]" multiple>
<button type="submit" name="submit">Merge XMLs</button>
</form>
<p>Result: <span id="result"></span></p>
<iframe id="output" name="output"></iframe>
<script>
/* input files selection event */
document.getElementById('files').addEventListener('change', function (evt) {
var rlt = '';
var fls = evt.target.files; /* FileList object */
for (var i = 0; i < fls.length; i++) { /* loop the selected files */
rlt += ', ' + fls[i].name; //get name
}
document.getElementById('result').innerHTML = rlt.substr(2); //display filenames
var out = document.getElementById('output').contentDocument || document.getElementById('output').contentWindow.document;
out.removeChild(out.documentElement); //remove previous output
});
</script>
</body>
</html>

80
node_modules/mergexml/examplen.js generated vendored Normal file
View file

@ -0,0 +1,80 @@
/**
* JS MergeXML NodeJS usage sample
* server-side component
*
* @package MergeXML
* @author Vallo Reima
* @copyright (C)2019
*/
const http = require('http');
const fs = require('fs'); //read/remove uploaded files
const formidable = require('formidable'); //to process the uploads
const MergeXML = require('./mergexml.js'); //loading the class
/* const oMX = new (require('./mergexml.js'))(); //load and instantiate */
const hostname = '127.0.0.1';
const port = 3000;
const template = 'examplen.htm';
const server = http.createServer((req, res) => {
if (req.method === 'POST') { //merge uploaded
let form = new formidable.IncomingForm();
form.multiples = true; //multi-selected files
form.parse(req, (err, fields, files) => { //process form data
let f = Object.keys(files)[0]; //1st property is files[]
let dat = Merge(files[f]);
Respond(res, dat); //display result
});
} else if (req.url === '/') {
fs.readFile(template, (err, data) => { //get template html
if (!err && data) { //obtained
let dat = data.toString().replace('%url%', `http://${hostname}:${port}`); //set action url
Respond(res, dat, 'html'); //launch the page
} else {
Respond(res, `Cannot read '${template}'`);
}
});
}
}).listen(port, hostname, () => {
console.log(`NodeJS is running at http://${hostname}:${port}`);
});
/**
* send response
* @param {object} res
* @param {string} type plain|html
* @param {string} data
*/
const Respond = function (res, data, type = 'plain') {
res.writeHead(200, {'Content-Type': `text/${type}`, 'Content-Length': data.length});
res.write(data);
res.end();
};
/**
* merge uploaded files and remove
* @param {array} files
* @returns {string}
*/
const Merge = function (files) {
let oMX = new MergeXML();
/* oMX.Init(); //using global instance */
for (let i = 0; i < files.length; i++) {
let dat = fs.readFileSync(files[i].path).toString();
fs.unlinkSync(files[i].path);
if (!oMX.AddSource(dat)) {
break;
}
}
var rlt;
if (oMX.error.code !== '') {
rlt = oMX.error.text; /* no DOM support */
} else if (oMX.count < 2) {
rlt = 'Minimum 2 files are required';
} else {
rlt = oMX.Get(1);
}
return rlt;
};

619
node_modules/mergexml/mergexml.js generated vendored Normal file
View file

@ -0,0 +1,619 @@
/**
* JS XML merging class
* merge multiple XML sources
* supports browser and NodeJS environments
*
* @package MergeXML
* @author Vallo Reima
* @copyright (C)2014-2019
*/
/**
* AMD/CommonJS wrapper
* @author Martijn van de Rijdt
*
* @param {object} root
* @param {function} factory
*/
(function (root, factory) {
"use strict";
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module
define([], factory);
} else if (typeof exports === 'object') {
// Does not work with strict CommonJS,
// but only CommonJS-like environments
// that support module.exports, like Node
module.exports = factory();
} else {
// Direct call, root is the owner (window)
root.MergeXML = factory();
}
}(this, function () {
/**
* Return a function as the exported value
* @param {object} opts -- processiong options (see readme)
*/
return function (opts) {
var mde; /* access mode: 1 - IE, 2 - browser, 3 - nodejs */
var msv; /* MS DOM version */
var psr; /* DOMParser object */
var xpe; /* xPath evaluator object */
var xpr; /* XPathResult object */
var nsr; /* namespace resolver method */
var nsd = {/* default namespace prefix and URIs */
pfx: '_',
psr: 'http://www.w3.org/1999/xhtml',
xpe: 'http://www.w3.org/2000/xmlns/'
};
var erp; /* parsing error flag */
var stay; /* overwrite protection */
var join; /* joining root name and status*/
var updn; /* update nodes sequentially by name */
var XML_ELEMENT_NODE = 1;
var XML_TEXT_NODE = 3;
var XML_COMMENT_NODE = 8;
var XML_PI_NODE = 7;
var that = this;
var Init = function () {
that.error = {};
/* detect NodeJS environment */
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
var p = typeof opts === 'object' && typeof opts.path === 'string' ? opts.path : '';
try { //obtain xml support
global.XPathEvaluator = require(p + 'xpath');
global.DOMParser = require((p || '@xmldom/') + 'xmldom').DOMParser;
global.XMLSerializer = require((p || '@xmldom/') + 'xmldom').XMLSerializer;
} catch (e) {
console.log(e.message);
}
}
mde = Setup(); //set mode
that.Init(opts);
};
/**
* determine mode, set functionality
* @returns {mixed} -- int - mode
* false - failed
*/
var Setup = function () {
var m;
var f = false;
var vers = [//IE
'MSXML2.DOMDocument.6.0',
'MSXML2.DOMDocument.3.0',
'MSXML2.DOMDocument',
'Microsoft.XmlDom'
];
var n = vers.length;
for (var i = 0; i < n; i++) {
try {
var d = new ActiveXObject(vers[i]);
d.async = false;
f = true; /* DOM supported */
if (d.loadXML('<x></x>') && d.selectSingleNode('/')) {
break; /* xPath supported */
}
} catch (e) {
/* skip */
}
}
if (f) {
if (i < n) {
msv = vers[i];
m = 1; /* IE mode */
} else {
m = 'nox'; /* no xPath */
}
} else {
var env;
if (typeof window !== 'undefined') {
env = window;
m = 2; // any browser
} else if (typeof global !== 'undefined') {
env = global;
m = 3; // NodeJS
} else {
env = {}; //unknown
}
if (!env.DOMParser) {
m = 'nod'; /* no DOM */
} else if (!env.XMLSerializer) {
m = 'nos'; /* no Serializer */
} else if (!env.XPathEvaluator) {
m = 'nox'; /* no xPath */
} else if (m === 2) { //browser
psr = new env.DOMParser();
xpe = new env.XPathEvaluator();
xpr = env.XPathResult;
f = psr.parseFromString('<invalid', 'text/xml'); /* force parsing error */
nsd.psr = f.getElementsByTagName('parsererror')[0].namespaceURI; //browser default namespace
} else {
psr = new env.DOMParser({xmlns: nsd.psr, errorHandler: function () {
erp = true; //indicate parse error
}});
xpe = env.XPathEvaluator;
xpr = env.XPathEvaluator.XPathResult;
nsd.xpe = xpe.XPath.XMLNS_NAMESPACE_URI;
}
}
return typeof m === 'string' ? Error(m) : m;
};
/**
* (re)set the objects
* @param {object} opt -- processiong options
* @returns {mixed} -- false - error
*/
that.Init = function (opt) {
if (typeof opt !== 'object') {
opt = {};
}
/* set stay attribute value to check */
if (typeof opt.stay === 'undefined') {
if (typeof stay === 'undefined') {
stay = ['all'];
}
} else if (!opt.stay) {
stay = [];
} else if (typeof opt.stay === 'object' && opt.stay instanceof Array) {
stay = opt.stay;
} else {
stay = [opt.stay];
}
/* set join condition for different roots */
if (typeof opt.join === 'undefined') {
if (typeof join === 'undefined') {
join = ['root'];
}
} else if (!opt.join) {
join = [false];
} else {
join = [String(opt.join)];
}
join[1] = false;
/* set update sequence manner */
if (typeof opt.updn !== 'undefined') {
updn = opt.updn;
} else if (typeof updn === 'undefined') {
updn = true;
}
that.dom = null; /* result DOM object */
that.nsp = {}; /* namespaces */
that.count = 0; /* adding counter */
if (mde) {
that.error = {code: '', text: ''};
}
return mde;
};
/**
* add XML file
* @param {object} file -- FileList element
* @return {object|false}
*/
that.AddFile = function (file) {
var rlt;
if (!mde) {
rlt = mde;
} else if (!file || !file.target) {
rlt = Error('nof');
} else if (!file.target.result) {
rlt = Error('emf');
} else {
rlt = that.AddSource(file.target.result);
}
return rlt;
};
/**
* add XML string
* @param {string|oobject} xml
* @return mixed -- false - bad content
* object - result
*/
that.AddSource = function (xml) {
var rlt, doc;
if (mde) {
if (typeof xml === 'object') {
doc = that.Get(1, xml) ? xml : false;
if (doc && ((mde > 1 && !DOMParser) || (mde === 1 && !doc.selectSingleNode('/')))) {
doc = null; /* not compatible */
}
} else {
try {
doc = Load(xml);
} catch (e) {
doc = false;
}
}
}
if (!mde) {
rlt = mde;
} else if (doc === null) {
rlt = Error('nob');
} else if (doc === false) {
rlt = Error('inv');
} else if (doc === true) {
that.nsp = NameSpaces(that.dom.documentElement);
that.count = 1;
rlt = that.dom;
} else if (CheckSource(doc)) {
Merge(doc, '/'); /* add to existing */
if (join[1] === true) {
var tmp = that.dom.createTextNode("\r\n");
that.dom.documentElement.appendChild(tmp);
}
that.count++;
rlt = that.dom;
} else {
rlt = false;
}
return rlt;
};
/**
* load the source into dom object
* @param {object|string} src -- the source
* @return {mixed} -- false - error
* true - 1st load
* object - loaded doc
*/
var Load = function (src) {
var rlt, doc;
if (mde > 1) {
erp = false;
if (that.dom) {
doc = psr.parseFromString(src, 'text/xml');
rlt = ParseError(doc) ? doc : false;
} else {
that.dom = psr.parseFromString(src, 'text/xml');
rlt = ParseError(that.dom) ? true : false;
}
} else if (that.dom) {
doc = new ActiveXObject(msv);
doc.async = false;
rlt = doc.loadXML(src) ? doc : false;
} else {
that.dom = new ActiveXObject(msv);
that.dom.async = false;
that.dom.setProperty('SelectionLanguage', 'XPath');
rlt = that.dom.loadXML(src) ? true : false;
}
return rlt;
};
/**
* check for xml syntax (mode 2)
* @param {object} doc
* @return {bool} -- true - ok
*/
var ParseError = function (doc) {
return !erp && !doc.getElementsByTagNameNS(nsd.psr, 'parsererror').length;
};
/**
*
* @param {object} doc
* @return {bool} -- true - ok
*/
var CheckSource = function (doc) {
var rlt = true;
var charSet1 = that.dom.characterSet || that.dom.inputEncoding || that.dom.xmlEncoding;
var charSet2 = doc.characterSet || doc.inputEncoding || doc.xmlEncoding;
if (charSet2 !== charSet1) {
rlt = Error('enc');
} else if (doc.documentElement.namespaceURI !== that.dom.documentElement.namespaceURI) { /* $dom->documentElement->lookupnamespaceURI(NULL) */
rlt = Error('nse');
} else if (doc.documentElement.nodeName !== that.dom.documentElement.nodeName) {
if (!join[0]) {
rlt = Error('dif');
} else if (!join[1]) {
var enc = typeof charSet1 !== 'undefined' ? charSet1 : 'UTF-8';
var ver = that.dom.xmlVersion ? that.dom.xmlVersion : '1.0';
var xml = '<?xml version="' + ver + '" encoding="' + enc + "\"?>\r\n<" + join[0] + ">\r\n</" + join[0] + '>';
var d = Load(xml);
if (d) {
var tmp = that.dom.documentElement.cloneNode(true);
d.documentElement.appendChild(tmp);
tmp = d.createTextNode("\r\n");
d.documentElement.appendChild(tmp);
that.dom = d;
join[1] = true;
} else {
rlt = Error('jne');
join[1] = null;
}
}
}
if (rlt) {
var a = NameSpaces(doc.documentElement);
for (var c in a) {
if (!that.nsp[c]) {
if (typeof that.dom.documentElement.setAttributeNS !== 'undefined') {
that.dom.documentElement.setAttributeNS(nsd.xpe, 'xmlns:' + c, a[c]);
} else {
// no choice but to use the incorrect setAttribute instead
that.dom.documentElement.setAttribute('xmlns:' + c, a[c]);
}
that.nsp[c] = a[c];
}
}
if (!updn) {
nsr = null;
} else if (mde === 1) {
ResolverIE();
} else if (mde === 3) {
nsr = that;
} else {
nsr = that.lookupNamespaceURI;
}
}
return rlt;
};
/**
* join 2 dom objects recursively
* @param {object} src -- current source node
* @param {string} pth -- current source path
*/
var Merge = function (src, pth) {
for (var i = 0; i < src.childNodes.length; i++) {
var tmp;
var node = src.childNodes[i]; //$node->getNodePath()
var path = GetNodePath(src.childNodes, node, pth, i);
var obj = that.Query(path);
if (node.nodeType === XML_ELEMENT_NODE) {
var flg = true; /* replace existing node by default */
if (obj === null || obj.namespaceURI !== node.namespaceURI) {
tmp = node.cloneNode(true); /* take existing node */
obj = that.Query(pth); /* destination parent */
obj.appendChild(tmp); /* add a node */
} else {
if (ArraySearch(obj.getAttribute('stay'), stay) !== false) {
flg = false; /* don't replace */
}
if (flg) {
try {
for (var j = 0; j < node.attributes.length; j++) { /* add/replace attributes */
if (node.attributes[j].namespaceURI && typeof node.setAttributeNS !== 'undefined') {
obj.setAttributeNS(node.attributes[j].namespaceURI, node.attributes[j].nodeName, node.attributes[j].nodeValue);
} else {
obj.setAttribute(node.attributes[j].nodeName, node.attributes[j].nodeValue);
}
}
} catch (e) {
/* read-only node */
}
}
}
if (node.hasChildNodes() && flg) {
Merge(node, path); /* go to subnodes */
}
} else if (node.nodeType === XML_TEXT_NODE || node.nodeType === XML_COMMENT_NODE) { /* leaf node */
if (obj === null || obj.nodeType !== node.nodeType) {
obj = that.Query(pth); /* destination parent node */
if (node.nodeType === XML_TEXT_NODE) {
tmp = that.dom.createTextNode(node.nodeValue); /* add text */
} else {
tmp = that.dom.createComment(node.nodeValue); /* add comment */
}
obj.appendChild(tmp); /* add leaf */
} else {
obj.nodeValue = node.nodeValue; /* replace leaf */
obj.data = node.data; //to ensure serializing
}
}
}
};
/**
* form the node xPath
* @param {object} nodes -- child nodes
* @param {object} node -- current child
* @param {string} pth -- parent path
* @param {int} eln -- element sequence number
* @return {string} query path
*/
var GetNodePath = function (nodes, node, pth, eln) {
var p, i;
var j = 0;
if (node.nodeType === XML_ELEMENT_NODE) {
for (i = 0; i <= eln; i++) {
if ((updn && nodes[i].nodeType === node.nodeType && nodes[i].nodeName === node.nodeName) ||
(!updn && nodes[i].nodeType !== XML_PI_NODE)) {
j++;
}
}
if (updn) {
var f = false;
var a = NameSpaces(node);
for (var c in a) {
if (c !== nsd.pfx) {
that.nsp[c] = a[c];
f = (mde === 1);
}
}
if (f) {
ResolverIE();
}
if (node.prefix) {
p = node.prefix + ':';
} else if (that.nsp[nsd.pfx]) {
p = nsd.pfx + ':';
} else {
p = '';
}
p += (node.localName ? node.localName : node.baseName);
} else {
p = 'node()';
}
} else if (node.nodeType === XML_TEXT_NODE || node.nodeType === XML_COMMENT_NODE) {
for (i = 0; i <= eln; i++) {
if (nodes[i].nodeType === node.nodeType) {
j++;
}
}
p = node.nodeType === XML_TEXT_NODE ? 'text()' : 'comment()';
} else {
p = pth;
}
if (j) {
p = pth + (pth.slice(-1) === '/' ? '' : '/') + p + '[' + j + ']';
}
return p;
};
/**
* get node's namespaces
* @param {object} node
* @return {array}
*/
var NameSpaces = function (node) {
var rlt = {};
var attrs = node.attributes;
for (var i = 0; i < attrs.length; ++i) {
var a = attrs[i].name.split(':');
if (a[0] === 'xmlns') {
var c = a[1] ? a[1] : nsd.pfx;
rlt[c] = attrs[i].value;
}
}
return rlt;
};
/**
* xPath query
* @param {string} qry -- query statement
* @return {object}
*/
that.Query = function (qry) {
if (!mde) {
return null;
}
var rlt;
if (join[1]) {
qry = '/' + that.dom.documentElement.nodeName + (qry === '/' ? '' : qry);
}
try {
if (mde > 1) {
rlt = xpe.evaluate(qry, that.dom, nsr, xpr.FIRST_ORDERED_NODE_TYPE, null);
rlt = rlt.singleNodeValue;
} else {
rlt = that.dom.selectSingleNode(qry);
}
} catch (e) {
rlt = null; /* no such path */
}
return rlt;
};
/**
* XPathNSResolver
* @param {string} pfx node prefix
* @return {string} namespace URI
*/
that.lookupNamespaceURI = function (pfx) {
return that.nsp[pfx] || null;
};
/**
* XPath IE Resolver
*/
var ResolverIE = function () {
var p = '';
for (var c in that.nsp) {
p += ' xmlns:' + c + '=' + "'" + that.nsp[c] + "'";
}
if (p) {
that.dom.setProperty('SelectionNamespaces', p.substr(1));
}
};
/**
* find array memeber by value
* @param {mixed} val
* @param {array} arr
* @returns {mixed}
*/
var ArraySearch = function (val, arr) {
var rlt = false;
for (var key in arr) {
if (arr[key] === val) {
rlt = key;
break;
}
}
return rlt;
};
/**
* get result
* @param {int} flg -- 0 - object
* 1 - xml
* 2 - html
* @param {object} doc
* @return {mixed}
*/
that.Get = function (flg, doc) {
var rlt;
if (flg && !doc) {
doc = that.dom;
}
if (!mde) {
rlt = that.error.text;
} else if (!flg) {
rlt = that.dom;
} else if (!doc) {
rlt = '';
} else if (doc.xml) {
rlt = doc.xml;
} else {
try {
rlt = (new XMLSerializer()).serializeToString(doc);
} catch (e) {
rlt = e.message;
flg = null;
}
}
if (rlt && flg === 2) { /* make html view */
if (join[1]) {
var k = rlt.indexOf('<' + join[0]);
rlt = rlt.substr(0, k) + "\r\n" + rlt.substr(k);
}
rlt = rlt.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/ |\t/g, '&nbsp;'); /* tags and spaces */
rlt = rlt.replace(/(\r\n|\n|\r)/g, '<br>'); /* line breaks */
}
return rlt;
};
/**
* set error message
* @param {string} err -- token
* @return {bool} false
*/
var Error = function (err) {
var errs = {
nod: 'XML DOM is not supported',
nos: 'Serializer is not supported',
nox: 'xPath is not supported',
nob: 'Incompatible source object',
nof: 'File not found',
emf: 'File is empty', /* possible delivery fault */
inv: 'Invalid XML source',
enc: 'Different encoding',
dif: 'Different root nodes',
jne: 'Invalid join parameter',
nse: 'Namespace incompatibility',
und: 'Undefined error'
};
that.error.code = errs[err] ? err : 'und';
that.error.text = errs[that.error.code];
return false;
};
Init();
};
}));

View file

@ -0,0 +1,401 @@
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.7.13](https://github.com/xmldom/xmldom/compare/0.7.12...0.7.13)
### Fixed
- dom: prevent iteration over deleted items [`#514`](https://github.com/xmldom/xmldom/pull/514)/ [`#499`](https://github.com/xmldom/xmldom/issues/499)
Thank you, [@qtow](https://github.com/qtow), for your contributions
## [0.7.12](https://github.com/xmldom/xmldom/compare/0.7.11...0.7.12)
### Fixed
- fix: Set nodeName property in ProcessingInstruction [`#509`](https://github.com/xmldom/xmldom/pull/509) / [`#505`](https://github.com/xmldom/xmldom/issues/505)
Thank you, [@cjbarth](https://github.com/cjbarth), for your contributions
## [0.7.11](https://github.com/xmldom/xmldom/compare/0.7.10...0.7.11)
### Fixed
- extend list of HTML entities [`#489`](https://github.com/xmldom/xmldom/pull/489)
Thank you, [@zorkow](https://github.com/zorkow), for your contributions
## [0.7.10](https://github.com/xmldom/xmldom/compare/0.7.9...0.7.10)
### Fixed
- properly parse closing where the last attribute has no value [`#485`](https://github.com/xmldom/xmldom/pull/485) / [`#486`](https://github.com/xmldom/xmldom/issues/486)
Thank you, [@bulandent](https://github.com/bulandent), for your contributions
## [0.7.9](https://github.com/xmldom/xmldom/compare/0.7.8...0.7.9)
### Fixed
- Properly check nodes before replacement [`#457`](https://github.com/xmldom/xmldom/pull/457) / [`#455`](https://github.com/xmldom/xmldom/issues/455) / [`#456`](https://github.com/xmldom/xmldom/issues/456)
Thank you, [@edemaine](https://github.com/edemaine), [@pedro-l9](https://github.com/pedro-l9), for your contributions
## [0.7.8](https://github.com/xmldom/xmldom/compare/0.7.7...0.7.8)
### Fixed
- fix: Restore ES5 compatibility [`#452`](https://github.com/xmldom/xmldom/pull/452) / [`#453`](https://github.com/xmldom/xmldom/issues/453)
Thank you, [@fengxinming](https://github.com/fengxinming), for your contributions
## [0.7.7](https://github.com/xmldom/xmldom/compare/0.7.6...0.7.7)
### Fixed
- 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)
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.
In the upcoming version 0.9.0 those text nodes will no longer be added and an error will be thrown instead.
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.
Related Spec: <https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity>
Thank you, [@frumioj](https://github.com/frumioj), [@cjbarth](https://github.com/cjbarth), [@markgollnick](https://github.com/markgollnick) for your contributions
## [0.7.6](https://github.com/xmldom/xmldom/compare/0.7.5...0.7.6)
### Fixed
- Avoid iterating over prototype properties [`#441`](https://github.com/xmldom/xmldom/pull/441) / [`#437`](https://github.com/xmldom/xmldom/pull/437) / [`#436`](https://github.com/xmldom/xmldom/issues/436)
Thank you, [@jftanner](https://github.com/jftanner), [@Supraja9726](https://github.com/Supraja9726) for your contributions
## 0.7.5
[Commits](https://github.com/xmldom/xmldom/compare/0.7.4...0.7.5)
### Fixes:
- Preserve default namespace when serializing [`#319`](https://github.com/xmldom/xmldom/issues/319) / [`#321`](https://github.com/xmldom/xmldom/pull/321)
Thank you, [@lupestro](https://github.com/lupestro)
## 0.7.4
[Commits](https://github.com/xmldom/xmldom/compare/0.7.3...0.7.4)
### Fixes:
- Restore ability to parse `__prototype__` attributes [`#315`](https://github.com/xmldom/xmldom/pull/315)
Thank you, [@dsimpsonOMF](https://github.com/dsimpsonOMF)
## 0.7.3
[Commits](https://github.com/xmldom/xmldom/compare/0.7.2...0.7.3)
### Fixes:
- Add doctype when parsing from string [`#277`](https://github.com/xmldom/xmldom/issues/277) / [`#301`](https://github.com/xmldom/xmldom/pull/301)
- Correct typo in error message [`#294`](https://github.com/xmldom/xmldom/pull/294)
Thank you, [@rrthomas](https://github.com/rrthomas)
### Refactor:
- Improve exports & require statements, new main package entry [`#233`](https://github.com/xmldom/xmldom/pull/233)
### Docs:
- Fix Stryker badge [`#298`](https://github.com/xmldom/xmldom/pull/298)
- Fix link to help-wanted issues [`#299`](https://github.com/xmldom/xmldom/pull/299)
### Chore:
- Execute stryker:dry-run on branches [`#302`](https://github.com/xmldom/xmldom/pull/302)
- Fix stryker config [`#300`](https://github.com/xmldom/xmldom/pull/300)
- Split test and lint scripts [`#297`](https://github.com/xmldom/xmldom/pull/297)
- Switch to stryker dashboard owned by org [`#292`](https://github.com/xmldom/xmldom/pull/292)
## 0.7.2
[Commits](https://github.com/xmldom/xmldom/compare/0.7.1...0.7.2)
### Fixes:
- Types: Add index.d.ts to packaged files [`#288`](https://github.com/xmldom/xmldom/pull/288)
Thank you, [@forty](https://github.com/forty)
## 0.7.1
[Commits](https://github.com/xmldom/xmldom/compare/0.7.0...0.7.1)
### Fixes:
- Types: Copy types from DefinitelyTyped [`#283`](https://github.com/xmldom/xmldom/pull/283)
Thank you, [@kachkaev](https://github.com/kachkaev)
### Chore:
- package.json: remove author, maintainers, etc. [`#279`](https://github.com/xmldom/xmldom/pull/279)
## 0.7.0
[Commits](https://github.com/xmldom/xmldom/compare/0.6.0...0.7.0)
Due to [`#271`](https://github.com/xmldom/xmldom/issue/271) this version was published as
- unscoped `xmldom` package to github (git tags [`0.7.0`](https://github.com/xmldom/xmldom/tree/0.7.0) and [`0.7.0+unscoped`](https://github.com/xmldom/xmldom/tree/0.7.0%2Bunscoped))
- scoped `@xmldom/xmldom` package to npm (git tag `0.7.0+scoped`)
For more details look at [`#278`](https://github.com/xmldom/xmldom/pull/278#issuecomment-902172483)
### Fixes:
- Security: Misinterpretation of malicious XML input [`CVE-2021-32796`](https://github.com/xmldom/xmldom/security/advisories/GHSA-5fg8-2547-mr8q)
- Implement `Document.getElementsByClassName` as specified [`#213`](https://github.com/xmldom/xmldom/pull/213), thank you, [@ChALkeR](https://github.com/ChALkeR)
- Inherit namespace prefix from parent when required [`#268`](https://github.com/xmldom/xmldom/pull/268)
- Handle whitespace in closing tags [`#267`](https://github.com/xmldom/xmldom/pull/267)
- Update `DOMImplementation` according to recent specs [`#210`](https://github.com/xmldom/xmldom/pull/210)
BREAKING CHANGE: Only if you "passed features to be marked as available as a constructor arguments" and expected it to "magically work".
- No longer serializes any namespaces with an empty URI [`#244`](https://github.com/xmldom/xmldom/pull/244)
(related to [`#168`](https://github.com/xmldom/xmldom/pull/168) released in 0.6.0)
BREAKING CHANGE: Only if you rely on ["unsetting" a namespace prefix](https://github.com/xmldom/xmldom/pull/168#issuecomment-886984994) by setting it to an empty string
- Set `localName` as part of `Document.createElement` [`#229`](https://github.com/xmldom/xmldom/pull/229), thank you, [@rrthomas](https://github.com/rrthomas)
### CI
- We are now additionally running tests against node v16
- Stryker tests on the master branch now run against node v14
### Docs
- Describe relations with and between specs: [`#211`](https://github.com/xmldom/xmldom/pull/211), [`#247`](https://github.com/xmldom/xmldom/pull/247)
## 0.6.0
[Commits](https://github.com/xmldom/xmldom/compare/0.5.0...0.6.0)
### Fixes
- Stop serializing empty namespace values like `xmlns:ds=""` [`#168`](https://github.com/xmldom/xmldom/pull/168)
BREAKING CHANGE: If your code expected empty namespaces attributes to be serialized.
Thank you, [@pdecat](https://github.com/pdecat) and [@FranckDepoortere](https://github.com/FranckDepoortere)
- Escape `<` to `&lt;` when serializing attribute values [`#198`](https://github.com/xmldom/xmldom/issues/198) / [`#199`](https://github.com/xmldom/xmldom/pull/199)
## 0.5.0
[Commits](https://github.com/xmldom/xmldom/compare/0.4.0...0.5.0)
### Fixes
- Avoid misinterpretation of malicious XML input - [`GHSA-h6q6-9hqw-rwfv`](https://github.com/xmldom/xmldom/security/advisories/GHSA-h6q6-9hqw-rwfv) (CVE-2021-21366)
- Improve error reporting; throw on duplicate attribute\
BREAKING CHANGE: It is currently not clear how to consistently deal with duplicate attributes, so it's also safer for our users to fail when detecting them.
It's possible to configure the `DOMParser.errorHandler` before parsing, to handle those errors differently.
To accomplish this and also be able to verify it in tests I needed to
- create a new `Error` type `ParseError` and export it
- Throw `ParseError` from `errorHandler.fatalError` and prevent those from being caught in `XMLReader`.
- export `DOMHandler` constructor as `__DOMHandler`
- Preserve quotes in DOCTYPE declaration
Since the only purpose of parsing the DOCTYPE is to be able to restore it when serializing, we decided that it would be best to leave the parsed `publicId` and `systemId` as is, including any quotes.
BREAKING CHANGE: If somebody relies on the actual unquoted values of those ids, they will need to take care of either single or double quotes and the right escaping.
(Without this change this would not have been possible because the SAX parser already dropped the information about the quotes that have been used in the source.)
https://www.w3.org/TR/2006/REC-xml11-20060816/#dtd
https://www.w3.org/TR/2006/REC-xml11-20060816/#IDAX1KS (External Entity Declaration)
- Fix breaking preprocessors' directives when parsing attributes [`#171`](https://github.com/xmldom/xmldom/pull/171)
- fix(dom): Escape `]]&gt;` when serializing CharData [`#181`](https://github.com/xmldom/xmldom/pull/181)
- Switch to (only) MIT license (drop problematic LGPL license option) [`#178`](https://github.com/xmldom/xmldom/pull/178)
- Export DOMException; remove custom assertions; etc. [`#174`](https://github.com/xmldom/xmldom/pull/174)
### Docs
- Update MDN links in `readme.md` [`#188`](https://github.com/xmldom/xmldom/pull/188)
## 0.4.0
[Commits](https://github.com/xmldom/xmldom/compare/0.3.0...0.4.0)
### Fixes
- **BREAKING** Restore `&nbsp;` behavior from v0.1.27 [`#67`](https://github.com/xmldom/xmldom/pull/67)
- **BREAKING** Typecheck source param before parsing [`#113`](https://github.com/xmldom/xmldom/pull/113)
- Include documents in package files list [`#156`](https://github.com/xmldom/xmldom/pull/156)
- Preserve doctype with sysid [`#144`](https://github.com/xmldom/xmldom/pull/144)
- Remove ES6 syntax from getElementsByClassName [`#91`](https://github.com/xmldom/xmldom/pull/91)
- Revert "Add lowercase of åäö in entityMap" due to duplicate entries [`#84`](https://github.com/xmldom/xmldom/pull/84)
- fix: Convert all line separators to LF [`#66`](https://github.com/xmldom/xmldom/pull/66)
### Docs
- Update CHANGELOG.md through version 0.3.0 [`#63`](https://github.com/xmldom/xmldom/pull/63)
- Update badges [`#78`](https://github.com/xmldom/xmldom/pull/78)
- Add .editorconfig file [`#104`](https://github.com/xmldom/xmldom/pull/104)
- Add note about import [`#79`](https://github.com/xmldom/xmldom/pull/79)
- Modernize & improve the example in readme.md [`#81`](https://github.com/xmldom/xmldom/pull/81)
### CI
- Add Stryker Mutator [`#70`](https://github.com/xmldom/xmldom/pull/70)
- Add Stryker action to update dashboard [`#77`](https://github.com/xmldom/xmldom/pull/77)
- Add Node GitHub action workflow [`#64`](https://github.com/xmldom/xmldom/pull/64)
- add & enable eslint [`#106`](https://github.com/xmldom/xmldom/pull/106)
- Use eslint-plugin-es5 to enforce ES5 syntax [`#107`](https://github.com/xmldom/xmldom/pull/107)
- Recover `vows` tests, drop `proof` tests [`#59`](https://github.com/xmldom/xmldom/pull/59)
- Add jest tessuite and first tests [`#114`](https://github.com/xmldom/xmldom/pull/114)
- Add jest testsuite with `xmltest` cases [`#112`](https://github.com/xmldom/xmldom/pull/112)
- Configure Renovate [`#108`](https://github.com/xmldom/xmldom/pull/108)
- Test European HTML entities [`#86`](https://github.com/xmldom/xmldom/pull/86)
- Updated devDependencies
### Other
- Remove files that are not of any use [`#131`](https://github.com/xmldom/xmldom/pull/131), [`#65`](https://github.com/xmldom/xmldom/pull/65), [`#33`](https://github.com/xmldom/xmldom/pull/33)
## 0.3.0
[Commits](https://github.com/xmldom/xmldom/compare/0.2.1...0.3.0)
- **BREAKING** Node >=10.x is now required.
- **BREAKING** Remove `component.json` (deprecated package manager https://github.com/componentjs/guide)
- **BREAKING** Move existing sources into `lib` subdirectory.
- **POSSIBLY BREAKING** Introduce `files` entry in `package.json` and remove use of `.npmignore`.
- [Add `Document.getElementsByClassName`](https://github.com/xmldom/xmldom/issues/24).
- [Add `Node` to the list of exports](https://github.com/xmldom/xmldom/pull/27)
- [Add lowercase of åäö in `entityMap`](https://github.com/xmldom/xmldom/pull/23).
- Move CHANGELOG to markdown file.
- Move LICENSE to markdown file.
## 0.2.1
[Commits](https://github.com/xmldom/xmldom/compare/0.2.0...0.2.1)
- Correct `homepage`, `repository` and `bugs` URLs in `package.json`.
## 0.2.0
[Commits](https://github.com/xmldom/xmldom/compare/v0.1.27...0.2.0)
- Includes all **BREAKING** changes introduced in [`xmldom-alpha@v0.1.28`](#0128) by the original authors.
- **POSSIBLY BREAKING** [remove the `Object.create` check from the `_extends` method of `dom.js` that added a `__proto__` property](https://github.com/xmldom/xmldom/commit/0be2ae910a8a22c9ec2cac042e04de4c04317d2a#diff-7d1c5d97786fdf9af5446a241d0b6d56L19-L22) ().
- **POSSIBLY BREAKING** [remove code that added a `__proto__` property](https://github.com/xmldom/xmldom/commit/366159a76a181ce9a0d83f5dc48205686cfaf9cc)
- formatting/corrections in `package.json`
## 0.1.31
[Commits](https://github.com/xmldom/xmldom/compare/v0.1.27...v0.1.31)
The patch versions (`v0.1.29` - `v0.1.31`) that have been released on the [v0.1.x branch](https://github.com/xmldom/xmldom/tree/0.1.x), to reflect the changed maintainers, **are branched off from [`v0.1.27`](#0127) so they don't include the breaking changes introduced in [`xmldom-alpha@v0.1.28`](#0128)**:
## Maintainer changes
After the last commit to the original repository <https://github.com/jindw/xmldom> on the 9th of May 2017, the first commit to <https://github.com/xmldom/xmldom> is from the 19th of December 2019. [The fork has been announced in the original repository on the 2nd of March 2020.](https://github.com/jindw/xmldom/issues/259)
The versions listed below have been published to one or both of the following packages:
- <https://www.npmjs.com/package/xmldom-alpha>
- <https://www.npmjs.com/package/xmldom>
It is currently not planned to continue publishing the `xmldom-alpha` package.
The new maintainers did not invest time to understand changes that led to the last `xmldom` version [`0.1.27`](#0127) published by the original maintainer, but consider it the basis for their work.
A timeline of all the changes that happened from that version until `0.3.0` is available in <https://github.com/xmldom/xmldom/issues/62>. Any related questions should be asked there.
## 0.1.28
[Commits](https://github.com/xmldom/xmldom/compare/v0.1.27...xmldom-alpha@v0.1.28)
Published by @jindw on the 9th of May 2017 as
- `xmldom-alpha@0.1.28`
- **BREAKING** includes [regression regarding `&nbsp;` (issue #57)](https://github.com/xmldom/xmldom/issues/57)
- [Fix `license` field in `package.json`](https://github.com/jindw/xmldom/pull/178)
- [Conditional converting of HTML entities](https://github.com/jindw/xmldom/pull/80)
- Fix `dom.js` serialization issue for missing document element ([example that failed on `toString()` before this change](https://github.com/xmldom/xmldom/blob/a58dcf7a265522e80ce520fe3be0cddb1b976f6f/test/parse/unclosedcomment.js#L10-L11))
- Add new module `entities.js`
## 0.1.27
Published by @jindw on the 28th of Nov 2016 as
- `xmldom@0.1.27`
- `xmldom-alpha@0.1.27`
- Various bug fixes.
## 0.1.26
Published on the 18th of Nov 2016
as `xmldom@0.1.26`
- Details unknown
## 0.1.25
Published on the 18th of Nov 2016 as
- `xmldom@0.1.25`
- Details unknown
## 0.1.24
Published on the 27th of November 2016 as
- `xmldom@0.1.24`
- `xmldom-alpha@0.1.24`
- Added node filter.
## 0.1.23
Published on the 5th of May 2016 as
- `xmldom-alpha@0.1.23`
- Add namespace support for nest node serialize.
- Various other bug fixes.
## 0.1.22
- Merge XMLNS serialization.
- Remove \r from source string.
- Print namespaces for child elements.
- Switch references to nodeType to use named constants.
- Add nodelist toString support.
## 0.1.21
- Fix serialize bug.
## 0.1.20
- Optimize invalid XML support.
- Add toString sorter for attributes output.
- Add html self closed node button.
- Add `*` NS support for getElementsByTagNameNS.
- Convert attribute's value to string in setAttributeNS.
- Add support for HTML entities for HTML docs only.
- Fix TypeError when Document is created with DocumentType.
## 0.1.19
- Fix [infinite loop on unclosed comment (jindw/xmldom#68)](https://github.com/jindw/xmldom/issues/68)
- Add error report for unclosed tag.
- Various other fixes.
## 0.1.18
- Add default `ns` support.
- parseFromString now renders entirely plain text documents as textNode.
- Enable option to ignore white space on parsing.
## 0.1.17
**Details missing for this and potential earlier version**
## 0.1.16
- Correctly handle multibyte Unicode greater than two byts. #57. #56.
- Initial unit testing and test coverage. #53. #46. #19.
- Create Bower `component.json` #52.
## 0.1.8
- Add: some test case from node-o3-xml(excludes xpath support)
- Fix: remove existed attribute before setting (bug introduced in v0.1.5)
- Fix: index direct access for childNodes and any NodeList collection(not w3c standard)
- Fix: remove last child bug

View file

@ -0,0 +1,8 @@
Copyright 2019 - present Christopher J. Brody and other contributors, as listed in: https://github.com/xmldom/xmldom/graphs/contributors
Copyright 2012 - 2017 @jindw <jindw@xidea.org> and other contributors, as listed in: https://github.com/jindw/xmldom/graphs/contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,43 @@
/// <reference lib="dom" />
declare module "@xmldom/xmldom" {
var DOMParser: DOMParserStatic;
var XMLSerializer: XMLSerializerStatic;
var DOMImplementation: DOMImplementationStatic;
interface DOMImplementationStatic {
new(): DOMImplementation;
}
interface DOMParserStatic {
new (): DOMParser;
new (options: Options): DOMParser;
}
interface XMLSerializerStatic {
new (): XMLSerializer;
}
interface DOMParser {
parseFromString(xmlsource: string, mimeType?: string): Document;
}
interface XMLSerializer {
serializeToString(node: Node): string;
}
interface Options {
locator?: any;
errorHandler?: ErrorHandlerFunction | ErrorHandlerObject | undefined;
}
interface ErrorHandlerFunction {
(level: string, msg: any): any;
}
interface ErrorHandlerObject {
warning?: ((msg: any) => any) | undefined;
error?: ((msg: any) => any) | undefined;
fatalError?: ((msg: any) => any) | undefined;
}
}

View file

@ -0,0 +1,2 @@
extends:
- 'plugin:es5/no-es2015'

View file

@ -0,0 +1,177 @@
'use strict'
/**
* Ponyfill for `Array.prototype.find` which is only available in ES6 runtimes.
*
* Works with anything that has a `length` property and index access properties, including NodeList.
*
* @template {unknown} T
* @param {Array<T> | ({length:number, [number]: T})} list
* @param {function (item: T, index: number, list:Array<T> | ({length:number, [number]: T})):boolean} predicate
* @param {Partial<Pick<ArrayConstructor['prototype'], 'find'>>?} ac `Array.prototype` by default,
* allows injecting a custom implementation in tests
* @returns {T | undefined}
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
* @see https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.find
*/
function find(list, predicate, ac) {
if (ac === undefined) {
ac = Array.prototype;
}
if (list && typeof ac.find === 'function') {
return ac.find.call(list, predicate);
}
for (var i = 0; i < list.length; i++) {
if (Object.prototype.hasOwnProperty.call(list, i)) {
var item = list[i];
if (predicate.call(undefined, item, i, list)) {
return item;
}
}
}
}
/**
* "Shallow freezes" an object to render it immutable.
* Uses `Object.freeze` if available,
* otherwise the immutability is only in the type.
*
* Is used to create "enum like" objects.
*
* @template T
* @param {T} object the object to freeze
* @param {Pick<ObjectConstructor, 'freeze'> = Object} oc `Object` by default,
* allows to inject custom object constructor for tests
* @returns {Readonly<T>}
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
*/
function freeze(object, oc) {
if (oc === undefined) {
oc = Object
}
return oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object
}
/**
* All mime types that are allowed as input to `DOMParser.parseFromString`
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString#Argument02 MDN
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#domparsersupportedtype WHATWG HTML Spec
* @see DOMParser.prototype.parseFromString
*/
var MIME_TYPE = freeze({
/**
* `text/html`, the only mime type that triggers treating an XML document as HTML.
*
* @see DOMParser.SupportedType.isHTML
* @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration
* @see https://en.wikipedia.org/wiki/HTML Wikipedia
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring WHATWG HTML Spec
*/
HTML: 'text/html',
/**
* Helper method to check a mime type if it indicates an HTML document
*
* @param {string} [value]
* @returns {boolean}
*
* @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration
* @see https://en.wikipedia.org/wiki/HTML Wikipedia
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring */
isHTML: function (value) {
return value === MIME_TYPE.HTML
},
/**
* `application/xml`, the standard mime type for XML documents.
*
* @see https://www.iana.org/assignments/media-types/application/xml IANA MimeType registration
* @see https://tools.ietf.org/html/rfc7303#section-9.1 RFC 7303
* @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
*/
XML_APPLICATION: 'application/xml',
/**
* `text/html`, an alias for `application/xml`.
*
* @see https://tools.ietf.org/html/rfc7303#section-9.2 RFC 7303
* @see https://www.iana.org/assignments/media-types/text/xml IANA MimeType registration
* @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
*/
XML_TEXT: 'text/xml',
/**
* `application/xhtml+xml`, indicates an XML document that has the default HTML namespace,
* but is parsed as an XML document.
*
* @see https://www.iana.org/assignments/media-types/application/xhtml+xml IANA MimeType registration
* @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument WHATWG DOM Spec
* @see https://en.wikipedia.org/wiki/XHTML Wikipedia
*/
XML_XHTML_APPLICATION: 'application/xhtml+xml',
/**
* `image/svg+xml`,
*
* @see https://www.iana.org/assignments/media-types/image/svg+xml IANA MimeType registration
* @see https://www.w3.org/TR/SVG11/ W3C SVG 1.1
* @see https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Wikipedia
*/
XML_SVG_IMAGE: 'image/svg+xml',
})
/**
* Namespaces that are used in this code base.
*
* @see http://www.w3.org/TR/REC-xml-names
*/
var NAMESPACE = freeze({
/**
* The XHTML namespace.
*
* @see http://www.w3.org/1999/xhtml
*/
HTML: 'http://www.w3.org/1999/xhtml',
/**
* Checks if `uri` equals `NAMESPACE.HTML`.
*
* @param {string} [uri]
*
* @see NAMESPACE.HTML
*/
isHTML: function (uri) {
return uri === NAMESPACE.HTML
},
/**
* The SVG namespace.
*
* @see http://www.w3.org/2000/svg
*/
SVG: 'http://www.w3.org/2000/svg',
/**
* The `xml:` namespace.
*
* @see http://www.w3.org/XML/1998/namespace
*/
XML: 'http://www.w3.org/XML/1998/namespace',
/**
* The `xmlns:` namespace
*
* @see https://www.w3.org/2000/xmlns/
*/
XMLNS: 'http://www.w3.org/2000/xmlns/',
})
exports.find = find;
exports.freeze = freeze;
exports.MIME_TYPE = MIME_TYPE;
exports.NAMESPACE = NAMESPACE;

View file

@ -0,0 +1,268 @@
var conventions = require("./conventions");
var dom = require('./dom')
var entities = require('./entities');
var sax = require('./sax');
var DOMImplementation = dom.DOMImplementation;
var NAMESPACE = conventions.NAMESPACE;
var ParseError = sax.ParseError;
var XMLReader = sax.XMLReader;
function DOMParser(options){
this.options = options ||{locator:{}};
}
DOMParser.prototype.parseFromString = function(source,mimeType){
var options = this.options;
var sax = new XMLReader();
var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
var errorHandler = options.errorHandler;
var locator = options.locator;
var defaultNSMap = options.xmlns||{};
var isHTML = /\/x?html?$/.test(mimeType);//mimeType.toLowerCase().indexOf('html') > -1;
var entityMap = isHTML ? entities.HTML_ENTITIES : entities.XML_ENTITIES;
if(locator){
domBuilder.setDocumentLocator(locator)
}
sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
sax.domBuilder = options.domBuilder || domBuilder;
if(isHTML){
defaultNSMap[''] = NAMESPACE.HTML;
}
defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML;
if(source && typeof source === 'string'){
sax.parse(source,defaultNSMap,entityMap);
}else{
sax.errorHandler.error("invalid doc source");
}
return domBuilder.doc;
}
function buildErrorHandler(errorImpl,domBuilder,locator){
if(!errorImpl){
if(domBuilder instanceof DOMHandler){
return domBuilder;
}
errorImpl = domBuilder ;
}
var errorHandler = {}
var isCallback = errorImpl instanceof Function;
locator = locator||{}
function build(key){
var fn = errorImpl[key];
if(!fn && isCallback){
fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl;
}
errorHandler[key] = fn && function(msg){
fn('[xmldom '+key+']\t'+msg+_locator(locator));
}||function(){};
}
build('warning');
build('error');
build('fatalError');
return errorHandler;
}
//console.log('#\n\n\n\n\n\n\n####')
/**
* +ContentHandler+ErrorHandler
* +LexicalHandler+EntityResolver2
* -DeclHandler-DTDHandler
*
* DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
* DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
* @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
*/
function DOMHandler() {
this.cdata = false;
}
function position(locator,node){
node.lineNumber = locator.lineNumber;
node.columnNumber = locator.columnNumber;
}
/**
* @see org.xml.sax.ContentHandler#startDocument
* @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
*/
DOMHandler.prototype = {
startDocument : function() {
this.doc = new DOMImplementation().createDocument(null, null, null);
if (this.locator) {
this.doc.documentURI = this.locator.systemId;
}
},
startElement:function(namespaceURI, localName, qName, attrs) {
var doc = this.doc;
var el = doc.createElementNS(namespaceURI, qName||localName);
var len = attrs.length;
appendElement(this, el);
this.currentElement = el;
this.locator && position(this.locator,el)
for (var i = 0 ; i < len; i++) {
var namespaceURI = attrs.getURI(i);
var value = attrs.getValue(i);
var qName = attrs.getQName(i);
var attr = doc.createAttributeNS(namespaceURI, qName);
this.locator &&position(attrs.getLocator(i),attr);
attr.value = attr.nodeValue = value;
el.setAttributeNode(attr)
}
},
endElement:function(namespaceURI, localName, qName) {
var current = this.currentElement
var tagName = current.tagName;
this.currentElement = current.parentNode;
},
startPrefixMapping:function(prefix, uri) {
},
endPrefixMapping:function(prefix) {
},
processingInstruction:function(target, data) {
var ins = this.doc.createProcessingInstruction(target, data);
this.locator && position(this.locator,ins)
appendElement(this, ins);
},
ignorableWhitespace:function(ch, start, length) {
},
characters:function(chars, start, length) {
chars = _toString.apply(this,arguments)
//console.log(chars)
if(chars){
if (this.cdata) {
var charNode = this.doc.createCDATASection(chars);
} else {
var charNode = this.doc.createTextNode(chars);
}
if(this.currentElement){
this.currentElement.appendChild(charNode);
}else if(/^\s*$/.test(chars)){
this.doc.appendChild(charNode);
//process xml
}
this.locator && position(this.locator,charNode)
}
},
skippedEntity:function(name) {
},
endDocument:function() {
this.doc.normalize();
},
setDocumentLocator:function (locator) {
if(this.locator = locator){// && !('lineNumber' in locator)){
locator.lineNumber = 0;
}
},
//LexicalHandler
comment:function(chars, start, length) {
chars = _toString.apply(this,arguments)
var comm = this.doc.createComment(chars);
this.locator && position(this.locator,comm)
appendElement(this, comm);
},
startCDATA:function() {
//used in characters() methods
this.cdata = true;
},
endCDATA:function() {
this.cdata = false;
},
startDTD:function(name, publicId, systemId) {
var impl = this.doc.implementation;
if (impl && impl.createDocumentType) {
var dt = impl.createDocumentType(name, publicId, systemId);
this.locator && position(this.locator,dt)
appendElement(this, dt);
this.doc.doctype = dt;
}
},
/**
* @see org.xml.sax.ErrorHandler
* @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
*/
warning:function(error) {
console.warn('[xmldom warning]\t'+error,_locator(this.locator));
},
error:function(error) {
console.error('[xmldom error]\t'+error,_locator(this.locator));
},
fatalError:function(error) {
throw new ParseError(error, this.locator);
}
}
function _locator(l){
if(l){
return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
}
}
function _toString(chars,start,length){
if(typeof chars == 'string'){
return chars.substr(start,length)
}else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
if(chars.length >= start+length || start){
return new java.lang.String(chars,start,length)+'';
}
return chars;
}
}
/*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
* used method of org.xml.sax.ext.LexicalHandler:
* #comment(chars, start, length)
* #startCDATA()
* #endCDATA()
* #startDTD(name, publicId, systemId)
*
*
* IGNORED method of org.xml.sax.ext.LexicalHandler:
* #endDTD()
* #startEntity(name)
* #endEntity(name)
*
*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
* IGNORED method of org.xml.sax.ext.DeclHandler
* #attributeDecl(eName, aName, type, mode, value)
* #elementDecl(name, model)
* #externalEntityDecl(name, publicId, systemId)
* #internalEntityDecl(name, value)
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
* IGNORED method of org.xml.sax.EntityResolver2
* #resolveEntity(String name,String publicId,String baseURI,String systemId)
* #resolveEntity(publicId, systemId)
* #getExternalSubset(name, baseURI)
* @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
* IGNORED method of org.xml.sax.DTDHandler
* #notationDecl(name, publicId, systemId) {};
* #unparsedEntityDecl(name, publicId, systemId, notationName) {};
*/
"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
DOMHandler.prototype[key] = function(){return null}
})
/* 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 */
function appendElement (hander,node) {
if (!hander.currentElement) {
hander.doc.appendChild(node);
} else {
hander.currentElement.appendChild(node);
}
}//appendChild and setAttributeNS are preformance key
exports.__DOMHandler = DOMHandler;
exports.DOMParser = DOMParser;
/**
* @deprecated Import/require from main entry point instead
*/
exports.DOMImplementation = dom.DOMImplementation;
/**
* @deprecated Import/require from main entry point instead
*/
exports.XMLSerializer = dom.XMLSerializer;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
var dom = require('./dom')
exports.DOMImplementation = dom.DOMImplementation
exports.XMLSerializer = dom.XMLSerializer
exports.DOMParser = require('./dom-parser').DOMParser

View file

@ -0,0 +1,656 @@
var NAMESPACE = require("./conventions").NAMESPACE;
//[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
//[5] Name ::= NameStartChar (NameChar)*
var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
//var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
var S_TAG = 0;//tag name offerring
var S_ATTR = 1;//attr name offerring
var S_ATTR_SPACE=2;//attr name end and space offer
var S_EQ = 3;//=space?
var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
var S_ATTR_END = 5;//attr value end and no space(quot end)
var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
var S_TAG_CLOSE = 7;//closed el<el />
/**
* Creates an error that will not be caught by XMLReader aka the SAX parser.
*
* @param {string} message
* @param {any?} locator Optional, can provide details about the location in the source
* @constructor
*/
function ParseError(message, locator) {
this.message = message
this.locator = locator
if(Error.captureStackTrace) Error.captureStackTrace(this, ParseError);
}
ParseError.prototype = new Error();
ParseError.prototype.name = ParseError.name
function XMLReader(){
}
XMLReader.prototype = {
parse:function(source,defaultNSMap,entityMap){
var domBuilder = this.domBuilder;
domBuilder.startDocument();
_copy(defaultNSMap ,defaultNSMap = {})
parse(source,defaultNSMap,entityMap,
domBuilder,this.errorHandler);
domBuilder.endDocument();
}
}
function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
function fixedFromCharCode(code) {
// String.prototype.fromCharCode does not supports
// > 2 bytes unicode chars directly
if (code > 0xffff) {
code -= 0x10000;
var surrogate1 = 0xd800 + (code >> 10)
, surrogate2 = 0xdc00 + (code & 0x3ff);
return String.fromCharCode(surrogate1, surrogate2);
} else {
return String.fromCharCode(code);
}
}
function entityReplacer(a){
var k = a.slice(1,-1);
if(k in entityMap){
return entityMap[k];
}else if(k.charAt(0) === '#'){
return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
}else{
errorHandler.error('entity not found:'+a);
return a;
}
}
function appendText(end){//has some bugs
if(end>start){
var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
locator&&position(start);
domBuilder.characters(xt,0,end-start);
start = end
}
}
function position(p,m){
while(p>=lineEnd && (m = linePattern.exec(source))){
lineStart = m.index;
lineEnd = lineStart + m[0].length;
locator.lineNumber++;
//console.log('line++:',locator,startPos,endPos)
}
locator.columnNumber = p-lineStart+1;
}
var lineStart = 0;
var lineEnd = 0;
var linePattern = /.*(?:\r\n?|\n)|.*$/g
var locator = domBuilder.locator;
var parseStack = [{currentNSMap:defaultNSMapCopy}]
var closeMap = {};
var start = 0;
while(true){
try{
var tagStart = source.indexOf('<',start);
if(tagStart<0){
if(!source.substr(start).match(/^\s*$/)){
var doc = domBuilder.doc;
var text = doc.createTextNode(source.substr(start));
doc.appendChild(text);
domBuilder.currentElement = text;
}
return;
}
if(tagStart>start){
appendText(tagStart);
}
switch(source.charAt(tagStart+1)){
case '/':
var end = source.indexOf('>',tagStart+3);
var tagName = source.substring(tagStart + 2, end).replace(/[ \t\n\r]+$/g, '');
var config = parseStack.pop();
if(end<0){
tagName = source.substring(tagStart+2).replace(/[\s<].*/,'');
errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName);
end = tagStart+1+tagName.length;
}else if(tagName.match(/\s</)){
tagName = tagName.replace(/[\s<].*/,'');
errorHandler.error("end tag name: "+tagName+' maybe not complete');
end = tagStart+1+tagName.length;
}
var localNSMap = config.localNSMap;
var endMatch = config.tagName == tagName;
var endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase()
if(endIgnoreCaseMach){
domBuilder.endElement(config.uri,config.localName,tagName);
if(localNSMap){
for(var prefix in localNSMap) {
if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) {
domBuilder.endPrefixMapping(prefix);
}
}
}
if(!endMatch){
errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName ); // No known test case
}
}else{
parseStack.push(config)
}
end++;
break;
// end elment
case '?':// <?...?>
locator&&position(tagStart);
end = parseInstruction(source,tagStart,domBuilder);
break;
case '!':// <!doctype,<![CDATA,<!--
locator&&position(tagStart);
end = parseDCC(source,tagStart,domBuilder,errorHandler);
break;
default:
locator&&position(tagStart);
var el = new ElementAttributes();
var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
//elStartEnd
var end = parseElementStartPart(source,tagStart,el,currentNSMap,entityReplacer,errorHandler);
var len = el.length;
if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
el.closed = true;
if(!entityMap.nbsp){
errorHandler.warning('unclosed xml attribute');
}
}
if(locator && len){
var locator2 = copyLocator(locator,{});
//try{//attribute position fixed
for(var i = 0;i<len;i++){
var a = el[i];
position(a.offset);
a.locator = copyLocator(locator,{});
}
domBuilder.locator = locator2
if(appendElement(el,domBuilder,currentNSMap)){
parseStack.push(el)
}
domBuilder.locator = locator;
}else{
if(appendElement(el,domBuilder,currentNSMap)){
parseStack.push(el)
}
}
if (NAMESPACE.isHTML(el.uri) && !el.closed) {
end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder)
} else {
end++;
}
}
}catch(e){
if (e instanceof ParseError) {
throw e;
}
errorHandler.error('element parse error: '+e)
end = -1;
}
if(end>start){
start = end;
}else{
//TODO: 这里有可能sax回退有位置错误风险
appendText(Math.max(tagStart,start)+1);
}
}
}
function copyLocator(f,t){
t.lineNumber = f.lineNumber;
t.columnNumber = f.columnNumber;
return t;
}
/**
* @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
* @return end of the elementStartPart(end of elementEndPart for selfClosed el)
*/
function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
/**
* @param {string} qname
* @param {string} value
* @param {number} startIndex
*/
function addAttribute(qname, value, startIndex) {
if (el.attributeNames.hasOwnProperty(qname)) {
errorHandler.fatalError('Attribute ' + qname + ' redefined')
}
el.addValue(qname, value, startIndex)
}
var attrName;
var value;
var p = ++start;
var s = S_TAG;//status
while(true){
var c = source.charAt(p);
switch(c){
case '=':
if(s === S_ATTR){//attrName
attrName = source.slice(start,p);
s = S_EQ;
}else if(s === S_ATTR_SPACE){
s = S_EQ;
}else{
//fatalError: equal must after attrName or space after attrName
throw new Error('attribute equal must after attrName'); // No known test case
}
break;
case '\'':
case '"':
if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
){//equal
if(s === S_ATTR){
errorHandler.warning('attribute value must after "="')
attrName = source.slice(start,p)
}
start = p+1;
p = source.indexOf(c,start)
if(p>0){
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
addAttribute(attrName, value, start-1);
s = S_ATTR_END;
}else{
//fatalError: no end quot match
throw new Error('attribute value no end \''+c+'\' match');
}
}else if(s == S_ATTR_NOQUOT_VALUE){
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
//console.log(attrName,value,start,p)
addAttribute(attrName, value, start);
//console.dir(el)
errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
start = p+1;
s = S_ATTR_END
}else{
//fatalError: no equal before
throw new Error('attribute value must after "="'); // No known test case
}
break;
case '/':
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));
case S_ATTR_END:
case S_TAG_SPACE:
case S_TAG_CLOSE:
s =S_TAG_CLOSE;
el.closed = true;
case S_ATTR_NOQUOT_VALUE:
case S_ATTR:
break;
case S_ATTR_SPACE:
el.closed = true;
break;
//case S_EQ:
default:
throw new Error("attribute invalid close char('/')") // No known test case
}
break;
case ''://end document
errorHandler.error('unexpected end of input');
if(s == S_TAG){
el.setTagName(source.slice(start,p));
}
return p;
case '>':
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));
case S_ATTR_END:
case S_TAG_SPACE:
case S_TAG_CLOSE:
break;//normal
case S_ATTR_NOQUOT_VALUE://Compatible state
case S_ATTR:
value = source.slice(start,p);
if(value.slice(-1) === '/'){
el.closed = true;
value = value.slice(0,-1)
}
case S_ATTR_SPACE:
if(s === S_ATTR_SPACE){
value = attrName;
}
if(s == S_ATTR_NOQUOT_VALUE){
errorHandler.warning('attribute "'+value+'" missed quot(")!');
addAttribute(attrName, value.replace(/&#?\w+;/g,entityReplacer), start)
}else{
if(!NAMESPACE.isHTML(currentNSMap['']) || !value.match(/^(?:disabled|checked|selected)$/i)){
errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
}
addAttribute(value, value, start)
}
break;
case S_EQ:
throw new Error('attribute value missed!!');
}
// console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
return p;
/*xml space '\x20' | #x9 | #xD | #xA; */
case '\u0080':
c = ' ';
default:
if(c<= ' '){//space
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));//tagName
s = S_TAG_SPACE;
break;
case S_ATTR:
attrName = source.slice(start,p)
s = S_ATTR_SPACE;
break;
case S_ATTR_NOQUOT_VALUE:
var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
errorHandler.warning('attribute "'+value+'" missed quot(")!!');
addAttribute(attrName, value, start)
case S_ATTR_END:
s = S_TAG_SPACE;
break;
//case S_TAG_SPACE:
//case S_EQ:
//case S_ATTR_SPACE:
// void();break;
//case S_TAG_CLOSE:
//ignore warning
}
}else{//not space
//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
switch(s){
//case S_TAG:void();break;
//case S_ATTR:void();break;
//case S_ATTR_NOQUOT_VALUE:void();break;
case S_ATTR_SPACE:
var tagName = el.tagName;
if (!NAMESPACE.isHTML(currentNSMap['']) || !attrName.match(/^(?:disabled|checked|selected)$/i)) {
errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!')
}
addAttribute(attrName, attrName, start);
start = p;
s = S_ATTR;
break;
case S_ATTR_END:
errorHandler.warning('attribute space is required"'+attrName+'"!!')
case S_TAG_SPACE:
s = S_ATTR;
start = p;
break;
case S_EQ:
s = S_ATTR_NOQUOT_VALUE;
start = p;
break;
case S_TAG_CLOSE:
throw new Error("elements closed character '/' and '>' must be connected to");
}
}
}//end outer switch
//console.log('p++',p)
p++;
}
}
/**
* @return true if has new namespace define
*/
function appendElement(el,domBuilder,currentNSMap){
var tagName = el.tagName;
var localNSMap = null;
//var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
var i = el.length;
while(i--){
var a = el[i];
var qName = a.qName;
var value = a.value;
var nsp = qName.indexOf(':');
if(nsp>0){
var prefix = a.prefix = qName.slice(0,nsp);
var localName = qName.slice(nsp+1);
var nsPrefix = prefix === 'xmlns' && localName
}else{
localName = qName;
prefix = null
nsPrefix = qName === 'xmlns' && ''
}
//can not set prefix,because prefix !== ''
a.localName = localName ;
//prefix == null for no ns prefix attribute
if(nsPrefix !== false){//hack!!
if(localNSMap == null){
localNSMap = {}
//console.log(currentNSMap,0)
_copy(currentNSMap,currentNSMap={})
//console.log(currentNSMap,1)
}
currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
a.uri = NAMESPACE.XMLNS
domBuilder.startPrefixMapping(nsPrefix, value)
}
}
var i = el.length;
while(i--){
a = el[i];
var prefix = a.prefix;
if(prefix){//no prefix attribute has no namespace
if(prefix === 'xml'){
a.uri = NAMESPACE.XML;
}if(prefix !== 'xmlns'){
a.uri = currentNSMap[prefix || '']
//{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
}
}
}
var nsp = tagName.indexOf(':');
if(nsp>0){
prefix = el.prefix = tagName.slice(0,nsp);
localName = el.localName = tagName.slice(nsp+1);
}else{
prefix = null;//important!!
localName = el.localName = tagName;
}
//no prefix element has default namespace
var ns = el.uri = currentNSMap[prefix || ''];
domBuilder.startElement(ns,localName,tagName,el);
//endPrefixMapping and startPrefixMapping have not any help for dom builder
//localNSMap = null
if(el.closed){
domBuilder.endElement(ns,localName,tagName);
if(localNSMap){
for (prefix in localNSMap) {
if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) {
domBuilder.endPrefixMapping(prefix);
}
}
}
}else{
el.currentNSMap = currentNSMap;
el.localNSMap = localNSMap;
//parseStack.push(el);
return true;
}
}
function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
if(/^(?:script|textarea)$/i.test(tagName)){
var elEndStart = source.indexOf('</'+tagName+'>',elStartEnd);
var text = source.substring(elStartEnd+1,elEndStart);
if(/[&<]/.test(text)){
if(/^script$/i.test(tagName)){
//if(!/\]\]>/.test(text)){
//lexHandler.startCDATA();
domBuilder.characters(text,0,text.length);
//lexHandler.endCDATA();
return elEndStart;
//}
}//}else{//text area
text = text.replace(/&#?\w+;/g,entityReplacer);
domBuilder.characters(text,0,text.length);
return elEndStart;
//}
}
}
return elStartEnd+1;
}
function fixSelfClosed(source,elStartEnd,tagName,closeMap){
//if(tagName in closeMap){
var pos = closeMap[tagName];
if(pos == null){
//console.log(tagName)
pos = source.lastIndexOf('</'+tagName+'>')
if(pos<elStartEnd){//忘记闭合
pos = source.lastIndexOf('</'+tagName)
}
closeMap[tagName] =pos
}
return pos<elStartEnd;
//}
}
function _copy (source, target) {
for (var n in source) {
if (Object.prototype.hasOwnProperty.call(source, n)) {
target[n] = source[n];
}
}
}
function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
var next= source.charAt(start+2)
switch(next){
case '-':
if(source.charAt(start + 3) === '-'){
var end = source.indexOf('-->',start+4);
//append comment source.substring(4,end)//<!--
if(end>start){
domBuilder.comment(source,start+4,end-start-4);
return end+3;
}else{
errorHandler.error("Unclosed comment");
return -1;
}
}else{
//error
return -1;
}
default:
if(source.substr(start+3,6) == 'CDATA['){
var end = source.indexOf(']]>',start+9);
domBuilder.startCDATA();
domBuilder.characters(source,start+9,end-start-9);
domBuilder.endCDATA()
return end+3;
}
//<!DOCTYPE
//startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
var matchs = split(source,start);
var len = matchs.length;
if(len>1 && /!doctype/i.test(matchs[0][0])){
var name = matchs[1][0];
var pubid = false;
var sysid = false;
if(len>3){
if(/^public$/i.test(matchs[2][0])){
pubid = matchs[3][0];
sysid = len>4 && matchs[4][0];
}else if(/^system$/i.test(matchs[2][0])){
sysid = matchs[3][0];
}
}
var lastMatch = matchs[len-1]
domBuilder.startDTD(name, pubid, sysid);
domBuilder.endDTD();
return lastMatch.index+lastMatch[0].length
}
}
return -1;
}
function parseInstruction(source,start,domBuilder){
var end = source.indexOf('?>',start);
if(end){
var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
if(match){
var len = match[0].length;
domBuilder.processingInstruction(match[1], match[2]) ;
return end+2;
}else{//error
return -1;
}
}
return -1;
}
function ElementAttributes(){
this.attributeNames = {}
}
ElementAttributes.prototype = {
setTagName:function(tagName){
if(!tagNamePattern.test(tagName)){
throw new Error('invalid tagName:'+tagName)
}
this.tagName = tagName
},
addValue:function(qName, value, offset) {
if(!tagNamePattern.test(qName)){
throw new Error('invalid attribute:'+qName)
}
this.attributeNames[qName] = this.length;
this[this.length++] = {qName:qName,value:value,offset:offset}
},
length:0,
getLocalName:function(i){return this[i].localName},
getLocator:function(i){return this[i].locator},
getQName:function(i){return this[i].qName},
getURI:function(i){return this[i].uri},
getValue:function(i){return this[i].value}
// ,getIndex:function(uri, localName)){
// if(localName){
//
// }else{
// var qName = uri
// }
// },
// getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
// getType:function(uri,localName){}
// getType:function(i){},
}
function split(source,start){
var match;
var buf = [];
var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
reg.lastIndex = start;
reg.exec(source);//skip <
while(match = reg.exec(source)){
buf.push(match);
if(match[1])return buf;
}
}
exports.XMLReader = XMLReader;
exports.ParseError = ParseError;

View file

@ -0,0 +1,60 @@
{
"name": "@xmldom/xmldom",
"version": "0.7.13",
"description": "A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module.",
"keywords": [
"w3c",
"dom",
"xml",
"parser",
"javascript",
"DOMParser",
"XMLSerializer",
"ponyfill"
],
"homepage": "https://github.com/xmldom/xmldom",
"repository": {
"type": "git",
"url": "git://github.com/xmldom/xmldom.git"
},
"main": "lib/index.js",
"types": "index.d.ts",
"files": [
"CHANGELOG.md",
"LICENSE",
"readme.md",
"index.d.ts",
"lib"
],
"scripts": {
"lint": "eslint lib test",
"start": "nodemon --watch package.json --watch lib --watch test --exec 'npm --silent run test && npm --silent run lint'",
"stryker": "stryker run",
"stryker:dry-run": "stryker run -m '' --reporters progress",
"test": "jest",
"testrelease": "npm test && eslint lib",
"release": "np --no-yarn --test-script testrelease --branch release-0.7.x --tag lts patch"
},
"engines": {
"node": ">=10.0.0"
},
"dependencies": {},
"devDependencies": {
"@stryker-mutator/core": "^5.2.2",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-es5": "^1.5.0",
"eslint-plugin-prettier": "^3.4.1",
"get-stream": "^6.0.1",
"jest": "^27.0.6",
"nodemon": "^2.0.12",
"np": "7.6.2",
"prettier": "^2.3.2",
"xmltest": "^1.5.0",
"yauzl": "^2.10.0"
},
"bugs": {
"url": "https://github.com/xmldom/xmldom/issues"
},
"license": "MIT"
}

View file

@ -0,0 +1,338 @@
# @xmldom/xmldom
***Since version 0.7.0 this package is published to npm as [`@xmldom/xmldom`](https://www.npmjs.com/package/@xmldom/xmldom) and no longer as [`xmldom`](https://www.npmjs.com/package/xmldom), because [we are no longer able to publish `xmldom`](https://github.com/xmldom/xmldom/issues/271).***
*For better readability in the docs we will continue to talk about this library as "xmldom".*
[![license](https://img.shields.io/npm/l/@xmldom/xmldom?color=blue&style=flat-square)](LICENSE)
[![npm](https://img.shields.io/npm/v/@xmldom/xmldom?style=flat-square)](https://www.npmjs.com/package/@xmldom/xmldom)
[![bug issues](https://img.shields.io/github/issues/xmldom/xmldom/bug?color=red&style=flat-square)](https://github.com/xmldom/xmldom/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
[![help-wanted issues](https://img.shields.io/github/issues/xmldom/xmldom/help-wanted?color=darkgreen&style=flat-square)](https://github.com/xmldom/xmldom/issues?q=is%3Aissue+is%3Aopen+label%3Ahelp-wanted)
[![Mutation report](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fxmldom%2Fxmldom%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/xmldom/xmldom/master)
xmldom is a javascript [ponyfill](https://ponyfill.com/) to provide the following APIs [that are present in modern browsers](https://caniuse.com/xml-serializer) to other runtimes:
- convert an XML string into a DOM tree
```
new DOMParser().parseFromString(xml, mimeType) => Document
```
- create, access and modify a DOM tree
```
new DOMImplementation().createDocument(...) => Document
```
- serialize a DOM tree back into an XML string
```
new XMLSerializer().serializeToString(node) => string
```
The target runtimes `xmldom` supports are currently Node >= v10 (ES5) and Rhino ([not tested as part of CI](https://github.com/xmldom/xmldom/discussions/214)).
When deciding how to fix bugs or implement features, `xmldom` tries to stay as close as possible to the various [related specifications/standards](#specs).
As indicated by the version starting with `0.`, this implementation is not feature complete and some implemented features differ from what the specifications describe.
**Issues and PRs for such differences are always welcome, even when they only provide a failing test case.**
This project was forked from it's [original source](https://github.com/jindw/xmldom) in 2019, more details about that transition can be found in the [CHANGELOG](CHANGELOG.md#maintainer-changes).
## Usage
### Install:
> npm install @xmldom/xmldom
### Example:
```javascript
const { DOMParser } = require('@xmldom/xmldom')
const doc = new DOMParser().parseFromString(
'<xml xmlns="a" xmlns:c="./lite">\n' +
'\t<child>test</child>\n' +
'\t<child></child>\n' +
'\t<child/>\n' +
'</xml>',
'text/xml'
)
doc.documentElement.setAttribute('x', 'y')
doc.documentElement.setAttributeNS('./lite', 'c:x', 'y2')
console.info(doc)
const nsAttr = doc.documentElement.getAttributeNS('./lite', 'x')
console.info(nsAttr)
```
Note: in Typescript and ES6 you can use the import approach, as follows:
```javascript
import { DOMParser } from '@xmldom/xmldom'
```
## API Reference
* [DOMParser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser):
```javascript
parseFromString(xmlsource,mimeType)
```
* **options extension** _by xmldom_ (not DOM standard!!)
```javascript
//added the options argument
new DOMParser(options)
//errorHandler is supported
new DOMParser({
/**
* locator is always need for error position info
*/
locator:{},
/**
* you can override the errorHandler for xml parser
* @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
*/
errorHandler:{warning:function(w){console.warn(w)},error:callback,fatalError:callback}
//only callback model
//errorHandler:function(level,msg){console.log(level,msg)}
})
```
* [XMLSerializer](https://developer.mozilla.org/en-US/docs/Web/API/XMLSerializer)
```javascript
serializeToString(node)
```
### DOM level2 method and attribute:
* [Node](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247)
attribute:
nodeValue|prefix
readonly attribute:
nodeName|nodeType|parentNode|childNodes|firstChild|lastChild|previousSibling|nextSibling|attributes|ownerDocument|namespaceURI|localName
method:
insertBefore(newChild, refChild)
replaceChild(newChild, oldChild)
removeChild(oldChild)
appendChild(newChild)
hasChildNodes()
cloneNode(deep)
normalize()
isSupported(feature, version)
hasAttributes()
* [DOMException](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html)
The DOMException class has the following constants (and `value` of type `Number`):
1. `DOMException.INDEX_SIZE_ERR` (`1`)
1. `DOMException.DOMSTRING_SIZE_ERR` (`2`)
1. `DOMException.HIERARCHY_REQUEST_ERR` (`3`)
1. `DOMException.WRONG_DOCUMENT_ERR` (`4`)
1. `DOMException.INVALID_CHARACTER_ERR` (`5`)
1. `DOMException.NO_DATA_ALLOWED_ERR` (`6`)
1. `DOMException.NO_MODIFICATION_ALLOWED_ERR` (`7`)
1. `DOMException.NOT_FOUND_ERR` (`8`)
1. `DOMException.NOT_SUPPORTED_ERR` (`9`)
1. `DOMException.INUSE_ATTRIBUTE_ERR` (`10`)
1. `DOMException.INVALID_STATE_ERR` (`11`)
1. `DOMException.SYNTAX_ERR` (`12`)
1. `DOMException.INVALID_MODIFICATION_ERR` (`13`)
1. `DOMException.NAMESPACE_ERR` (`14`)
1. `DOMException.INVALID_ACCESS_ERR` (`15`)
The DOMException object has the following properties:
code
This property is of type Number.
* extends the Error type thrown as part of DOM API:
* [DOMImplementation](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-102161490)
method:
hasFeature(feature, version)
createDocumentType(qualifiedName, publicId, systemId)
createDocument(namespaceURI, qualifiedName, doctype)
* [Document](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#i-Document) : Node
readonly attribute:
doctype|implementation|documentElement
method:
createElement(tagName)
createDocumentFragment()
createTextNode(data)
createComment(data)
createCDATASection(data)
createProcessingInstruction(target, data)
createAttribute(name)
createEntityReference(name)
getElementsByTagName(tagname)
importNode(importedNode, deep)
createElementNS(namespaceURI, qualifiedName)
createAttributeNS(namespaceURI, qualifiedName)
getElementsByTagNameNS(namespaceURI, localName)
getElementById(elementId)
* [DocumentFragment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-B63ED1A3) : Node
* [Element](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-745549614) : Node
readonly attribute:
tagName
method:
getAttribute(name)
setAttribute(name, value)
removeAttribute(name)
getAttributeNode(name)
setAttributeNode(newAttr)
removeAttributeNode(oldAttr)
getElementsByTagName(name)
getAttributeNS(namespaceURI, localName)
setAttributeNS(namespaceURI, qualifiedName, value)
removeAttributeNS(namespaceURI, localName)
getAttributeNodeNS(namespaceURI, localName)
setAttributeNodeNS(newAttr)
getElementsByTagNameNS(namespaceURI, localName)
hasAttribute(name)
hasAttributeNS(namespaceURI, localName)
* [Attr](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-637646024) : Node
attribute:
value
readonly attribute:
name|specified|ownerElement
* [NodeList](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177)
readonly attribute:
length
method:
item(index)
* [NamedNodeMap](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1780488922)
readonly attribute:
length
method:
getNamedItem(name)
setNamedItem(arg)
removeNamedItem(name)
item(index)
getNamedItemNS(namespaceURI, localName)
setNamedItemNS(arg)
removeNamedItemNS(namespaceURI, localName)
* [CharacterData](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-FF21A306) : Node
method:
substringData(offset, count)
appendData(arg)
insertData(offset, arg)
deleteData(offset, count)
replaceData(offset, count, arg)
* [Text](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1312295772) : CharacterData
method:
splitText(offset)
* [CDATASection](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-667469212)
* [Comment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1728279322) : CharacterData
* [DocumentType](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-412266927)
readonly attribute:
name|entities|notations|publicId|systemId|internalSubset
* Notation : Node
readonly attribute:
publicId|systemId
* Entity : Node
readonly attribute:
publicId|systemId|notationName
* EntityReference : Node
* ProcessingInstruction : Node
attribute:
data
readonly attribute:
target
### DOM level 3 support:
* [Node](http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-textContent)
attribute:
textContent
method:
isDefaultNamespace(namespaceURI){
lookupNamespaceURI(prefix)
### DOM extension by xmldom
* [Node] Source position extension;
attribute:
//Numbered starting from '1'
lineNumber
//Numbered starting from '1'
columnNumber
## Specs
The implementation is based on several specifications:
<!-- Should open in new tab and the links in the SVG should be clickable there! -->
<a href="https://raw.githubusercontent.com/xmldom/xmldom/master/docs/specs.svg" target="_blank" rel="noopener noreferrer nofollow" >![Overview of related specifications and their relations](docs/specs.svg)</a>
### DOM Parsing and Serialization
From the [W3C DOM Parsing and Serialization (WD 2016)](https://www.w3.org/TR/2016/WD-DOM-Parsing-20160517/) `xmldom` provides an implementation for the interfaces:
- `DOMParser`
- `XMLSerializer`
Note that there are some known deviations between this implementation and the W3 specifications.
Note: [The latest version of this spec](https://w3c.github.io/DOM-Parsing/) has the status "Editors Draft", since it is under active development. One major change is that [the definition of the `DOMParser` interface has been moved to the HTML spec](https://w3c.github.io/DOM-Parsing/#the-domparser-interface)
### DOM
The original author claims that xmldom implements [DOM Level 2] in a "fully compatible" way and some parts of [DOM Level 3], but there are not enough tests to prove this. Both Specifications are now superseded by the [DOM Level 4 aka Living standard] wich has a much broader scope than xmldom.
xmldom implements the following interfaces (most constructors are currently not exposed):
- `Attr`
- `CDATASection`
- `CharacterData`
- `Comment`
- `Document`
- `DocumentFragment`
- `DocumentType`
- `DOMException` (constructor exposed)
- `DOMImplementation` (constructor exposed)
- `Element`
- `Entity`
- `EntityReference`
- `LiveNodeList`
- `NamedNodeMap`
- `Node` (constructor exposed)
- `NodeList`
- `Notation`
- `ProcessingInstruction`
- `Text`
more details are available in the (incomplete) [API Reference](#api-reference) section.
### HTML
xmldom does not have any goal of supporting the full spec, but it has some capability to parse, report and serialize things differently when "detecting HTML" (by checking the default namespace).
There is an upcoming change to better align the implementation with the latest specs, related to <https://github.com/xmldom/xmldom/issues/203>.
### SAX, XML, XMLNS
xmldom has an own SAX parser implementation to do the actual parsing, which implements some interfaces in alignment with the Java interfaces SAX defines:
- `XMLReader`
- `DOMHandler`
There is an idea/proposal to make ti possible to replace it with something else in <https://github.com/xmldom/xmldom/issues/55>

1
node_modules/mergexml/node_modules/xpath/.npmignore generated vendored Normal file
View file

@ -0,0 +1 @@
node_modules/

133
node_modules/mergexml/node_modules/xpath/README.md generated vendored Normal file
View file

@ -0,0 +1,133 @@
## xpath
DOM 3 XPath 1.0 implemention and helper for JavaScript, with node.js support.
Originally written by Cameron McCormack ([blog](http://mcc.id.au/xpathjs)).
Additional contributions from
Yaron Naveh ([blog](http://webservices20.blogspot.com/))
goto100
Thomas Weinert
Jimmy Rishe
and [others](https://github.com/goto100/xpath/graphs/contributors)
## Install
Install with [npm](http://github.com/isaacs/npm):
npm install xpath
xpath is xml engine agnostic but I recommend to use [xmldom](https://github.com/jindw/xmldom):
npm install xmldom
## API Documentation
Can be found [here](https://github.com/goto100/xpath/blob/master/docs/xpath%20methods.md). See below for example usage.
## Your first xpath:
`````javascript
var xpath = require('xpath')
, dom = require('xmldom').DOMParser
var xml = "<book><title>Harry Potter</title></book>"
var doc = new dom().parseFromString(xml)
var nodes = xpath.select("//title", doc)
console.log(nodes[0].localName + ": " + nodes[0].firstChild.data)
console.log("Node: " + nodes[0].toString())
`````
title: Harry Potter
Node: <title>Harry Potter</title>
### Alternatively
Using the same interface you have on modern browsers ([MDN])
`````javascript
var node = null;
var xml = "<book author='J. K. Rowling'><title>Harry Potter</title></book>"
var doc = new dom().parseFromString(xml)
var result = xpath.evaluate(
"/book/title", // xpathExpression
doc, // contextNode
null, // namespaceResolver
xpath.XPathResult.ANY_TYPE, // resultType
null // result
)
node = result.iterateNext();
while (node) {
console.log(node.localName + ": " + node.firstChild.data);
console.log("Node: " + node.toString());
node = result.iterateNext();
}
`````
title: Harry Potter
Node: <title>Harry Potter</title>
## Evaluate string values directly:
`````javascript
var xml = "<book><title>Harry Potter</title></book>";
var doc = new dom().parseFromString(xml);
var title = xpath.select("string(//title)", doc);
console.log(title);
`````
Harry Potter
## Namespaces
`````javascript
var xml = "<book><title xmlns='myns'>Harry Potter</title></book>"
var doc = new dom().parseFromString(xml)
var node = xpath.select("//*[local-name(.)='title' and namespace-uri(.)='myns']", doc)[0]
console.log(node.namespaceURI)
`````
myns
## Namespaces with easy mappings
`````javascript
var xml = "<book xmlns:bookml='http://example.com/book'><bookml:title>Harry Potter</bookml:title></book>"
var select = xpath.useNamespaces({"bookml": "http://example.com/book"});
console.log(select('//bookml:title/text()', doc)[0].nodeValue);
`````
Harry Potter
## Default namespace with mapping
`````javascript
var xml = "<book xmlns='http://example.com/book'><title>Harry Potter</title></book>"
var select = xpath.useNamespaces({"bookml": "http://example.com/book"});
console.log(select('//bookml:title/text()', doc)[0].nodeValue);
`````
Harry Potter
## Attributes
`````javascript
var xml = "<book author='J. K. Rowling'><title>Harry Potter</title></book>"
var doc = new dom().parseFromString(xml)
var author = xpath.select1("/book/@author", doc).value
console.log(author)
`````
J. K. Rowling
[MDN]: https://developer.mozilla.org/en/docs/Web/API/Document/evaluate
## License
MIT

View file

@ -0,0 +1,62 @@
# `XPathEvaluator`
The `xpath.parse()` method returns an `XPathEvaluator`, which contains the following methods.
Each of these methods takes an optional `options` object, which can contain any of the following properties:
`namespaces` - a namespace resolver. See the [documentation page](namespace%20resolvers.md) for details.
`variables` - a variable resolver. See the [documentation page](variable%20resolvers.md) for details.
`functions` - a function resolver. See the [documentation page](function%20resolvers.md) for details.
`node` - the context node for evaluating the expression
Example usage:
```js
var evaluator = xpath.parse('/characters/character[@greeting = $greeting]');
var character = evaluator.select1({
node: myCharacterDoc,
variables: {
greeting: "Hello, I'm Harry, Harry Potter."
}
});
```
## `XPathEvaluator` methods
`evaluate([options])`
Evaluates the XPath expression and returns the result. The resulting type is determined based on the type of the expression, using the same criteria as [`xpath.select`](xpath%20methods.md).
`evaluateNumber([options])`
Evaluates the XPath expression and returns the result as a number.
`evaluateString([options])`
Evaluates the XPath expression and returns the result as a string.
`evaluateBoolean([options])`
Evaluates the XPath expression and returns the result as a boolean value.
`evaluateNodeSet([options])`
Evaluates the XPath expression and returns the result as an XNodeSet. See the [documentation page](#) for details on this interface.
This is only valid for expressions that evaluate to a node set.
`select([options])`
Evaluates the XPath expression and returns an array of the resulting nodes, in document order.
This is only valid for expressions that evaluate to a node set.
`select1([options])`
Evaluates the XPath expression and the first node in the resulting node set, in document order. Returns `undefined`
This is only valid for expressions that evaluate to a node set.

View file

@ -0,0 +1,47 @@
# XPathResult interface
Represents the result of an XPath expression. This interface is used for the parameters passed into custom functions
used in [function resolvers](function resolvers.md) and can represent a number, a string, a boolean value, or a node set.
## Methods
```js
booleanValue() -> boolean
```
Returns the boolean value of the result in accordance with the XPath 1.0 spec.
```js
numberValue() -> number
```
Returns the numeric value of the result in accordance with the XPath 1.0 spec.
```js
stringValue() -> string
```
Returns the string value of the result in accordance with the XPath 1.0 spec.
## Methods and properties that are only present on `XPathResult`s representing node sets
```js
toArray() -> Array of nodes
```
Returns an array of the nodes in the node set, in document order.
```js
first() -> Node
```
Returns the first node in the node set, in document order.
```js
size -> number
```
Returns the number of nodes in this node set

View file

@ -0,0 +1,88 @@
# Function Resolvers
The methods on the [XPathEvaluator](XPathEvaluator.md) type can optionally take a function resolver to resolve
function references in the XPath expression being evaluated.
There are three ways to specify a function resolver and you can use any one of them depending on which is
most suited to your particular situation.
Note that if your functions are in a namespace (e.g. `fn:myFunction()`), you must use the second or third
type as the plain object implementation does not support namespaces.
## Function implementations
Custom XPath functions are implemented as JavaScript functions taking one or more arguments.
The first argument passed in is a context object containing a number of properties relating to the execution context,
the most important being `contextNode`, the context in which the function is being evaluated.
The remaining arguments are the arguments passed into the XPath function, as instances of the `XPathResult` interface.
Please see [the documentation on that interface](XPathResult.md) for details.
As the return value, you can return a string, number, boolean, single node, or array of nodes.
## Function Resolver Type 1: Plain object
A plain object with function names as the keys and function implementations as the values.
Example usage:
```js
var evaluator = xpath.parse('squareRoot(10)');
var aboutPi = evaluator.evaluateNumber({
functions: {
'squareRoot': function (c, value) {
return Math.sqrt(value.numberValue());
}
}
});
```
## Function Resolver Type 2: Function
A function that takes a function name as its first parameter and an optional namespace URI as its second parameter
and returns a function based on the name and namespace.
Example usage:
```js
var evaluator = xpath.parse('math:squareRoot(10)');
var aboutPi = evaluator.evaluateNumber({
functions: function (name, namespace) {
if (name === 'squareRoot' && namespace === 'http://sample.org/math/') {
return function (c, value) {
return Math.sqrt(value.numberValue());
};
}
},
namespaces: {
math: 'http://sample.org/math/'
}
});
```
## Function Resolver Type 3: Object with `getFunction` method
An object with a method named `getFunction` that works in the same way as the function-based function resolver
described above.
Example usage:
```js
var evaluator = xpath.parse('math:squareRoot(10)');
var aboutPi = evaluator.evaluateNumber({
functions: {
getFunction: function (name, namespace) {
if (name === 'squareRoot' && namespace === 'http://sample.org/math/') {
return function (c, value) {
return Math.sqrt(value.numberValue());
};
}
}
},
namespaces: {
math: 'http://sample.org/math/'
}
});
```

View file

@ -0,0 +1,69 @@
# Namespace Resolvers
The methods on the [XPathEvaluator](XPathEvaluator.md) type can optionally take a namespace resolver to resolve
namespace references in the XPath expression being evaluated.
There are three ways to specify a namespace resolver and you can use any one of them depending on which is
most suited to your particular situation.
## Namespace Resolver Type 1: Plain object
A plain object with namespace prefixes as the keys and namespace URIs as the values:
Example usage:
```js
var evaluator = xpath.parse('/bk:book/hp:characters');
var characters = evaluator.select({
node: myBookNode,
namespaces: {
'bk': 'http://sample.org/books/',
'hp': 'http://sample.org/harrypotter/'
}
});
```
## Namespace Resolver Type 2: Function
A function that takes a namespace prefix as a parameter and returns the corresponding namespace URI.
Example usage:
```js
var evaluator = xpath.parse('/bk:book/hp:characters');
var characters = evaluator.select({
node: myBookNode,
namespaces: function (prefix) {
if (prefix === 'bk') {
return 'http://sample.org/books/';
}
if (prefix === 'hp') {
return 'http://sample.org/books/';
}
}
});
```
## Namespace Resolver Type 3: Object with `getNamespace` method
An object with a method named `getNamespace` that works in the same way as the function-based namespace resolver
described above.
Example usage:
```js
var evaluator = xpath.parse('/bk:book/hp:characters');
var characters = evaluator.select({
node: myBookNode,
namespaces: {
getNamespace: function (prefix) {
if (prefix === 'bk') {
return 'http://sample.org/books/';
}
if (prefix === 'hp') {
return 'http://sample.org/books/';
}
}
}
});
```

View file

@ -0,0 +1,21 @@
# Using Parsed Expressions
The `xpath.parse()` method allows pre-parsing an XPath expression and creating an XPath executor to evaluate the XPath as many times as needed.
This can provide a performance benefit if you plan to evaluate the same XPath multiple times, because the expression only needs to be parsed once.
This also provides access to additional features such as the use of variables and custom XPath functions, which are not available using the evaluation methods on the `xpath` object.
#### xpath.parse(expression)
Parses the specified XPath expression and returns an `XPathEvaluator`. See the [documentation page](XPathEvaluator.md) for API details.
`expression` should be a string.
Example usage:
```js
var evaluator = xpath.parse('/book/characters');
```

View file

@ -0,0 +1,89 @@
# Variable Resolvers
The methods on the [XPathEvaluator](#) type can optionally take a variable resolver to resolve
variable references in the XPath expression being evaluated.
There are three ways to specify a variable resolver and you can use any one of them depending on which is
most suited to your particular situation.
Note that if your variables are in a namespace (e.g. `$myVars:var`), you must use the second or third
type as the plain object implementation does not support namespaces.
## Variable values
You can use any of five types of values to specify the values of variables:
- string
- number
- boolean
- single node (will be treated as a node set)
- array of nodes or array-like collection of nodes (will be treated as a node set)
## Variable Resolver Type 1: Plain object
A plain object with variable names as the keys and variable values as the values.
Example usage:
````
var evaluator = xpath.parse('concat($character1, ", ", $character2, ", and ", $character3)');
var mainCharacters = evaluator.evaluateString({
variables: {
character1: 'Harry',
character2: 'Ron',
character3: 'Hermione'
}
});
````
## Variable Resolver Type 2: Function
A function that takes a variable name as its first parameter and an optional namespace URI as its second parameter
and returns a value based on the name and namespace.
Example usage:
````
var evaluator = xpath.parse('concat($hp:character1, ", ", $hp:character2, ", and ", $hp:character3)');
var mainCharacters = evaluator.evaluateString({
variables: function (name, namespace) {
if (namespace === 'http://sample.org/harrypotter/') {
switch (name) {
case 'character1': return 'Harry';
case 'character2': return 'Ron';
case 'character3': return 'Hermione';
}
}
},
namespaces: {
hp: 'http://sample.org/harrypotter/'
}
});
````
## Function Resolver Type 3: Object with `getFunction` method
An object with a method named `getVariable` that works in the same way as the function-based variable resolver
described above.
Example usage:
````
var evaluator = xpath.parse('concat($hp:character1, ", ", $hp:character2, ", and ", $hp:character3)');
var mainCharacters = evaluator.evaluateString({
variables: {
getVariable: function (name, namespace) {
if (namespace === 'http://sample.org/harrypotter/') {
switch (name) {
case 'character1': return 'Harry';
case 'character2': return 'Ron';
case 'character3': return 'Hermione';
}
}
}
},
namespaces: {
hp: 'http://sample.org/harrypotter/'
}
});
````

View file

@ -0,0 +1,39 @@
# xpath methods
This page details the methods exposed on the `xpath` object.
### `xpath.parse(expression)`
Creates a parsed expression. See the [documentation page](parsed%20expressions.md) for details.
### `xpath.select(expression[, node[, single]])`
Evaluates an XPath expression and returns the result. The return value is determined based on the result type of the expression (which can always be predicted ahead of time based on the expression's syntax):
- A boolean value if the expression evaluates to a boolean value.
- A number if the expression evaluates to a numeric value.
- A string if the expression evaluates to a string.
- If the expression evaluates to a nodeset:
- An array of 0 or more nodes if `single` is unspecified or falsy
- A single node (the first node in document order) or `undefined` if `single` is truthy
`node` is optional and if specified, is used as the context node for evaluating the expression. (It is necessary if the expression makes use of the current contex.)
`single` is optional and is ignored if the expression evaluates to anything other than a nodeset.
### `xpath.select1(expression[, node])`
Alias for [`xpath.select(expression, node, true)`](#xpathselectexpression-node-single). Selects a single node or value.
### `xpath.useNamespaces(mappings)`
Produces a function with the same signature as [`xpath.select()`](#xpathselectexpression-node-single) that evaluates the provided xpath expression using the XML namespace definitions provided in `mapppings`.
`mappings` should be an object with namespace prefixes as its property names and namespace URIs as its property values.
Example usage:
```js
var expr = xpath.useNamespaces({ hp: 'http://www.example.com/harryPotter', bk: 'http://www.example.com/books' });
var result = expr('/bk:books/bk:book[@name = "Harry Potter and the Half-Blood Prince"]/hp:characters', myBooks);
```

38
node_modules/mergexml/node_modules/xpath/package.json generated vendored Normal file
View file

@ -0,0 +1,38 @@
{
"name": "xpath",
"version": "0.0.27",
"description": "DOM 3 XPath implemention and helper for node.js.",
"engines": {
"node": ">=0.6.0"
},
"author": {
"name": "Cameron McCormack"
},
"contributors": [
{
"name": "goto100"
},
{
"name": "James Rishe"
}
],
"dependencies": {},
"devDependencies": {
"nodeunit": ">=0.6.4",
"xmldom": "^0.1.19"
},
"typings": "./xpath.d.ts",
"scripts": {
"test": "./node_modules/.bin/nodeunit test.js"
},
"repository": {
"type": "git",
"url": "https://github.com/goto100/xpath.git"
},
"main": "./xpath.js",
"keywords": [
"xpath",
"xml"
],
"license": "MIT"
}

1092
node_modules/mergexml/node_modules/xpath/test.js generated vendored Normal file

File diff suppressed because it is too large Load diff

9
node_modules/mergexml/node_modules/xpath/xpath.d.ts generated vendored Normal file
View file

@ -0,0 +1,9 @@
type SelectedValue = Node | Attr | string | number | boolean;
interface XPathSelect {
(expression: string, node?: Node): Array<SelectedValue>;
(expression: string, node: Node, single: true): SelectedValue;
}
export var select: XPathSelect;
export function select1(expression: string, node?: Node): SelectedValue;
export function evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver, type: number, result: XPathResult): XPathResult;
export function useNamespaces(namespaceMap: { [name: string]: string }): XPathSelect;

4764
node_modules/mergexml/node_modules/xpath/xpath.js generated vendored Normal file

File diff suppressed because it is too large Load diff

40
node_modules/mergexml/package.json generated vendored Normal file
View file

@ -0,0 +1,40 @@
{
"name": "mergexml",
"version": "1.2.4",
"description": "Merge multiple XML sources",
"main": "mergexml.js",
"repository": {
"type": "git",
"url": "https://github.com/hareko/js-merge-xml"
},
"scripts": {
"test": "karma start test/all.conf.js"
},
"keywords": [
"xml",
"merge"
],
"author": "Vallo Reima",
"license": "ISC",
"bugs": {
"url": "https://github.com/hareko/js-merge-xml/issues"
},
"dependencies": {
"formidable": "^3.5.1",
"@xmldom/xmldom": "^0.7.0",
"xpath": "0.0.27"
},
"devDependencies": {
"chai": "3.0.x",
"jasmine-core": "2.0.x",
"karma": "1.3.x",
"karma-chai": "0.1.x",
"karma-chrome-launcher": "2.0.x",
"karma-firefox-launcher": "1.0.x",
"karma-jasmine": "0.3.x",
"karma-mocha": "1.2.x",
"karma-opera-launcher": "1.0.x",
"karma-safari-launcher": "1.0.x",
"mocha": "3.1.x"
}
}

64
node_modules/mergexml/test/all.conf.js generated vendored Normal file
View file

@ -0,0 +1,64 @@
// Karma configuration
// Generated on Thu Jul 02 2015 10:24:08 GMT-0600 (MDT)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '..',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha', 'chai'],
// list of files / patterns to load in the browser
files: [
'mergexml.js',
'test/spec/*.spec.js'
],
// list of files to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Firefox', 'Chrome', 'ChromeCanary', 'Safari', 'Opera'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
};

179
node_modules/mergexml/test/spec/merge.spec.js generated vendored Normal file
View file

@ -0,0 +1,179 @@
/* jshint node:true */
/* global MergeXML, describe, it, before, after, beforeEach, afterEach, expect */
'use strict';
describe('Instantiating object ', function() {
var merger;
it('works', function() {
merger = new MergeXML();
expect(merger).to.be.an('object');
});
});
describe('Adding source', function() {
var merger, a, b;
it('strings works', function() {
merger = new MergeXML();
a = '<a/>';
b = '<b/>';
expect(merger.AddSource(a)).to.not.equal(false);
expect(merger.AddSource(b)).to.not.equal(false);
});
});
describe('Merging XML sources', function() {
var merger, a, b;
describe('with option join = undefined', function() {
// TODO
});
describe('with option join = false', function() {
it('succeeds if sources have a common root name', function() {
merger = new MergeXML({
join: false
});
a = '<r><a/></r>';
b = '<r><b/></r>';
merger.AddSource(a);
merger.AddSource(b);
expect(merger.Get(1).trim()).to.equal('<r><a/><b/></r>');
});
it('fails to merge second source if sources do not have a common root name', function() {
merger = new MergeXML({
join: false
});
a = '<a/>';
b = '<b/>';
merger.AddSource(a);
merger.AddSource(b);
expect(merger.Get(1).trim()).to.equal('<a/>');
});
});
describe('with option updn = true or undefined', function() {
var merger, a, b;
it('merges sources by nodeName', function() {
merger = new MergeXML({
updn: true
});
a = '<a>' +
'<c>s1</c>' +
'<c>s3</c>' +
'</a>';
b = '<a>' +
'<c>s1</c>' +
'<b>s2</b>' +
'<c>s4</c>' +
'</a>';
merger.AddSource(a);
merger.AddSource(b);
expect(merger.Get(1).trim()).to.equal('<a><c>s1</c><c>s4</c><b>s2</b></a>');
merger = new MergeXML();
merger.AddSource(a);
merger.AddSource(b);
expect(merger.Get(1).trim()).to.equal('<a><c>s1</c><c>s4</c><b>s2</b></a>');
});
});
describe('with option updn = false', function() {
var merger, a, b;
it('merges sources by node position, discarding nodeName', function() {
merger = new MergeXML({
updn: false
});
a = '<a>' +
'<c>s1</c>' +
'<c>s3</c>' +
'</a>';
b = '<a>' +
'<c>s1</c>' +
'<b>s2</b>' +
'<c>s4</c>' +
'</a>';
merger.AddSource(a);
merger.AddSource(b);
expect(merger.Get(1).trim()).to.equal('<a><c>s1</c><c>s2</c><c>s4</c></a>');
});
});
describe('with namespaced attributes', function() {
var merger;
var ns = 'https://github.com/enketo/merge-xml';
it('correctly adds namespaced attributes from second source', function() {
merger = new MergeXML({
join: false
});
a = '<a>' +
'<c>s1</c>' +
'</a>';
b = '<a xmlns:enk="' + ns + '">' +
'<c enk:custom="something">s2</c>' +
'</a>';
merger.AddSource(a);
merger.AddSource(b);
expect(merger.error.code).to.equal('');
expect(merger.error.text).to.equal('');
expect(merger.Get(1).trim()).to.equal('<a xmlns:enk="' + ns + '"><c enk:custom="something">s2</c></a>');
// in IE11 and below, merger.Get(0) returns an ActiveXObject we use the internal "Query" function
expect(merger.Query('//c').attributes[0].localName).to.equal('custom'); // fails in IE because
expect(merger.Query('//c').attributes[0].namespaceURI).to.equal(ns);
})
})
describe('with sources that have and do not have a UTF encoding declaration', function() {
var merger;
var a = '<?xml version="1.0"?>' +
'<a><c>s1</c></a>';
var b = '<?xml version="1.0" encoding="UTF-8"?>' +
'<a><c>s2</c></a>';
it('undeclared and UTF-8', function() {
merger = new MergeXML({
join: false
});
merger.AddSource(a);
merger.AddSource(b);
expect(merger.error.code).to.equal('');
expect(merger.error.text).to.equal('');
expect(merger.Get(1)).to.contain('<a><c>s2</c></a>');
});
it('UTF8 and undeclared', function() {
merger = new MergeXML({
join: false
});
merger.AddSource(b);
merger.AddSource(a);
expect(merger.error.code).to.equal('');
expect(merger.error.text).to.equal('');
expect(merger.Get(1)).to.contain('<a><c>s1</c></a>');
});
});
});

33
node_modules/mergexml/test/test1.xml generated vendored Normal file
View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
sample configuration
@package System
@author Vallo Reima
@copyright (C)2012
-->
<cfg xmlns="http://www.vallo.me/">
<!-- Application properties -->
<apn>
<name>vRegistrator</name>
<vers>1.1</vers>
</apn>
<!-- Modules -->
<mod>
<ath flag="O">auth</ath>
<sni flag="C">login</sni>
<snu>signup</snu>
</mod>
<!-- Loader modules -->
<ldm>
<sni>
<P opt="wrap">login</P>
<J opt="load" stay="all">login</J>
<S>login</S>
</sni>
<snu>
<P opt="wrap">signup</P>
<S>signup</S>
<J opt="load">signup</J>
</snu>
</ldm>
</cfg>

30
node_modules/mergexml/test/test2.xml generated vendored Normal file
View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
sample configuration
@package Application
@author Vallo Reima
@copyright (C)2013
-->
<cfg xmlns="http://www.vallo.me/" xmlns:rgn="http://www.vregistry.com/">
<!-- Application properties -->
<rgn:apn>
<name>vRegistry</name>
<vers>1.0</vers>
</rgn:apn>
<!-- Modules -->
<mod>
<sni flag="C">signin</sni>
</mod>
<!-- Loader modified-->
<ldm>
<sni>
<P opt="wrapper">signin</P>
<S>login</S>
<S>signin</S>
<J opt="loader">login</J>
</sni>
</ldm>
</cfg>
<!--
merged with system
-->