1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
""" Traits UI tools for viewing the XML tree of SVG files.
"""
from enthought.traits.api import HasTraits, List, Property, Str
from enthought.traits.ui import api as tui
known_namespaces = {
'{http://www.w3.org/2000/svg}': 'svg',
'{http://www.w3.org/2000/02/svg/testsuite/description/}': 'testcase',
'{http://www.w3.org/1999/xlink}': 'xlink',
'{http://www.w3.org/XML/1998/namespace}': 'xml',
'{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}': 'sodipodi',
'{http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd}': 'sodipodi',
'{http://purl.org/dc/elements/1.1/}': 'dc',
'{http://web.resource.org/cc/}': 'cc',
'{http://www.w3.org/1999/02/22-rdf-syntax-ns#}': 'rdf',
'{http://www.inkscape.org/namespaces/inkscape}': 'inkscape',
'{http://ns.adobe.com/AdobeIllustrator/10.0/}': 'adobei',
'{http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/}': 'adobea',
'{http://ns.adobe.com/Graphs/1.0/}': 'graphs',
'{http://ns.adobe.com/Extensibility/1.0/}': 'adobex',
}
def normalize_name(name):
""" Normalize XML names to abbreviate namespaces.
"""
for ns in known_namespaces:
if name.startswith(ns):
name = '%s:%s' % (known_namespaces[ns], name[len(ns):])
return name
class Attribute(HasTraits):
""" View model for an XML attribute.
"""
name = Str()
value = Str()
label = Property()
def _get_label(self):
return '%s : %s' % (normalize_name(self.name), self.value)
class Element(HasTraits):
""" View model for an XML element.
"""
tag = Str()
children = List()
attributes = List(Attribute)
text = Str()
label = Property()
kids = Property()
def _get_label(self):
return normalize_name(self.tag)
def _get_kids(self):
kids = self.children + self.attributes
if self.text:
kids.append(Attribute(value=self.text))
return kids
def xml_to_tree(root):
""" Convert an ElementTree Element to the view models for viewing in the
TreeEditor.
"""
element = Element(tag=root.tag)
if root.text is not None:
element.text = root.text.strip()
for name in sorted(root.keys()):
element.attributes.append(Attribute(name=name, value=root.get(name)))
for child in root:
element.children.append(xml_to_tree(child))
return element
xml_tree_editor = tui.TreeEditor(
nodes = [
tui.TreeNode(
node_for = [Element],
children = 'kids',
label = 'label',
menu = False,
),
tui.TreeNode(
node_for = [Attribute],
children = '',
label = 'label',
menu = False,
)
],
editable = False,
show_icons = False,
)
class XMLTree(tui.ModelView):
""" Handler for viewing XML trees.
"""
traits_view = tui.View(
tui.Item('model', editor=xml_tree_editor, show_label=False),
width=1024,
height=768,
resizable=True,
)
@classmethod
def fromxml(cls, root, **traits):
return cls(model=xml_to_tree(root), **traits)
def main():
from xml.etree import cElementTree as ET
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('file')
args = parser.parse_args()
xml = ET.parse(args.file).getroot()
t = XMLTree.fromxml(xml)
t.configure_traits()
if __name__ == '__main__':
main()
|