# Author: Miguel Martinez Lopez
#
# Uncomment the next line to see my email
# print("Author's email: %s"%"61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex"))
try:
from ttk import Treeview, Scrollbar, Frame
from Tkconstants import HORIZONTAL, VERTICAL, N,S,E,W, END
except ImportError:
from tkinter.ttk import Treeview, Scrollbar, Frame
from tkinter.constants import HORIZONTAL, VERTICAL, N,S,E,W, END
import xml.etree.ElementTree as ET
from operator import attrgetter
def autoscroll(sbar, first, last):
"""Hide and show scrollbar as needed."""
first, last = float(first), float(last)
if first <= 0 and last >= 1:
sbar.grid_remove()
else:
sbar.grid()
sbar.set(first, last)
class XML_Viwer(Frame):
def __init__(self, master, xml=None, **kwargs):
Frame.__init__(self, master, class_="XML_Viwer")
self._vsb = Scrollbar(self, orient=VERTICAL)
self._hsb = Scrollbar(self, orient=HORIZONTAL)
kwargs["yscrollcommand"] = lambda f, l: autoscroll(self._vsb, f, l)
kwargs["xscrollcommand"] = lambda f, l: autoscroll(self._hsb, f, l)
self._treeview = Treeview(self, **kwargs)
# Without this line, horizontal scrolling doesn't work properly.
self._treeview.column("#0", stretch= False)
self._vsb['command'] = self._treeview.yview
self._hsb['command'] = self._treeview.xview
self._treeview.grid(column=0, row=0, sticky=N+S+W+E)
self._vsb.grid(column=1, row=0, sticky=N+S)
self._hsb.grid(column=0, row=1, sticky=E+W)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
self._element_tree = None
if xml is not None:
self.parse_xml(xml)
def parse_xml(self, xml):
self._element_tree = ET.ElementTree(ET.fromstring(xml))
self.clear()
self._walk_xml(self._element_tree.getroot())
@property
def element_tree(self):
return self._element_tree
@element_tree.setter
def element_tree(self, element_tree):
self._element_tree = element_tree
self.clear()
self._walk_xml(element_tree.getroot())
def clear(self):
self._treeview.delete(*self._treeview.get_children())
def _walk_xml(self, node, depth=0, parent=""):
text = "<" + node.tag
attrs = node.attrib
# list function is here necessary to provide support to Python 3
a_names = list(attrs.keys())
a_names.sort()
for a_name in a_names:
text += ' %s="' % a_name
text += attrs[a_name]
text += '"'
text += ">"
item = self._treeview.insert(parent, END, text = text)
if node.text:
text = node.text.strip()
if text != "":
for line in text.splitlines():
self._treeview.insert(item, END, text = line)
child_nodes = sorted(list(node), key=attrgetter('tag'))
for child_node in node:
self._walk_xml(child_node, depth+1, parent=item)
if node.tail:
tail = node.tail.strip()
if tail != "":
for line in tail.splitlines():
self._treeview.insert(parent, END, text = line)
if __name__ == "__main__":
try:
from Tkinter import Tk
except ImportError:
from tkinter import Tk
root = Tk()
xml = """
<messages>
<note id="501">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
<note id="502">
<to>Jani</to>
<from>Tove</from>
<heading>Re: Reminder</heading>
<body>I will not</body>
</note>
</messages>"""
XML_Viwer(root, xml).pack()
root.mainloop()
Diff to Previous Revision
--- revision 1 2017-01-28 00:17:12
+++ revision 2 2017-01-28 00:23:25
@@ -80,7 +80,9 @@
text = "<" + node.tag
attrs = node.attrib
- a_names = attrs.keys()
+
+ # list function is here necessary to provide support to Python 3
+ a_names = list(attrs.keys())
a_names.sort()
for a_name in a_names:
@@ -106,7 +108,7 @@
tail = node.tail.strip()
if tail != "":
for line in tail.splitlines():
- self._treeview.insert(item, END, text = line)
+ self._treeview.insert(parent, END, text = line)
if __name__ == "__main__":
try: