add json2xml plugin
diff --git a/json2xml/index.js b/json2xml/index.js
new file mode 100644
index 0000000..2b78e72
--- /dev/null
+++ b/json2xml/index.js
@@ -0,0 +1,194 @@
+'use strict';
+/**
+ * This plugin accumulates data chunks from the client into an array
+ * property on the request or response, concats them on end. Then  
+ * transforms the request or response based on 'accept' or 'content-type' 
+ * headers. 
+ * 
+ * If the HTTP verb is GET and the Accept type does not match the 
+ * response type, the plugin will attempt to transform it (from 
+ * xml to json or vice versa).
+ *
+ * If the HTTP verb is NOT GET then the content-type is used. If the
+ * content-type is set to 'json', then an attempt is made to transform to
+ * 'xml' and vice-versa.
+ *
+ * This plugin can be disabled by sending the 'x-apigee-json2xml' http
+ * header.
+ *
+ * Users should be aware that buffering large requests or responses in
+ * memory can cause Apigee Edge Microgateway to run out of memory under
+ * high load or with a large number of concurrent requests. So this plugin
+ * should only be used when it is known that request/response bodies are small.
+ */
+
+var debug = require('debug')('plugin:json2xml');
+//library to convert json to xml
+var js2xmlparser = require("js2xmlparser");
+//library to convert xml to json
+var parseString = require("xml2js").parseString;
+var util = require("util");
+
+module.exports.init = function (config, logger, stats) {
+
+	//initialize the variables to false
+
+	//variables to control whether request and/or response transformation should take place
+	var requestXML = false;
+	var requestJSON = false;
+	var responseJSON = false;
+	var responseXML = false;
+	//use these variables to determine the content type of response sent by target server
+	var responseIsXML = false;
+	var responseIsJSON = false;
+	//flag to control whether transfornation should take place
+	var disable = false;
+
+	//method to accumulate responses
+	function accumulateResponse(res, data) {
+		debug('plugin accumulateResponse');
+		if (!res._chunks) res._chunks = [];
+		res._chunks.push(data);
+	}
+
+	//method to accumulate requests
+	function accumulateRequest(req, data) {
+		debug('plugin accumulateRequest');
+		if (disable) return;
+		if (!req._chunks) req._chunks = [];
+		req._chunks.push(data);
+	}
+	
+	return {
+
+		onrequest: function(req, res, next) {
+			debug('plugin onrequest');
+			var method  = req.method.toLowerCase();
+			var acceptType = req.headers['accept'];
+			var contentType = req.headers['content-type'];
+
+			if (req.headers['x-apigee-json2xml-disable']) disable = true;
+
+			debug("accept header: " + acceptType);
+			debug("content-type header: " + contentType);
+
+			//if plugin is disabled don't process headers.
+			if (!disable) {
+				if (method === "get" && acceptType === "application/xml") {
+					responseXML = true;
+				} else if (method === "get" && acceptType === "application/json") {
+					responseJSON = true;
+				} else if (method !== "get" && contentType === "application/json") {
+					requestJSON = true;
+					responseJSON = true;
+				} else if (method !== "get" && contentType === "application/xml") {
+					requestXML = true;
+					responseXML = true;
+				}
+			}
+			
+			debug("requestJSON flag is " + requestJSON);
+			debug("responseJSON flag is " + responseJSON);
+
+			debug("requestXML flag is " + requestXML);
+			debug("responseXML flag is " + responseXML);
+
+			debug("plugin disabled: " + disable);
+
+			next();
+		},
+		// indicates start of target response
+		// response headers and status code should be available at this time
+		onresponse: function(req, res, next) {
+			debug('plugin onresponse');
+			//nothing to do on response
+			next();
+		},
+		//
+		ondata_request: function(req, res, data, next) {
+			debug('plugin ondata_request');
+			if (data && data.length > 0 && disable == false) accumulateRequest(req, data);
+			next(null, null);
+		},
+		//
+		//
+		ondata_response: function(req, res, data, next) {
+			debug('plugin ondata_response');
+			if (data && data.length > 0 && disable == false) accumulateResponse(res, data);
+			next(null, null);
+		},
+		//
+		onend_request: function(req, res, data, next) {
+			debug('plugin onend_request');
+			if (data && data.length > 0 && disable == false) accumulateRequest(res, data);
+			var content = null;
+			if(req._chunks && req._chunks.length) {
+				content = Buffer.concat(req._chunks);
+			}
+			delete req._chunks;
+
+			//if pugin is disabled, don't do anything
+			if (!disable) {
+				if (requestJSON) {
+					//the request needs to be transformed to xml before sending to 
+					//the target server.
+
+					//set request content type.
+					req.setHeader('Content-Type', 'application/xml');
+					next(null, js2xmlparser.parse("Root",JSON.parse(content)));
+				} else if (requestXML) {
+					//set request content type.
+					req.setHeader('Content-Type', 'application/json');
+					parseString(content.toString(), function(err, js){
+						if (err) next (err);
+						next(null, JSON.stringify(js));
+					});
+				} else { //do nothing
+					next(null, content);
+				}
+			} else {
+				next(null, content);
+			}
+		},
+		//
+		onend_response: function(req, res, data, next) {
+			debug('plugin onend_request');
+			if (data && data.length > 0 && disable == false) accumulateResponse(res, data);
+
+			var contentType = res.getHeader('content-type');
+			if (contentType === "application/xml") {
+				responseIsXML = true;
+			} else if (contentType === "application/json") {
+				responseIsJSON = true;
+			}
+
+			debug("responseIsJSON flag is " + responseIsJSON);
+			debug("responseIsXML flag is" + responseIsXML);
+
+
+			var content = null;
+			if(res._chunks && res._chunks.length) {
+				content = Buffer.concat(res._chunks);
+			}
+			delete res._chunks;
+
+			//if disabled don't do anything.
+			if (!disable) {
+				if (responseXML && responseIsJSON) {
+					res.setHeader('Content-Type', 'application/xml');
+					next(null, js2xmlparser.parse("Root",JSON.parse(content)));
+				} else if (responseJSON && responseIsXML) {
+					res.setHeader('Content-Type', 'application/json');
+					parseString(content.toString(), function(err, js){
+						if (err) next (err);
+						next(null, JSON.stringify(js));
+					});
+				} else {
+					next(null, content);
+				}
+			} else {
+				next(null, content);
+			}
+		}		
+	};
+}
\ No newline at end of file
diff --git a/json2xml/package.json b/json2xml/package.json
new file mode 100644
index 0000000..52013ed
--- /dev/null
+++ b/json2xml/package.json
@@ -0,0 +1,24 @@
+{
+  "name": "edgemicro-json2xml",
+  "version": "1.0.0",
+  "description": "This plugin transforms JSON to XML and vice versa based on the Accept and Content-Type http headers",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "srinandan",
+  "license": "Apache 2.0",
+  "dependencies": {
+    "debug": "^2.2.0",
+    "js2xmlparser": "^2.0.2",
+    "xml2js": "^0.4.17"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/apigee/microgateway-plugins.git"
+  },
+  "bugs": {
+    "url": "https://github.com/apigee/microgateway-plugins/issues"
+  },
+  "homepage": "https://github.com/apigee/microgateway-plugins#readme"
+}