Skip to content

Loading…

Added stripPrefix option #115

Closed
wants to merge 1 commit into from

2 participants

@creynders

Based on #97 (with thanks to @metatribal !!) I added the stripPrefix option which strips out namespace prefixes from both node and attribute names to the xml2js coffee file. I also updated the tests, readme and lib files.

Hope this is good enough, since I really need this :grin:

@Leonidas-from-XIV

I am not too sure to add such specific functionality, see #114. Maybe you two could come up with a new option, one that takes a function which takes a tag name and returns a new tag name and will get applied to the tags? That is a more general option and could solve both #114 and #115.

(Also, please use the current version of CoffeeScript, because your patch contains some version number noise to unrelated files)

@creynders

A tag name processor sounds like a good idea. I'll try and issue a PR today. (I'll make sure I use the current version of Coffee)

@creynders creynders added a commit to creynders/node-xml2js that referenced this pull request
@creynders creynders Facilitates tag and attribute name processing
resolves #115
resolves #114
a4b9205
@Leonidas-from-XIV

Closed in favor of #116.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 12, 2013
  1. @creynders

    Added stripPrefix option

    creynders committed
    resolves #97
This page is out of date. Refresh to see the latest.
Showing with 42 additions and 11 deletions.
  1. +2 −0 README.md
  2. +1 −1 lib/bom.js
  3. +24 −7 lib/xml2js.js
  4. +9 −3 src/xml2js.coffee
  5. +6 −0 test/parser.test.coffee
View
2 README.md
@@ -220,6 +220,8 @@ value})``. Possible options are:
* `strict` (default `true`): Set sax-js to strict or non-strict parsing mode.
Defaults to `true` which is *highly* recommended, since parsing HTML which
is not well-formed XML might yield just about anything. Added in 0.2.7.
+ * `stripPrefix` (default `false`): Strip namespace prefixes from element and
+ attribute names. Added in 0.4.1.
Options for the `Builder` class
-------------------------------
View
2 lib/bom.js
@@ -1,4 +1,4 @@
-// Generated by CoffeeScript 1.6.3
+// Generated by CoffeeScript 1.6.2
(function() {
var xml2js;
View
31 lib/xml2js.js
@@ -1,4 +1,4 @@
-// Generated by CoffeeScript 1.6.3
+// Generated by CoffeeScript 1.6.2
(function() {
var bom, builder, events, isEmpty, sax,
__hasProp = {}.hasOwnProperty,
@@ -35,7 +35,8 @@
childkey: '@@',
charsAsChildren: false,
async: false,
- strict: true
+ strict: true,
+ stripPrefix: false
},
"0.2": {
explicitCharkey: false,
@@ -55,6 +56,7 @@
charsAsChildren: false,
async: false,
strict: true,
+ stripPrefix: false,
rootName: 'root',
xmldec: {
'version': '1.0',
@@ -84,6 +86,7 @@
exports.Builder = (function() {
function Builder(opts) {
var key, value, _ref;
+
this.options = {};
_ref = exports.defaults["0.2"];
for (key in _ref) {
@@ -100,6 +103,7 @@
Builder.prototype.buildObject = function(rootObj) {
var attrkey, charkey, render, rootElement, rootName;
+
attrkey = this.options.attrkey;
charkey = this.options.charkey;
if ((Object.keys(rootObj).length === 1) && (this.options.rootName === exports.defaults['0.2'].rootName)) {
@@ -110,6 +114,7 @@
}
render = function(element, obj) {
var attr, child, entry, index, key, value, _ref, _ref1;
+
if (typeof obj !== 'object') {
element.txt(obj);
} else {
@@ -160,6 +165,7 @@
this.reset = __bind(this.reset, this);
this.assignOrPush = __bind(this.assignOrPush, this);
var key, value, _ref;
+
if (!(this instanceof exports.Parser)) {
return new exports.Parser(opts);
}
@@ -197,8 +203,9 @@
};
Parser.prototype.reset = function() {
- var attrkey, charkey, err, ontext, stack,
+ var attrkey, charkey, err, ontext, prefixMatch, stack, stripPrefix,
_this = this;
+
this.removeAllListeners();
this.saxParser = sax.parser(this.options.strict, {
trim: false,
@@ -217,26 +224,31 @@
stack = [];
attrkey = this.options.attrkey;
charkey = this.options.charkey;
+ stripPrefix = this.options.stripPrefix;
+ prefixMatch = new RegExp(/(?!xmlns)^.*:/);
this.saxParser.onopentag = function(node) {
- var key, newValue, obj, _ref;
+ var key, newValue, nodeName, obj, objkey, _ref;
+
obj = {};
obj[charkey] = "";
if (!_this.options.ignoreAttrs) {
_ref = node.attributes;
for (key in _ref) {
if (!__hasProp.call(_ref, key)) continue;
+ objkey = _this.options.stripPrefix ? key.replace(prefixMatch, '') : key;
if (!(attrkey in obj) && !_this.options.mergeAttrs) {
obj[attrkey] = {};
}
newValue = node.attributes[key];
if (_this.options.mergeAttrs) {
- _this.assignOrPush(obj, key, newValue);
+ _this.assignOrPush(obj, objkey, newValue);
} else {
- obj[attrkey][key] = newValue;
+ obj[attrkey][objkey] = newValue;
}
}
}
- obj["#name"] = _this.options.normalizeTags ? node.name.toLowerCase() : node.name;
+ nodeName = _this.options.normalizeTags ? node.name.toLowerCase() : node.name;
+ obj["#name"] = _this.options.stripPrefix ? nodeName.replace(prefixMatch, '') : nodeName;
if (_this.options.xmlns) {
obj[_this.options.xmlnskey] = {
uri: node.uri,
@@ -247,6 +259,7 @@
};
this.saxParser.onclosetag = function() {
var cdata, emptyStr, node, nodeName, obj, old, s, xpath;
+
obj = stack.pop();
nodeName = obj["#name"];
delete obj["#name"];
@@ -273,6 +286,7 @@
if (_this.options.validator != null) {
xpath = "/" + ((function() {
var _i, _len, _results;
+
_results = [];
for (_i = 0, _len = stack.length; _i < _len; _i++) {
node = stack[_i];
@@ -316,6 +330,7 @@
};
ontext = function(text) {
var s;
+
s = stack[stack.length - 1];
if (s) {
s[charkey] += text;
@@ -325,6 +340,7 @@
this.saxParser.ontext = ontext;
return this.saxParser.oncdata = function(text) {
var s;
+
s = ontext(text);
if (s) {
return s.cdata = true;
@@ -368,6 +384,7 @@
exports.parseString = function(str, a, b) {
var cb, options, parser;
+
if (b != null) {
if (typeof b === 'function') {
cb = b;
View
12 src/xml2js.coffee
@@ -36,6 +36,7 @@ exports.defaults =
# callbacks are async? not in 0.1 mode
async: false
strict: true
+ stripPrefix: false
"0.2":
explicitCharkey: false
@@ -56,6 +57,7 @@ exports.defaults =
# not async in 0.2 mode either
async: false
strict: true
+ stripPrefix: false
# xml building options
rootName: 'root'
xmldec: {'version': '1.0', 'encoding': 'UTF-8', 'standalone': true}
@@ -181,22 +183,26 @@ class exports.Parser extends events.EventEmitter
# aliases, so we don't have to type so much
attrkey = @options.attrkey
charkey = @options.charkey
+ stripPrefix = @options.stripPrefix
+ prefixMatch = new RegExp /(?!xmlns)^.*:/
@saxParser.onopentag = (node) =>
obj = {}
obj[charkey] = ""
unless @options.ignoreAttrs
for own key of node.attributes
+ objkey = if @options.stripPrefix then key.replace(prefixMatch, '') else key
if attrkey not of obj and not @options.mergeAttrs
obj[attrkey] = {}
newValue = node.attributes[key]
if @options.mergeAttrs
- @assignOrPush obj, key, newValue
+ @assignOrPush obj, objkey, newValue
else
- obj[attrkey][key] = newValue
+ obj[attrkey][objkey] = newValue
# need a place to store the node name
- obj["#name"] = if @options.normalizeTags then node.name.toLowerCase() else node.name
+ nodeName = if @options.normalizeTags then node.name.toLowerCase() else node.name
+ obj["#name"] = if @options.stripPrefix then nodeName.replace(prefixMatch, '') else nodeName
if (@options.xmlns)
obj[@options.xmlnskey] = {uri: node.uri, local: node.local}
stack.push obj
View
6 test/parser.test.coffee
@@ -299,6 +299,12 @@ module.exports =
equ r.sample["pfx:top"][0].middle[0].$ns.local, 'middle'
equ r.sample["pfx:top"][0].middle[0].$ns.uri, 'http://bar.com')
+ 'test stripPrefix': skeleton(stripPrefix: true, (r) ->
+ console.log 'Result object: ' + util.inspect r, false, 10
+ equ r.sample["top"][0].$["attr"], 'baz'
+ equ r.sample["top"][0].$["xmlns:pfx"], 'http://foo.com'
+ )
+
'test callback should be called once': (test) ->
xml = '<?xml version="1.0" encoding="utf-8"?><test>test</test>'
i = 0
Something went wrong with that request. Please try again.