Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Facilitates tag and attribute name processing

resolves #115
resolves #114
  • Loading branch information...
commit a4b920512b3b4804601d2c548c7310081b14ca76 1 parent 23b4776
@creynders creynders authored
View
36 lib/xml2js.js
@@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.3
(function() {
- var bom, builder, events, isEmpty, sax,
+ var bom, builder, events, isEmpty, normalizeTag, processName, sax,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
@@ -17,6 +17,19 @@
return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0;
};
+ normalizeTag = function(name) {
+ return name.toLowerCase();
+ };
+
+ processName = function(processors, processedName) {
+ var process, _i, _len;
+ for (_i = 0, _len = processors.length; _i < _len; _i++) {
+ process = processors[_i];
+ processedName = process(processedName);
+ }
+ return processedName;
+ };
+
exports.defaults = {
"0.1": {
explicitCharkey: false,
@@ -35,7 +48,9 @@
childkey: '@@',
charsAsChildren: false,
async: false,
- strict: true
+ strict: true,
+ attrNameProcessor: null,
+ tagNameProcessor: null
},
"0.2": {
explicitCharkey: false,
@@ -55,6 +70,8 @@
charsAsChildren: false,
async: false,
strict: true,
+ attrNameProcessor: null,
+ tagNameProcessor: null,
rootName: 'root',
xmldec: {
'version': '1.0',
@@ -178,6 +195,12 @@
if (this.options.xmlns) {
this.options.xmlnskey = this.options.attrkey + "ns";
}
+ if (this.options.normalizeTags) {
+ if (!this.options.tagNameProcessor) {
+ this.options.tagNameProcessor = [];
+ }
+ this.options.tagNameProcessor.push(normalizeTag);
+ }
this.reset();
}
@@ -218,7 +241,7 @@
attrkey = this.options.attrkey;
charkey = this.options.charkey;
this.saxParser.onopentag = function(node) {
- var key, newValue, obj, _ref;
+ var key, newValue, obj, processedKey, _ref;
obj = {};
obj[charkey] = "";
if (!_this.options.ignoreAttrs) {
@@ -229,14 +252,15 @@
obj[attrkey] = {};
}
newValue = node.attributes[key];
+ processedKey = _this.options.attrNameProcessor ? processName(_this.options.attrNameProcessor, key) : key;
if (_this.options.mergeAttrs) {
- _this.assignOrPush(obj, key, newValue);
+ _this.assignOrPush(obj, processedKey, newValue);
} else {
- obj[attrkey][key] = newValue;
+ obj[attrkey][processedKey] = newValue;
}
}
}
- obj["#name"] = _this.options.normalizeTags ? node.name.toLowerCase() : node.name;
+ obj["#name"] = _this.options.tagNameProcessor ? processName(_this.options.tagNameProcessor, node.name) : node.name;
if (_this.options.xmlns) {
obj[_this.options.xmlnskey] = {
uri: node.uri,
View
22 src/xml2js.coffee
@@ -7,6 +7,13 @@ bom = require './bom'
isEmpty = (thing) ->
return typeof thing is "object" && thing? && Object.keys(thing).length is 0
+normalizeTag = (name) ->
+ return name.toLowerCase()
+
+processName = (processors, processedName) ->
+ processedName = process(processedName) for process in processors
+ return processedName
+
exports.defaults =
"0.1":
explicitCharkey: false
@@ -36,6 +43,8 @@ exports.defaults =
# callbacks are async? not in 0.1 mode
async: false
strict: true
+ attrNameProcessor: null
+ tagNameProcessor: null
"0.2":
explicitCharkey: false
@@ -56,6 +65,8 @@ exports.defaults =
# not async in 0.2 mode either
async: false
strict: true
+ attrNameProcessor: null
+ tagNameProcessor: null
# xml building options
rootName: 'root'
xmldec: {'version': '1.0', 'encoding': 'UTF-8', 'standalone': true}
@@ -139,6 +150,10 @@ class exports.Parser extends events.EventEmitter
# define the key used for namespaces
if @options.xmlns
@options.xmlnskey = @options.attrkey + "ns"
+ if @options.normalizeTags
+ if ! @options.tagNameProcessor
+ @options.tagNameProcessor = []
+ @options.tagNameProcessor.push normalizeTag
@reset()
@@ -190,13 +205,14 @@ class exports.Parser extends events.EventEmitter
if attrkey not of obj and not @options.mergeAttrs
obj[attrkey] = {}
newValue = node.attributes[key]
+ processedKey = if @options.attrNameProcessor then processName(@options.attrNameProcessor, key) else key
if @options.mergeAttrs
- @assignOrPush obj, key, newValue
+ @assignOrPush obj, processedKey, newValue
else
- obj[attrkey][key] = newValue
+ obj[attrkey][processedKey] = newValue
# need a place to store the node name
- obj["#name"] = if @options.normalizeTags then node.name.toLowerCase() else node.name
+ obj["#name"] = if @options.tagNameProcessor then processName(@options.tagNameProcessor, node.name) else node.name
if (@options.xmlns)
obj[@options.xmlnskey] = {uri: node.uri, local: node.local}
stack.push obj
View
2  test/fixtures/sample.xml
@@ -50,4 +50,6 @@
<pfx:top xmlns:pfx="http://foo.com" pfx:attr="baz">
<middle xmlns="http://bar.com"/>
</pfx:top>
+ <attrNameProcessTest camelCaseAttr="camelCaseAttrValue" lowercaseattr="lowercaseattr" />
+ <tagNameProcessTest/>
</sample>
View
26 test/parser.test.coffee
@@ -23,6 +23,12 @@ skeleton = (options, checks) ->
else
x2js.parseString xmlString
+nameToUpperCase = (name) ->
+ return name.toUpperCase()
+
+nameCutoff = (name) ->
+ return name.substr(0, 4)
+
###
The `validator` function validates the value at the XPath. It also transforms the value
if necessary to conform to the schema or other validation information being used. If there
@@ -340,3 +346,23 @@ module.exports =
equ err, null
assert.deepEqual resWithNew, resWithoutNew
test.done()
+
+ 'test single attrNameProcessor': skeleton(attrNameProcessor: [nameToUpperCase], (r)->
+ console.log 'Result object: ' + util.inspect r, false, 10
+ equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('CAMELCASEATTR'), true
+ equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('LOWERCASEATTR'), true)
+
+ 'test multiple attrNameProcessor': skeleton(attrNameProcessor: [nameToUpperCase, nameCutoff], (r)->
+ console.log 'Result object: ' + util.inspect r, false, 10
+ equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('CAME'), true
+ equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('LOWE'), true)
+
+ 'test single tagNameProcessor': skeleton(tagNameProcessor: [nameToUpperCase], (r)->
+ console.log 'Result object: ' + util.inspect r, false, 10
+ equ r.hasOwnProperty('SAMPLE'), true
+ equ r.SAMPLE.hasOwnProperty('TAGNAMEPROCESSTEST'), true)
+
+ 'test multiple tagNameProcessor': skeleton(tagNameProcessor: [nameToUpperCase, nameCutoff], (r)->
+ console.log 'Result object: ' + util.inspect r, false, 10
+ equ r.hasOwnProperty('SAMP'), true
+ equ r.SAMP.hasOwnProperty('TAGN'), true)
Please sign in to comment.
Something went wrong with that request. Please try again.