#!/usr/bin/env python
"""
A simple utility to convert Splunk's simple dashboard/form XML format used in
Splunk 4.0 and help you convert it into the advanced XML view format using the
provided "showsource" feature. In the future, an automated tool will most likely
be available. However, in the mean time it is quite tedious to convert all of
that by hand, so I wrote this to quickly convert the python dictionaries dumped
on the web page into the advance XML form structure one module at a time.
Basic instructions:
* Point your browser to your view and add "?showsource=true" to the end of the
URL, for example: http://localhost:8000/app/myapp/myview?showsource=true
* View the source (or download the HTML). This is because of embedded "<" and ">"
characters.
* Run a single expression (Found between the
tags in the HTML. But I didn't want to put the effort into it.
* Minimal XML escaping is handled here. If "<>" are found then a CDATA element
is used. And "&" is escaped in regular strings. This was good enough for my
needs, but may need to be improved upon.
This was written/tested with Splunk 4.0.6.
*** Feel free to use this script however you would like. It is provided as-is.
There is no warranty of any kind. ***
"""
__author__ = "Lowell Alleman"
__version__ = "0.2"
import sys
import re
INDENT = " "
def write_dict(d, stream, indent=0):
" Write out a nested dictionary structure in the XML
format."
prefix = INDENT * indent
for key, value in d.items():
if value is None:
continue
stream.write("%s
" % (prefix,key))
multiline = False
if type(value) == dict:
stream.write("\n")
write_dict(value, stream, indent+1)
multiline = True
elif type(value) in (list, tuple):
write_list(value, stream, indent+1)
multiline = True
elif type(value) == str and ("<" in value or ">" in value):
stream.write("" % value)
else:
stream.write(str(value).replace("&", "&"))
if multiline:
stream.write(prefix)
stream.write("\n")
def write_list(lst, stream, indent=0):
prefix = INDENT * indent
for item in lst:
stream.write(prefix + "
\n")
if type(item) == dict:
write_dict(item, stream, indent+1)
else:
raise TypeError("Always expecting a list of dictionariy. "
"Found type: %s" % type(item))
stream.write(prefix + "
\n")
def convert_to_xml(d, stream):
" Write out a
/ XML structure for the given dictionary. "
d = dict(d)
className = d["className"]
if "params" in d:
params = d["params"]
del d["params"]
else:
params = {}
del d["className"]
stream.write('\n")
write_dict(params, stream)
stream.write("\n")
stream.write("\n")
stream.flush()
def convert_py_to_xml(py_dict_string, xml_out):
"""
Take a single python dictionary string expression and convert it to XML. Any
errors are simply written to standard error and the process continues.
"""
try:
# Convert python dictionary string into a real python dictionary
d = eval(py_dict_string)
convert_to_xml(d, xml_out)
except Exception, e:
sys.stderr.write("Failed to convert to Splunk Advanced XML format"
"(%s)\nInput expression:\n%s\n\n" % (e, py_dict_string))
if __name__ == '__main__':
# Read entire input stream at once
chunk = sys.stdin.read()
# Lazy approach to handle an entire HTML file based on the fact that the
# each module has it's own dictionary within a "" block.
if "" in chunk:
chunks = re.findall(r"(.*?)
", chunk, re.IGNORECASE | re.MULTILINE | re.DOTALL)
else:
chunks = [ chunk ]
for chunk in chunks:
convert_py_to_xml(chunk, sys.stdout)