blob: 7f372fb3c960cd5f7e4d83aabf34638d033d7c76 [file] [log] [blame]
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
var INDENT = ' ';
/**
* a utility class to produce well-formed, indented XML
* @param {ContentWriter} contentWriter the content writer that this utility wraps
* @constructor
*/
function XMLWriter(contentWriter) {
this.cw = contentWriter;
this.stack = [];
}
function attrString(attrs) {
if (!attrs) {
return '';
}
var ret = [];
Object.keys(attrs).forEach(function (k) {
var v = attrs[k];
ret.push(k + '="' + v + '"');
});
return ret.length === 0 ? '' : ' ' + ret.join(' ');
}
XMLWriter.prototype.indent = function (str) {
return this.stack.map(function () { return INDENT; }).join('') + str;
};
/**
* writes the opening XML tag with the supplied attributes
* @param {String} name tag name
* @param {Object} [attrs=null] attrs attributes for the tag
*/
XMLWriter.prototype.openTag = function (name, attrs) {
var str = this.indent('<' + name + attrString(attrs) + '>');
this.cw.println(str);
this.stack.push(name);
};
/**
* closes an open XML tag.
* @param {String} name - tag name to close. This must match the writer's
* notion of the tag that is currently open.
*/
XMLWriter.prototype.closeTag = function (name) {
if (this.stack.length === 0) {
throw new Error('Attempt to close tag ' + name + ' when not opened');
}
var stashed = this.stack.pop(),
str = '</' + name + '>';
if (stashed !== name) {
throw new Error('Attempt to close tag ' + name + ' when ' + stashed + ' was the one open');
}
this.cw.println(this.indent(str));
};
/**
* writes a tag and its value opening and closing it at the same time
* @param {String} name tag name
* @param {Object} [attrs=null] attrs tag attributes
* @param {String} [content=null] content optional tag content
*/
XMLWriter.prototype.inlineTag = function (name, attrs, content) {
var str = '<' + name + attrString(attrs);
if (content) {
str += '>' + content + '</' + name + '>';
} else {
str += '/>';
}
str = this.indent(str);
this.cw.println(str);
};
/**
* closes all open tags and ends the document
*/
XMLWriter.prototype.closeAll = function () {
var that = this;
this.stack.slice().reverse().forEach(function (name) {
that.closeTag(name);
});
};
module.exports = XMLWriter;