xml-parser-xo
Advanced tools
Comparing version 2.2.1 to 3.0.0
354
index.js
@@ -1,213 +0,239 @@ | ||
/** | ||
* Module dependencies. | ||
* @typedef {Object} ParsingOptions | ||
* @property {function(node)} filter Returns false to exclude a node. Default is true. | ||
*/ | ||
var debug = require('debug')('xml-parser'); | ||
/** | ||
* Expose `parse`. | ||
*/ | ||
module.exports = parse; | ||
/** | ||
* Parse the given string of `xml`. | ||
* Parse the given XML string into an object. | ||
* | ||
* @param {String} xml | ||
* @param {Object} [options] | ||
* @config {Boolean} [trim=true] | ||
* @config {Boolean} [stripComments=true] | ||
* @param {ParsingOptions} [options] | ||
* @return {Object} | ||
* @api public | ||
*/ | ||
function parse(xml, options = {}) { | ||
function parse(xml, options) { | ||
options.filter = options.filter || (() => true); | ||
// trim content | ||
if (!options || options.trim) { | ||
xml = xml.trim(); | ||
} | ||
function nextChild() { | ||
return tag() || content() || comment() || cdata(); | ||
} | ||
// strip comments | ||
if (!options || options.stripComments) { | ||
xml = xml.replace(/<!--[\s\S]*?-->/g, ''); | ||
} | ||
function nextRootChild() { | ||
match(/\s*/); | ||
return tag(true) || comment() || doctype() || processingInstruction(false); | ||
} | ||
return document(); | ||
function document() { | ||
const decl = declaration(); | ||
const children = []; | ||
let documentRootNode; | ||
let child = nextRootChild(); | ||
/** | ||
* XML document. | ||
*/ | ||
while (child) { | ||
if (child.node.type === 'Element') { | ||
if (documentRootNode) { | ||
throw new Error('Found multiple root nodes'); | ||
} | ||
documentRootNode = child.node; | ||
} | ||
function document() { | ||
if (!child.excluded) { | ||
children.push(child.node); | ||
} | ||
var decl = declaration(); | ||
var child; | ||
var children = []; | ||
var documentRootNode; | ||
child = nextRootChild(); | ||
} | ||
while (child = nextRootChild()) { | ||
if (child.name !== '#comment') { | ||
if (documentRootNode) { | ||
throw new Error('Found multiple root nodes'); | ||
if (!documentRootNode) { | ||
throw new Error('Failed to parse XML'); | ||
} | ||
documentRootNode = child; | ||
} | ||
children.push(child); | ||
return { | ||
declaration: decl ? decl.node : null, | ||
root: documentRootNode, | ||
children | ||
}; | ||
} | ||
return { | ||
declaration: decl, | ||
root: documentRootNode, | ||
children: children | ||
}; | ||
} | ||
function declaration() { | ||
return processingInstruction(true); | ||
} | ||
/** | ||
* Declaration. | ||
*/ | ||
function processingInstruction(matchDeclaration) { | ||
const m = matchDeclaration ? match(/^<\?(xml)\s*/) : match(/^<\?([\w-:.]+)\s*/); | ||
if (!m) return; | ||
function declaration() { | ||
var m = match(/^<\?xml\s*/); | ||
if (!m) return; | ||
// tag | ||
const node = { | ||
name: m[1], | ||
type: 'ProcessingInstruction', | ||
attributes: {} | ||
}; | ||
// tag | ||
var node = { | ||
attributes: {} | ||
}; | ||
// attributes | ||
while (!(eos() || is('?>'))) { | ||
const attr = attribute(); | ||
if (!attr) return node; | ||
node.attributes[attr.name] = attr.value; | ||
} | ||
// attributes | ||
while (!(eos() || is('?>'))) { | ||
var attr = attribute(); | ||
if (!attr) return node; | ||
node.attributes[attr.name] = attr.value; | ||
match(/\?>/); | ||
return { | ||
excluded: matchDeclaration ? false : options.filter(node) === false, | ||
node | ||
}; | ||
} | ||
match(/\?>\s*/); | ||
function tag(matchRoot) { | ||
const m = match(/^<([\w-:.]+)\s*/); | ||
if (!m) return; | ||
return node; | ||
} | ||
// name | ||
const node = { | ||
type: 'Element', | ||
name: m[1], | ||
attributes: {}, | ||
children: [] | ||
}; | ||
/** | ||
* Tag. | ||
*/ | ||
// attributes | ||
while (!(eos() || is('>') || is('?>') || is('/>'))) { | ||
const attr = attribute(); | ||
if (!attr) return node; | ||
node.attributes[attr.name] = attr.value; | ||
} | ||
function tag() { | ||
debug('tag %j', xml); | ||
var m = match(/^<([\w-:.]+)\s*/); | ||
if (!m) return; | ||
const excluded = matchRoot ? false : options.filter(node) === false; | ||
// name | ||
var node = { | ||
name: m[1], | ||
attributes: {}, | ||
children: [] | ||
}; | ||
// self closing tag | ||
if (match(/^\s*\/>/)) { | ||
node.children = null; | ||
return { | ||
excluded, | ||
node | ||
}; | ||
} | ||
// attributes | ||
while (!(eos() || is('>') || is('?>') || is('/>'))) { | ||
var attr = attribute(); | ||
if (!attr) return node; | ||
node.attributes[attr.name] = attr.value; | ||
} | ||
match(/\??>/); | ||
// self closing tag | ||
if (match(/^\s*\/>/)) { | ||
node.children = null; | ||
return node; | ||
} | ||
if (!excluded) { | ||
// children | ||
let child = nextChild(); | ||
while (child) { | ||
if (!child.excluded) { | ||
node.children.push(child.node); | ||
} | ||
child = nextChild(); | ||
} | ||
} | ||
match(/\??>/); | ||
// closing | ||
match(/^<\/[\w-:.]+>/); | ||
// children | ||
var child; | ||
while (child = nextChild()) { | ||
node.children.push(child); | ||
return { | ||
excluded, | ||
node | ||
}; | ||
} | ||
// closing | ||
match(/^<\/[\w-:.]+>/); | ||
function doctype() { | ||
const m = match(/^<!DOCTYPE\s+[^>]*>/); | ||
if (m) { | ||
const node = { | ||
type: 'DocumentType', | ||
content: m[0] | ||
}; | ||
return { | ||
excluded: options.filter(node) === false, | ||
node | ||
}; | ||
} | ||
} | ||
return node; | ||
} | ||
function cdata() { | ||
const m = match(/^<!\[CDATA\[[^\]\]>]*]]>/); | ||
if (m) { | ||
const node = { | ||
type: 'CDATA', | ||
content: m[0] | ||
}; | ||
return { | ||
excluded: options.filter(node) === false, | ||
node | ||
}; | ||
} | ||
} | ||
function nextChild() { | ||
return tag() || content() || comment(); | ||
} | ||
function comment() { | ||
const m = match(/^<!--[\s\S]*?-->/); | ||
if (m) { | ||
const node = { | ||
type: 'Comment', | ||
content: m[0] | ||
}; | ||
return { | ||
excluded: options.filter(node) === false, | ||
node | ||
}; | ||
} | ||
} | ||
function nextRootChild() { | ||
return tag() || comment(); | ||
} | ||
function content() { | ||
const m = match(/^([^<]+)/); | ||
if (m) { | ||
const node = { | ||
type: 'Text', | ||
content: m[1] | ||
}; | ||
return { | ||
excluded: options.filter(node) === false, | ||
node | ||
}; | ||
} | ||
} | ||
function comment() { | ||
var m = match(/^<!--[\s\S]*?-->/); | ||
if (m) { | ||
return { | ||
name: '#comment', | ||
content: m[0] | ||
}; | ||
function attribute() { | ||
const m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/); | ||
if (!m) return; | ||
return {name: m[1], value: strip(m[2])} | ||
} | ||
} | ||
/** | ||
* Text content. | ||
*/ | ||
/** | ||
* Strip quotes from `val`. | ||
*/ | ||
function strip(val) { | ||
return val.replace(/^['"]|['"]$/g, ''); | ||
} | ||
function content() { | ||
debug('content %j', xml); | ||
var m = match(/^([^<]+)/); | ||
if (m) { | ||
return { | ||
name: '#text', | ||
content: m[1] | ||
}; | ||
/** | ||
* Match `re` and advance the string. | ||
*/ | ||
function match(re) { | ||
const m = xml.match(re); | ||
if (!m) return; | ||
xml = xml.slice(m[0].length); | ||
return m; | ||
} | ||
} | ||
/** | ||
* Attribute. | ||
*/ | ||
/** | ||
* End-of-source. | ||
*/ | ||
function eos() { | ||
return 0 === xml.length; | ||
} | ||
function attribute() { | ||
debug('attribute %j', xml); | ||
var m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/); | ||
if (!m) return; | ||
return { name: m[1], value: strip(m[2]) } | ||
} | ||
/** | ||
* Check for `prefix`. | ||
*/ | ||
function is(prefix) { | ||
return 0 === xml.indexOf(prefix); | ||
} | ||
/** | ||
* Strip quotes from `val`. | ||
*/ | ||
xml = xml.trim(); | ||
function strip(val) { | ||
return val.replace(/^['"]|['"]$/g, ''); | ||
} | ||
return document(); | ||
} | ||
/** | ||
* Match `re` and advance the string. | ||
*/ | ||
function match(re) { | ||
var m = xml.match(re); | ||
if (!m) return; | ||
xml = xml.slice(m[0].length); | ||
return m; | ||
} | ||
/** | ||
* End-of-source. | ||
*/ | ||
function eos() { | ||
return 0 == xml.length; | ||
} | ||
/** | ||
* Check for `prefix`. | ||
*/ | ||
function is(prefix) { | ||
return 0 == xml.indexOf(prefix); | ||
} | ||
} | ||
module.exports = parse; |
{ | ||
"name": "xml-parser-xo", | ||
"version": "2.2.1", | ||
"repository": "chrisbottin/xml-parser", | ||
"description": "XML Parser with eXtra Options", | ||
"version": "3.0.0", | ||
"repository": "github:chrisbottin/xml-parser", | ||
"bugs": { | ||
"url": "https://github.com/chrisbottin/xml-parser/issues" | ||
}, | ||
"homepage": "https://github.com/chrisbottin/xml-parser#readme", | ||
"description": "Parse a XML string into a proprietary syntax tree", | ||
"author": "Chris Bottin <chrisbottin@gmail.com>", | ||
"license": "MIT", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node_modules/.bin/mocha", | ||
"prepublishOnly": "npm test" | ||
"test": "mocha", | ||
"prepublishOnly": "eslint . && npm test" | ||
}, | ||
@@ -15,26 +22,15 @@ "engines": { | ||
"xml", | ||
"parse", | ||
"parser", | ||
"convert" | ||
"convert", | ||
"converter", | ||
"syntax", | ||
"tree" | ||
], | ||
"dependencies": { | ||
"debug": "^4.1.1" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"chai": "^4.2.0", | ||
"eslint": "^6.8.0", | ||
"mocha": "^6.2.1" | ||
}, | ||
"browser": { | ||
"debug": "./browserify/debug-mock.js" | ||
}, | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/chrisbottin/xml-parser/issues" | ||
}, | ||
"homepage": "https://github.com/chrisbottin/xml-parser#readme", | ||
"main": "index.js", | ||
"directories": { | ||
"example": "examples", | ||
"test": "test" | ||
}, | ||
"author": "" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
9714
0
219
0
3
69
1
- Removeddebug@^4.1.1
- Removeddebug@4.3.7(transitive)
- Removedms@2.1.3(transitive)