Written in python (download), pyxtree uses the treeview and scrolledwindow controls from the pyGTK download) UI, together with the ElementTree xml library that is included in the python standard library.
# --- --- --- --- --- --- --- --- --- --- --- ---
from optparse import OptionParser
# pyGTK --- --- --- --- --- --- --- --- ---
import pygtk
pygtk.require('2.0')
import gtk
# ElementTree - --- --- --- --- --- --- ---
import xml.etree.ElementTree as ET
# --- --- --- --- --- --- --- --- --- --- --- ---
import sys
xml_2_ns = {
'http://www.s3.org/XML/1998/namespace' : 'xml',
}
ns_2_xml = {
'xml' : 'http://www.s3.org/XML/1998/namespace',
}
def extend_tree(treestore, element, parent_node, ns_list):
'''
'''
#import pdb; pdb.set_trace()
node_label = '%s' % strip_ns_from_str(element.tag, ns_list)
if element.text != None:
element_text = element.text.strip()
if (len(element_text) > 0):
element_text = strip_ns_from_str(element_text, ns_list)
#discard = treestore.append(node, [element_text])
node_label = 'e %s : %s' % (node_label, element_text)
node = treestore.append(parent_node, [node_label])
# add attribute name/val pairs to node
for name, value in element.items():
name = strip_ns_from_str(name, ns_list)
value = strip_ns_from_str(value, ns_list)
label = 'a %s = %s' % (name, value)
treestore.append(node, [label])
# recurse over children
for child_element in element.getchildren():
child_node = extend_tree(treestore, child_element, node, ns_list)
return node
def etree_to_gtk_treestore(tree):
'''
construct gtk.TreeStore(str) from ElementTree
'''
treestore = gtk.TreeStore(str)
ns_list = ns_list_from_tree(tree)
element = tree.getroot()
node_label = '%s' % strip_ns_from_str(element.tag, ns_list)
if element.text != None:
element_text = element.text.strip()
if (len(element_text) > 0):
element_text = strip_ns_from_str(element_text, ns_list)
node_label = 'e %s : %s' % (node_label, element_text)
node = treestore.append(None, [node_label])
for child_e in element.getchildren():
extend_tree(treestore, child_e, node, ns_list)
# add attribute name/val pairs to node
for name, value in element.items():
name = strip_ns_from_str(name, ns_list)
value = strip_ns_from_str(value, ns_list)
label = '%s = %s' % (name, value)
treestore.append(None, [label])
# if ns is global
for ns in ns_list:
label = 'xmlns : %s' % ns
treestore.append(None, [label])
return treestore
def ns_from_string(s):
left = s.find('{')
right = s.find('}')
ns = s[left+1:right]
return ns
def process_potential_ns_string(s, ns_list):
if s == None:
return
if (s.find('{') != -1) and (s.find('}') != -1):
ns = ns_from_string(s)
if (ns not in ns_list):
ns_list.append(ns)
def ns_list_from_element(el, ns_list):
# tag
process_potential_ns_string(el.tag, ns_list)
# text
process_potential_ns_string(el.text, ns_list)
# attributes
for name, value in el.items():
process_potential_ns_string(name, ns_list)
process_potential_ns_string(value, ns_list)
for child_el in el.getchildren():
ns_list_from_element(child_el, ns_list)
return ns_list
def ns_list_from_tree(etree):
'''
'''
ns_list = []
root_e = etree.getroot()
# tag
process_potential_ns_string(root_e.tag, ns_list)
# text
process_potential_ns_string(root_e.text, ns_list)
# attributes
for name, value in root_e.items():
process_potential_ns_string(name, ns_list)
process_potential_ns_string(value, ns_list)
# child elements
for child_el in root_e.getchildren():
ns_list_from_element(child_el, ns_list)
return ns_list
def strip_ns_from_str(s, ns_list):
stripped = str(s)
for ns in ns_list:
token = '{%s}' % ns
loc = stripped.find(token)
if (loc != -1):
stripped = stripped[:loc] + stripped[loc + len(token):len(stripped)]
return stripped
class XMLTreeView:
'''
'''
def delete_event(widget, event, data=None):
'''
not an instance method, cuz gtk will not call as such
'''
gtk.main_quit()
return False
def __init__(self, path, title='pyxtree - python XML tree viewer', xsize=900, ysize = 500):
'''
'''
etree = ET.parse(path)
self.treestore = etree_to_gtk_treestore(etree)
self.window = gtk.Dialog()
self.window.connect("destroy", self.delete_event)
self.window.set_border_width(0)
self.swin_tree = gtk.ScrolledWindow()
self.swin_tree.set_border_width(10)
self.swin_tree.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
self.window.vbox.pack_start(self.swin_tree, True, True, 0)
self.swin_text = gtk.ScrolledWindow()
self.swin_text.set_border_width(10)
self.swin_text.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
self.window.vbox.pack_start(self.swin_text, True, True, 0)
self.window.set_title(title)
self.window.set_size_request(xsize, ysize)
self.window.connect("delete_event", self.delete_event)
# create the TreeView using treestore
self.treeview = gtk.TreeView(self.treestore)
self.tvcolumn = gtk.TreeViewColumn(path)
self.treeview.append_column(self.tvcolumn)
self.cell = gtk.CellRendererText()
# add the cell to the tvcolumn and allow it to expand
self.tvcolumn.pack_start(self.cell, True)
# set the cell "text" attribute to column 0 - retrieve text
# from that column in treestore
self.tvcolumn.add_attribute(self.cell, 'text', 0)
# make it searchable
self.treeview.set_search_column(0)
# Allow sorting on the column
#self.tvcolumn.set_sort_column_id(0)
# Allow drag and drop reordering of rows
#self.treeview.set_reorderable(True)
self.swin_tree.add_with_viewport(self.treeview)
self.swin_tree.show()
xfile = open(path, 'r')
xtext = xfile.read()
xfile.close()
label = gtk.Label(xtext)
# ns_list = ns_list_from_tree(etree)
# ns_str = ''
# for ns in ns_list:
# ns_str = ns_str + str(ns) + '\n'
# label = gtk.Label(ns_str)
label.set_alignment(xalign=0, yalign=0.5)
self.swin_text.add_with_viewport(label)
self.swin_text.show()
self.window.show_all()
def main(path = None):
'''
'''
if (path == None):
filechooser = gtk.FileChooserDialog(
title=None,
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
filter_stdxmlfiles = gtk.FileFilter()
filter_stdxmlfiles.set_name("Std XML Files")
filter_stdxmlfiles.add_pattern("*.xml")
filter_stdxmlfiles.add_pattern("*.wsdl")
filechooser.add_filter(filter_stdxmlfiles)
filter_allfiles = gtk.FileFilter()
filter_allfiles.set_name("All files")
filter_allfiles.add_pattern("*")
filechooser.add_filter(filter_allfiles)
response = filechooser.run()
if response == gtk.RESPONSE_OK:
path = filechooser.get_filename()
elif response == gtk.RESPONSE_CANCEL:
pass
#log failure
filechooser.destroy()
if (path != None):
tree_view = XMLTreeView(path)
gtk.main()
return
def src_file_from_cmd_args(args):
'''
'''
akapy = [
'pyxtree',
'pyxtree.py',
'python',
'python.exe',
'python2.5',
'python25.exe',
]
cleaned = []
for arg in args:
washed = arg.strip().lower()
if (washed not in akapy) and (washed.find('python') == -1):
cleaned.append(washed)
if len(cleaned) == 0:
cleaned = [None]
return cleaned
def configure_logging(LOG_FILENAME='pyxtree.log'):
import logging
logging.basicConfig(filename=LOG_FILENAME,level=logging.INFO)
log = logging.getLogger()
return log
def setup_command_line_options():
'''
using optparse
define command line arguments
return target filename, None if none specified
'''
parser = OptionParser()
parser.add_option('-f', dest='filename', help='target xml file to view')
(options, args) = parser.parse_args()
return(options.filename)
if __name__ == "__main__":
print('\nPyXTree - david.barkhuizen@gmail.com')
print('help: pyxtree -h\n')
xmlfilepath = setup_command_line_options()
log = configure_logging()
log.info('target file specified at command line = %s' % xmlfilepath)
main(path=xmlfilepath)
No comments:
Post a Comment
comment: