From bdee90463f15ccc522430e283c82968ea6ba43b1 Mon Sep 17 00:00:00 2001 From: Jeff Williams Date: Mon, 15 Oct 2012 20:47:08 -0700 Subject: [PATCH] replace JSON-to-XML serializer --- Jake/templates/package.json.tmpl | 1 + node_modules/js2xmlparser/LICENSE.md | 16 ++ node_modules/js2xmlparser/lib/js2xmlparser.js | 223 ++++++++++++++++++ node_modules/js2xmlparser/package.json | 30 +++ nodejs_modules/goessner/json2xml.js | 70 ------ templates/haruki/publish.js | 4 +- 6 files changed, 272 insertions(+), 72 deletions(-) create mode 100644 node_modules/js2xmlparser/LICENSE.md create mode 100644 node_modules/js2xmlparser/lib/js2xmlparser.js create mode 100644 node_modules/js2xmlparser/package.json delete mode 100644 nodejs_modules/goessner/json2xml.js diff --git a/Jake/templates/package.json.tmpl b/Jake/templates/package.json.tmpl index 46900d9f..3e268989 100644 --- a/Jake/templates/package.json.tmpl +++ b/Jake/templates/package.json.tmpl @@ -17,6 +17,7 @@ } ], "dependencies": { + "js2xmlparser": "0.1.0", "markdown": "0.4.0", "taffydb": "git://github.com/hegemonic/taffydb.git", "wrench": "1.3.9" diff --git a/node_modules/js2xmlparser/LICENSE.md b/node_modules/js2xmlparser/LICENSE.md new file mode 100644 index 00000000..0cb547eb --- /dev/null +++ b/node_modules/js2xmlparser/LICENSE.md @@ -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. \ No newline at end of file diff --git a/node_modules/js2xmlparser/lib/js2xmlparser.js b/node_modules/js2xmlparser/lib/js2xmlparser.js new file mode 100644 index 00000000..cf8110f1 --- /dev/null +++ b/node_modules/js2xmlparser/lib/js2xmlparser.js @@ -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]) + ""); + 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("", level)); + } + } + // Everything else + else { + + xml += addBreak(addIndent("<" + property + ">" + toString(object[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; + else + xml = addBreak("") + 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, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + + return data; +}; \ No newline at end of file diff --git a/node_modules/js2xmlparser/package.json b/node_modules/js2xmlparser/package.json new file mode 100644 index 00000000..d4384f36 --- /dev/null +++ b/node_modules/js2xmlparser/package.json @@ -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 > \r\n > \r\n > John\r\n > Smith\r\n > \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 > \r\n > \r\n > John\r\n > Smith\r\n > Wed Aug 26 1964 00:00:00 GMT-0400 (Eastern Daylight Time)\r\n >
\r\n > 3212 22nd St\r\n > Chicago\r\n > Illinois\r\n > 10000\r\n >
\r\n > 123-555-4567\r\n > 456-555-7890\r\n > john@smith.com\r\n >
", + "_id": "js2xmlparser@0.1.0", + "_from": "js2xmlparser" +} diff --git a/nodejs_modules/goessner/json2xml.js b/nodejs_modules/goessner/json2xml.js deleted file mode 100644 index 5283249f..00000000 --- a/nodejs_modules/goessner/json2xml.js +++ /dev/null @@ -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" : "/>"; - if (hasChild) { - for (var m in v) { - if (m == "#text") - xml += makeSafe(v[m]); - else if (m == "#cdata") - xml += ""; - else if (m.charAt(0) != "@") - xml += toXml(v[m], m, ind+"\t"); - } - xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + "\n"; - } - } - else { // added special-character transform, but this needs to be better handled [micmath] - xml += ind + "<" + name + ">" + makeSafe(v.toString()) + "\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(/\n' + xml.convert(root) + '\n' ); + var xml = require('js2xmlparser'); + console.log( xml('jsdoc', root) ); } else { console.log(root);