replace JSON-to-XML serializer

This commit is contained in:
Jeff Williams 2012-10-15 20:47:08 -07:00
parent da0a55e577
commit bdee90463f
6 changed files with 272 additions and 72 deletions

View File

@ -17,6 +17,7 @@
}
],
"dependencies": {
"js2xmlparser": "0.1.0",
"markdown": "0.4.0",
"taffydb": "git://github.com/hegemonic/taffydb.git",
"wrench": "1.3.9"

16
node_modules/js2xmlparser/LICENSE.md generated vendored Normal file
View File

@ -0,0 +1,16 @@
js2xmlparser is licensed under the MIT license:
> Copyright (C) 2012 Michael Kourlas
>
> 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.

223
node_modules/js2xmlparser/lib/js2xmlparser.js generated vendored Normal file
View File

@ -0,0 +1,223 @@
var xmlDeclaration = true;
var xmlVersion = "1.0";
var xmlEncoding = "UTF-8";
var attributeString = "@";
var valueString = "#";
var prettyPrinting = true;
var indentString = "\t";
module.exports = function (root, data, options) {
return toXML(init(root, data, options));
};
// Initialization
var init = function(root, data, options) {
// Error checking for root element
if (typeof root !== "string")
throw new Error("root element must be a string");
// Error checking and variable initialization for options
if (typeof options === "object" && options !== null) {
if ("declaration" in options) {
if ("include" in options.declaration) {
if (typeof options.declaration.include === "boolean")
xmlDeclaration = options.declaration.include;
else
throw new Error("declaration.include option must be a boolean");
}
if ("encoding" in options.declaration) {
if (typeof options.declaration.encoding === "string" || options.declaration.encoding === null)
xmlEncoding = options.declaration.encoding;
else
throw new Error("declaration.encoding option must be a string or null");
}
}
if ("attributeString" in options) {
if (typeof options.attributeString === "string")
attributeString = options.attributeString;
else
throw new Error("attributeString option must be a string");
}
if ("valueString" in options) {
if (typeof options.valueString === "string")
valueString = options.valueString;
else
throw new Error("valueString option must be a string");
}
if ("prettyPrinting" in options) {
if ("enabled" in options.prettyPrinting) {
if (typeof options.prettyPrinting.enabled === "boolean")
prettyPrinting = options.prettyPrinting.enabled;
else
throw new Error("prettyPrinting.enabled option must be a boolean");
}
if ("indentString" in options.prettyPrinting) {
if (typeof options.prettyPrinting.indentString === "string")
indentString = options.prettyPrinting.indentString;
else
throw new Error("prettyPrinting.indentString option must be a string");
}
}
}
// Error checking and variable initialization for data
if (typeof data !== "string" && typeof data !== "object")
throw new Error("data must be an object or a string");
if (typeof data === "string")
data = JSON.parse(data);
var tempData = {};
tempData[root] = data; // Add root element to object
return tempData;
};
// Convert object to XML
var toXML = function(object) {
// Initialize arguments, if necessary
var xml = arguments[1] || "";
var level = arguments[2] || 0;
for (var property in object) {
// Arrays
if (Object.prototype.toString.call(object[property]) === "[object Array]") {
// Create separate object for each array element and pass to this function
for (var i = 0; i < object[property].length; i++) {
var obj = {};
obj[property] = object[property][i];
xml = toXML(obj, xml, level);
}
}
// JSON-type objects with properties
else if (Object.prototype.toString.call(object[property]) === "[object Object]") {
xml += addIndent("<" + property, level);
// Add attributes
var lengthExcludingAttributes = Object.keys(object[property]).length;
if (Object.prototype.toString.call(object[property][attributeString]) === "[object Object]") {
lengthExcludingAttributes -= 1;
for (var attribute in object[property][attributeString])
xml += " " + attribute + "=\"" + toString(object[property][attributeString][attribute]) + "\"";
}
if (lengthExcludingAttributes === 0) // Empty object
xml += addBreak("/>");
else if (lengthExcludingAttributes === 1 && valueString in object[property]) // Value string only
xml += addBreak(">" + toString(object[property][valueString]) + "</" + property + ">");
else { // Object with properties
xml += addBreak(">");
// Create separate object for each property and pass to this function
for (var subProperty in object[property]) {
if (subProperty !== attributeString) {
var tempObject = {};
tempObject[subProperty] = object[property][subProperty];
xml = toXML(tempObject, xml, level + 1);
}
}
xml += addBreak(addIndent("</" + property + ">", level));
}
}
// Everything else
else {
xml += addBreak(addIndent("<" + property + ">" + toString(object[property]) + "</" + property + ">", level));
}
}
// Finalize XML at end of process
if (level === 0) {
// Remove extra line break at end of file
xml = xml.substring(0, xml.length - 1);
// Add XML declaration
if (xmlDeclaration)
if (xmlEncoding === null)
xml = addBreak("<?xml version=\"" + xmlVersion + "\"?>") + xml;
else
xml = addBreak("<?xml version=\"" + xmlVersion + "\" encoding=\"" + xmlEncoding + "\"?>") + xml;
}
return xml;
};
// Add indenting to data for pretty printing
var addIndent = function(data, level) {
if (prettyPrinting) {
var indent = "";
for (var i = 0; i < level; i++) {
indent += indentString;
}
data = indent + data;
}
return data;
};
// Add line break to data for pretty printing
var addBreak = function(data) {
return prettyPrinting ? data + "\n" : data;
};
// Convert anything into a valid XML string representation
var toString = function(data) {
// Recursive function used to handle nested functions
var functionHelper = function(data) {
if (Object.prototype.toString.call(data) === "[object Function]")
return (data() === undefined) ? data.toString() : functionHelper(data());
else
return data;
};
// Functions
if (Object.prototype.toString.call(data) === "[object Function]")
data = functionHelper(data);
// Empty objects
else if (Object.prototype.toString.call(data) === "[object Object]" && Object.keys(data).length === 0)
data = "";
// Cast data to string
if (typeof data !== "string")
data = data.toString();
// Escape illegal XML characters
data = data.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;");
return data;
};

30
node_modules/js2xmlparser/package.json generated vendored Normal file
View File

@ -0,0 +1,30 @@
{
"name": "js2xmlparser",
"description": "Parses JavaScript objects into XML",
"keywords": [
"convert",
"converter",
"js",
"json",
"object",
"objects",
"parse",
"parser",
"xml"
],
"homepage": "http://www.kourlas.net",
"version": "0.1.0",
"author": {
"name": "Michael Kourlas",
"email": "michaelkourlas@gmail.com"
},
"main": "./lib/js2xmlparser.js",
"repository": {
"type": "git",
"url": "git://github.com/michaelkourlas/node-js2xmlparser.git"
},
"license": "MIT",
"readme": "# node-js2xmlparser #\r\n\r\n## Overview ##\r\n\r\njs2xmlparser is a Node.js module that parses JavaScript objects into XML.\r\n\r\n## Features ##\r\n\r\nSince XML is a data-interchange format, js2xmlparser is designed primarily for JSON-type objects, arrays and primitive\r\ndata types, like many of the other JavaScript to XML parsers currently available for Node.js.\r\n\r\nHowever, js2xmlparser is capable of parsing any object, including native JavaScript objects such as Date and RegExp, by\r\ntaking advantage of each object's toString function. Functions are a special case where the return value of the function\r\nitself is used instead of the toString function, if available.\r\n\r\njs2xmlparser also supports a number of constructs unique to XML:\r\n\r\n* attributes (through a unique attribute property in objects)\r\n* mixed content (through a unique value property in objects)\r\n* multiple elements with the same name (through arrays)\r\n\r\njs2xmlparser can also pretty-print the XML it outputs with the option of customizing the indent string.\r\n\r\n## Installation ##\r\n\r\nThe easiest way to install js2xmlparser is to use npm: `npm install js2xmlparser`.\r\n\r\nAlternatively, you may download the source from GitHub and copy it to a folder named \"js2xmlparser\" within your\r\n\"node_modules\" directory.\r\n\r\n## Usage ##\r\n\r\nThe js2xmlparser module contains one function which takes the following arguments:\r\n\r\n* `root` - string containing the root element of the XML\r\n* `data` - object or JSON string to be converted to XML\r\n* `options` - object containing options (optional)\r\n * `declaration` - XML declaration options object (optional)\r\n * `include` - boolean representing whether an XML declaration is included (optional, default: true)\r\n * `encoding` - string representing the XML encoding for the corresponding attribute in the declaration; a value\r\n of null represents no encoding attribute (optional, default: \"UTF-8\")\r\n * `attributeString` - string containing the attribute property (optional, default: \"@\")\r\n * `valueString` - string containing the value property (optional, default: \"#\")\r\n * `prettyPrinting` - pretty-printing options object (optional)\r\n * `enabled` - boolean representing whether pretty-printing is enabled (optional, default: true)\r\n * `indentString` - string representing the indent (optional, default: \"\\t\")\r\n\r\n## Example ##\r\n\r\nThe following example illustrates the basic usage of js2xmlparser:\r\n\r\n var js2xmlparser = require(\"js2xmlparser\");\r\n\r\n var data = {\r\n \"firstName\": \"John\",\r\n \"lastName\": \"Smith\"\r\n };\r\n\r\n console.log(js2xmlparser(\"person\", data));\r\n\r\n > <?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n > <person>\r\n > <firstName>John</firstName>\r\n > <lastName>Smith</lastName>\r\n > </person>\r\n\r\nHere's a more complex example that builds on the first:\r\n\r\n var js2xmlparser = require(\"js2xmlparser\");\r\n\r\n var data = {\r\n \"firstName\": \"John\",\r\n \"lastName\": \"Smith\",\r\n \"dateOfBirth\": new Date(1964, 07, 26),\r\n \"address\": {\r\n \"@\": {\r\n \"type\": \"home\"\r\n },\r\n \"streetAddress\": \"3212 22nd St\",\r\n \"city\": \"Chicago\",\r\n \"state\": \"Illinois\",\r\n \"zip\": 10000\r\n },\r\n \"phone\": [\r\n {\r\n \"@\": {\r\n \"type\": \"home\"\r\n },\r\n \"#\": \"123-555-4567\"\r\n },\r\n {\r\n \"@\": {\r\n \"type\": \"cell\"\r\n },\r\n \"#\": \"456-555-7890\"\r\n }\r\n ],\r\n \"email\": function() {return \"john@smith.com\";}\r\n }\r\n\r\n console.log(js2xmlparser(\"person\", data));\r\n\r\n > <?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n > <person>\r\n > <firstName>John</firstName>\r\n > <lastName>Smith</lastName>\r\n > <dateOfBirth>Wed Aug 26 1964 00:00:00 GMT-0400 (Eastern Daylight Time)</dateOfBirth>\r\n > <address type=\"home\">\r\n > <streetAddress>3212 22nd St</streetAddress>\r\n > <city>Chicago</city>\r\n > <state>Illinois</state>\r\n > <zip>10000</zip>\r\n > </address>\r\n > <phone type=\"home\">123-555-4567</phone>\r\n > <phone type=\"cell\">456-555-7890</phone>\r\n > <email>john@smith.com</email>\r\n > </person>",
"_id": "js2xmlparser@0.1.0",
"_from": "js2xmlparser"
}

View File

@ -1,70 +0,0 @@
/* This work is licensed under Creative Commons GNU LGPL License.
License: http://creativecommons.org/licenses/LGPL/2.1/
Version: 0.9/modified to conform to commonjs modules pattern
Author: Stefan Goessner/2006
Web: http://goessner.net/
*/
var json2xml = (typeof exports === 'undefined')? {} : exports; // like commonjs
(function() {
json2xml.convert = function(o) {
var toXml = function(v, name, ind) {
var xml = "";
if (v instanceof Array) {
for (var i=0, n=v.length; i<n; i++)
xml += toXml(v[i], name, ind+"");
}
else if (typeof(v) == "object") {
var hasChild = false;
xml += ind + "<" + name;
for (var m in v) {
if (m.charAt(0) == "@")
xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
else
hasChild = true;
}
xml += hasChild ? ">\n" : "/>";
if (hasChild) {
for (var m in v) {
if (m == "#text")
xml += makeSafe(v[m]);
else if (m == "#cdata")
xml += "<![CDATA[" + lines(v[m]) + "]]>";
else if (m.charAt(0) != "@")
xml += toXml(v[m], m, ind+"\t");
}
xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + "</" + name + ">\n";
}
}
else { // added special-character transform, but this needs to be better handled [micmath]
xml += ind + "<" + name + ">" + makeSafe(v.toString()) + "</" + name + ">\n";
}
return xml;
},
xml="";
for (var m in o) {
xml += toXml(o[m], m, "");
}
return xml;
}
function lines(str) {
// normalise line endings, all in file will be unixy
str = str.replace(/\r\n/g, '\n');
return str;
}
function makeSafe(str) {
// xml special charaters
str = str.replace(/</g, '&lt;').replace(/&/g, '&amp;');
return lines(str);
}
})();

View File

@ -206,8 +206,8 @@ exports.publish = function(data, opts) {
if (opts.destination === 'console') {
if (opts.query && opts.query.format === 'xml') {
var xml = require('goessner/json2xml');
console.log( '<jsdoc>\n' + xml.convert(root) + '\n</jsdoc>' );
var xml = require('js2xmlparser');
console.log( xml('jsdoc', root) );
}
else {
console.log(root);