Created
October 11, 2013 18:42
-
-
Save fantactuka/6939900 to your computer and use it in GitHub Desktop.
WADL parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<title>WADL parser</title> | |
<link rel="stylesheet" href="application.css"/> | |
<style type="text/css"> | |
ul#output { | |
list-style: none outside; | |
margin: 0 0 20px; | |
padding: 0; | |
} | |
ul#output > li { | |
border-top: 1px solid #ddd; | |
cursor: pointer; | |
padding: 10px; | |
} | |
ul#output > li:nth-child(odd) { | |
background: #eee; | |
} | |
ul#output > li:hover { | |
background: #e7f3ff; | |
} | |
.resource-type, | |
.resource-param-type { | |
display: inline-block; | |
min-width: 50px; | |
text-align: center; | |
font-weight: normal; | |
padding-left: 5px; | |
padding-right: 5px; | |
margin-right: 15px; | |
text-transform: uppercase; | |
font-size: 0.75em; | |
} | |
.resource-type-get { | |
background: #8da67c; | |
} | |
.resource-type-post { | |
background: #6376a6; | |
} | |
.resource-type-put { | |
background: #b691c8; | |
} | |
.resource-type-delete { | |
background: #a63446; | |
} | |
.resource-path, | |
.resource-param-name { | |
font-family: Monaco, Menlo, Consolas, "Courier New", monospace; | |
} | |
.collapsed div.params { | |
display: none; | |
} | |
</style> | |
<script type="text/javascript" src="lib/jquery.js"></script> | |
<script type="text/javascript" src="lib/underscore.js"></script> | |
<script type="text/javascript"> | |
function xml2json(xml, tab) { | |
var X = { | |
toObj: function(xml) { | |
var o = {}; | |
if (xml.nodeType == 1) { // element node .. | |
if (xml.attributes.length) // element with attributes .. | |
for (var i = 0; i < xml.attributes.length; i++) | |
o["@" + xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue || "").toString(); | |
if (xml.firstChild) { // element has child nodes .. | |
var textChild = 0, cdataChild = 0, hasElementChild = false; | |
for (var n = xml.firstChild; n; n = n.nextSibling) { | |
if (n.nodeType == 1) hasElementChild = true; | |
else if (n.nodeType == 3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) textChild++; // non-whitespace text | |
else if (n.nodeType == 4) cdataChild++; // cdata section node | |
} | |
if (hasElementChild) { | |
if (textChild < 2 && cdataChild < 2) { // structured element with evtl. a single text or/and cdata node .. | |
X.removeWhite(xml); | |
for (var n = xml.firstChild; n; n = n.nextSibling) { | |
if (n.nodeType == 3) // text node | |
o["#text"] = X.escape(n.nodeValue); | |
else if (n.nodeType == 4) // cdata node | |
o["#cdata"] = X.escape(n.nodeValue); | |
else if (o[n.nodeName]) { // multiple occurence of element .. | |
if (o[n.nodeName] instanceof Array) | |
o[n.nodeName][o[n.nodeName].length] = X.toObj(n); | |
else | |
o[n.nodeName] = [o[n.nodeName], X.toObj(n)]; | |
} | |
else // first occurence of element.. | |
o[n.nodeName] = X.toObj(n); | |
} | |
} | |
else { // mixed content | |
if (!xml.attributes.length) | |
o = X.escape(X.innerXml(xml)); | |
else | |
o["#text"] = X.escape(X.innerXml(xml)); | |
} | |
} | |
else if (textChild) { // pure text | |
if (!xml.attributes.length) | |
o = X.escape(X.innerXml(xml)); | |
else | |
o["#text"] = X.escape(X.innerXml(xml)); | |
} | |
else if (cdataChild) { // cdata | |
if (cdataChild > 1) | |
o = X.escape(X.innerXml(xml)); | |
else | |
for (var n = xml.firstChild; n; n = n.nextSibling) | |
o["#cdata"] = X.escape(n.nodeValue); | |
} | |
} | |
if (!xml.attributes.length && !xml.firstChild) o = null; | |
} | |
else if (xml.nodeType == 9) { // document.node | |
o = X.toObj(xml.documentElement); | |
} | |
else | |
alert("unhandled node type: " + xml.nodeType); | |
return o; | |
}, | |
toJson: function(o, name, ind) { | |
var json = name ? ("\"" + name + "\"") : ""; | |
if (o instanceof Array) { | |
for (var i = 0, n = o.length; i < n; i++) | |
o[i] = X.toJson(o[i], "", ind + "\t"); | |
json += (name ? ":[" : "[") + (o.length > 1 ? ("\n" + ind + "\t" + o.join(",\n" + ind + "\t") + "\n" + ind) : o.join("")) + "]"; | |
} | |
else if (o == null) | |
json += (name && ":") + "null"; | |
else if (typeof(o) == "object") { | |
var arr = []; | |
for (var m in o) | |
arr[arr.length] = X.toJson(o[m], m, ind + "\t"); | |
json += (name ? ":{" : "{") + (arr.length > 1 ? ("\n" + ind + "\t" + arr.join(",\n" + ind + "\t") + "\n" + ind) : arr.join("")) + "}"; | |
} | |
else if (typeof(o) == "string") | |
json += (name && ":") + "\"" + o.toString() + "\""; | |
else | |
json += (name && ":") + o.toString(); | |
return json; | |
}, | |
innerXml: function(node) { | |
var s = "" | |
if ("innerHTML" in node) | |
s = node.innerHTML; | |
else { | |
var asXml = function(n) { | |
var s = ""; | |
if (n.nodeType == 1) { | |
s += "<" + n.nodeName; | |
for (var i = 0; i < n.attributes.length; i++) | |
s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue || "").toString() + "\""; | |
if (n.firstChild) { | |
s += ">"; | |
for (var c = n.firstChild; c; c = c.nextSibling) | |
s += asXml(c); | |
s += "</" + n.nodeName + ">"; | |
} | |
else | |
s += "/>"; | |
} | |
else if (n.nodeType == 3) | |
s += n.nodeValue; | |
else if (n.nodeType == 4) | |
s += "<![CDATA[" + n.nodeValue + "]]>"; | |
return s; | |
}; | |
for (var c = node.firstChild; c; c = c.nextSibling) | |
s += asXml(c); | |
} | |
return s; | |
}, | |
escape: function(txt) { | |
return txt.replace(/[\\]/g, "\\\\") | |
.replace(/[\"]/g, '\\"') | |
.replace(/[\n]/g, '\\n') | |
.replace(/[\r]/g, '\\r'); | |
}, | |
removeWhite: function(e) { | |
e.normalize(); | |
for (var n = e.firstChild; n;) { | |
if (n.nodeType == 3) { // text node | |
if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node | |
var nxt = n.nextSibling; | |
e.removeChild(n); | |
n = nxt; | |
} | |
else | |
n = n.nextSibling; | |
} | |
else if (n.nodeType == 1) { // element node | |
X.removeWhite(n); | |
n = n.nextSibling; | |
} | |
else // any other node | |
n = n.nextSibling; | |
} | |
return e; | |
} | |
}; | |
if (xml.nodeType == 9) // document node | |
xml = xml.documentElement; | |
var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t"); | |
return "{\n" + tab + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "\n}"; | |
} | |
$(function() { | |
var $form = $('#url-form'), | |
$url = $('#url-input'), | |
$output = $('#output'), | |
$toggle = $('#toggle-params'), | |
$resourceTpl = _.template($('#resource-template').html()), | |
collapsedClass = 'collapsed'; | |
$toggle.click(function() { | |
$output.find('> li')[$output.find('.' + collapsedClass).length ? 'removeClass' : 'addClass'](collapsedClass); | |
return false; | |
}); | |
$output.on('click', '> li', function(e) { | |
$(e.currentTarget).toggleClass(collapsedClass); | |
}); | |
$form.on('submit',function() { | |
var url = $url.val(); | |
$.ajax(url, { | |
success: function(xml) { | |
var json = xml2json(xml, ''), | |
data = JSON.parse(json); | |
try { | |
render(data.application.resources); | |
} catch(e) { | |
renderError(); | |
throw e; | |
} | |
}, | |
error: renderError | |
}); | |
return false; | |
}); | |
function renderError() { | |
$output.html('<li class="alert-error">Unable to parse WADL</li>'); | |
} | |
function render(resources) { | |
var html = _.map(parseData(resources),function(resource) { | |
return $resourceTpl({ resource: resource }); | |
}).join(''); | |
$output.html(html); | |
} | |
function parseData(resources) { | |
return _.chain(resources.resource).map(function(resource) { | |
return parseResource(resource); | |
}).flatten().value(); | |
} | |
function parseResource(resource, base) { | |
var path = (base || '') + resource['@path'], | |
results = []; | |
if (resource.method) { | |
var request = resource.method.request || {}, | |
queryParams = parseParams(request.param), | |
type = resource.method['@name'], | |
queryString = _.isEmpty(queryParams) ? '' : '?' + $.param(queryParams), | |
pathHtml = (path + decodeURIComponent(queryString)).replace(/\{([^}]*)\}/g, '<code>$1</code>'); | |
results.push({ | |
path: path, | |
pathHtml: pathHtml, | |
type: type, | |
typeCss: 'resource-type-' + type.toLowerCase(), | |
queryParams: queryParams, | |
pathParams: parseParams(resource.param) | |
}); | |
} | |
if (resource.resource) { | |
_.chain([resource.resource]).flatten().each(function(childResource) { | |
results.push(parseResource(childResource, path)) | |
}); | |
} | |
return results; | |
} | |
function parseParams() { | |
var params = _.chain(arguments).flatten().compact().value(), | |
result = []; | |
_.each(params, function(param) { | |
result.push({ | |
name: param['@name'], | |
type: param['@type'] ? param['@type'].replace('xs:', '') : 'custom', | |
value: '{' + param['@name'] + '}' | |
}); | |
}); | |
return result; | |
} | |
}); | |
</script> | |
</head> | |
<body> | |
<div class="container text-left" style="width: 90%"> | |
<h2>WADL parser</h2> | |
<form action="#" id="url-form"> | |
<div class="input-prepend input-append"> | |
<span class="add-on"><small>WADL URL</small></span> | |
<input class="span5" type="text" value="" id="url-input"> | |
<input class="btn" type="submit" value="Go!"/> | |
</div> | |
</form> | |
<p class="text-right"> | |
<a href="#toggle" id="toggle-params" class="btn btn-small">Expand / collapse</a> | |
</p> | |
<ul id="output"></ul> | |
<script type="text/x-template" id="resource-template"> | |
<li> | |
<span class="label resource-type <%= resource.typeCss %>"><%= resource.type %></span> | |
<span class="resource-path"><%= resource.pathHtml %></span> | |
<div class="params"> | |
<% if (resource.pathParams.length) { %> | |
<h5>Path params</h5> | |
<ul class="params"> | |
<% for(var i = 0; i < resource.pathParams.length; i ++) { %> | |
<li> | |
<span class="label resource-param-type"><%= resource.pathParams[i].type %></span> | |
<span class="resource-param-name"><%= resource.pathParams[i].name %></span> | |
</li> | |
<% } %> | |
</ul> | |
<% } %> | |
<% if (resource.queryParams.length) { %> | |
<h5>Query params</h5> | |
<ul class="params"> | |
<% for(var i = 0; i < resource.queryParams.length; i ++) { %> | |
<li> | |
<span class="label resource-param-type"><%= resource.queryParams[i].type %></span> | |
<span class="resource-param-name"><%= resource.queryParams[i].name %></span> | |
</li> | |
<% } %> | |
</ul> | |
<% } %> | |
</div> | |
</li> | |
</script> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment