#!/usr/bin/python
# A pretty-printer for VOTables incuded in the stc-votable note
# It only selects TABLE, GROUP, PARAM, FIELDrefs and FIELD elements, indents
# and line breaks the mess, and rearranges the attributes.  No character
# data is handled.
#
# This really is a quick hack for this special application.  Generalizing
# it to anything useful would be more work than staring afresh with a more
# general tool.

import re
import sys
import textwrap
from xml import sax
from xml.sax.handler import ContentHandler


class WhitespaceTextWrapper(textwrap.TextWrapper):
	wordsep_re = re.compile(r"(\s)\s*")


def fill(text, width=70, **kwargs):
	w = WhitespaceTextWrapper(width=width, **kwargs)
	return w.fill(text)


class PrettyPrinter(ContentHandler):
	curIndent = ""
	cleanupPat=re.compile(".*:")  # namespaces nuked here

	handledElements = {
		"TABLE": ('ID', 'name'),
		"GROUP": ('ID', 'utype'),
		"PARAM": ('ID', 'name', 'datatype', 'arraysize', 'utype', 'value'),
		"FIELDref": ('ref', 'utype'),
		"FIELD": ('ID', 'name', 'datatype', 'xtype', 'arraysize', 
			'utype', 'value'),
	}

	def __init__(self):
		self.toOpen = None

	def _formatOpener(self, indent, name, attrs, empty=False):
		attrs = dict(attrs)
		parts = [name]
		for attName in self.handledElements[name]:
			if attName in attrs:
				parts.append('%s="%s"'%(attName, attrs[attName]))
		if empty:
			text = "<%s/>"%" ".join(parts)
		else:
			text = "<%s>"%" ".join(parts)
		print fill(text, initial_indent=indent,
			subsequent_indent="  "+indent)

	def startElement(self, name, attrs):
		if name not in self.handledElements:
			return
		name = self.cleanupPat.sub("", name)
		if self.toOpen:
			self._formatOpener(*self.toOpen)
			self.toOpen = None
		self.toOpen = (self.curIndent, name, attrs)
		self.curIndent = self.curIndent+"  "
	
	def endElement(self, name):
		name = self.cleanupPat.sub("", name)
		if name not in self.handledElements:
			return
		self.curIndent = self.curIndent[:-2]
		if self.toOpen:
			self._formatOpener(empty=True, *self.toOpen)
			self.toOpen = None
		else:
			print self.curIndent+"</%s>"%name


def main():
	sax.parse(sys.stdin, PrettyPrinter())

if __name__=="__main__":
	main()
