#!/usr/bin/python2

from simplexml import *
import sys
from locale import getpreferredencoding

def help():
	print '''simplexml - command line xml navigation - Ales Smrcka (smrcka@sendmail.cz)
Syntax: simplexml Command Path filename.xml
Command can be:
	-v             - print data of found element(s)
        -v value       - set new very stripped data of found element(s)
        -s             - print very stripped data of found element(s)
        -a name        - print attribute value of found element(s)
        -a name=value,name2=value2 - set new values of attributes of found
                         element(s)
        -d name        - remove attribute
        -c             - print count of matched elements
        -n name        - new element child to matched element (must be
                         only one matched element)
        -r             - remove matched elements
        -e             - extract XML of elements and print them to stdout
        -z name        - create new root element - whole document will be
                         deleted, use this without path definition
Path:
        Path to element(s) are element names separated by / and followed by
        optional definition of attributes (attrname1=value1,attrname2=value2)
        and/or index of elements [index] and/or regual expression for very
        stripped data of element {regexp}. Optional definition of attributes,
        element index or data (content) definition can follow every element
        name. Path results to list of elements corresponding to the path
        definition.
        You can also use '..' as name of element to define parent node.
        Path examples:
          1. path/to/element
          2. path/to(author=Ales Smrcka)/element
          3. path/to(author=Ales Smrcka)[2]/element
          4. customers/customer(sex=male)/birth{\d+\.\d+\.1980}/../mtime
	     meaning: Select 'mtime' element as child element for element
               'customer' with attribute 'sex' as 'male' and with value of
               child element 'birth' matching regular expression for year 1980.
               See example file customer.xml for tree of elements...
        If you want to define character '}' in regular expression of stripped
        data, simply use '\}' combination.
	Very stripped data is content of element with no space characters at
        the beginning and at the end and multiple space characters inside
        content is translated into one space ' '.
Examples:
        Create new root element "mycustomers":
          simplexml -z mycustomers customers.xml
        Create new customer element:
          simplexml -n customer mycustomers customers.xml
        Set new customer name:
          simplexml -a "name=George Smith" "customers/customer(name=John Smith)" customers.xml
        Print birth day of customer John Smith (data of element birth)
          simplexml -v "customers/customer(name=John Smith)/birth" customers.xml
        Set new modification time of the third customer (data of element mtime)
          simplexml -v "2005-08-15 12:00" customers/customer[2]/mtime customers.xml
        Print all customer names (attribute name)
          simplexml -a name customers/customer customers.xml          
'''
	sys.exit(1)

def xmlopen(filename):
	try:
		return xmldoc(filename)
	except:
		print 'simplexml: Could not open file %s' % filename
		sys.exit(2)

def main():
	argc = len(sys.argv)
	if argc<2: help()
	enc = getpreferredencoding()
	for i in range(len(sys.argv)):
		sys.argv[i] = sys.argv[i].decode(enc)
	if sys.argv[1] == '-c':
		# print count of matched elements
		# -c path filename
		if argc<4: help()
		d = xmlopen(sys.argv[3])
		print len(d.elements(sys.argv[2]))
	elif sys.argv[1] == '-e':
		# print XML form of matched elements
		# -e path filename
		if argc<4: help()
		d = xmlopen(sys.argv[3])
		for element in d.elements(sys.argv[2]):
			print element.toxml()
	elif sys.argv[1] == '-s':
		# print value of elements
		# -s path filename
		if argc<4: help()
		d = xmlopen(sys.argv[3])
		for element in d.elements(sys.argv[2]):
			print element.value
	elif sys.argv[1] == '-v':
		# print or set data of elements
		# -v [value] path filename
		if argc<4: help()
		elif argc==4:
			# -v path filename
			d = xmlopen(sys.argv[3])
			for element in d.elements(sys.argv[2]):
				print element.data
		else:
			# -v value path filename
			d = xmlopen(sys.argv[4])
			for element in d.elements(sys.argv[3]):
				element.value = sys.argv[2]
			d.save()
	elif sys.argv[1] == '-r':
		# remove matched elements
		# -r path filename
		if argc<4: help()
		d = xmlopen(sys.argv[3])
		for element in d.elements(sys.argv[2]):
			element.remove()
		d.save()
	elif sys.argv[1] == '-n':
		# create new child to just one matched element
		# -n name path filename
		if argc<5: help()
		d = xmlopen(sys.argv[4])
		matched = d.elements(sys.argv[3])
		if len(matched)>1:
			print 'Path must match just one element'
			return 1
		elif len(matched)==0:
			print 'Path must match at least one element'
			return 1
		matched[0].newchild(sys.argv[2])
		d.save()
	elif sys.argv[1] == '-z':
		# create new root element
		# -z name filename
		if argc<4: help()
		try:
			d = xmldoc(sys.argv[3])
		except:
			d = xmldoc()
		d.new_root(sys.argv[2])
		d.save(sys.argv[3])
	elif sys.argv[1] == '-a':
		# print or set attribute of elements
		# -a attrname[=value] path filename
		if argc<5: help()
		d = xmlopen(sys.argv[4])
		aset=[]
		for adef in sys.argv[2].split(','):
			adef = adef.split('=')
			if len(adef)==2:
				aset.append(adef)
		if aset:
			# set attributes
			for element in d.elements(sys.argv[3]):
				for a in aset:
					element.attr(a[0], a[1])
			d.save()
		else:
			# print attribute
			for element in d.elements(sys.argv[3]):
				print element.attr(sys.argv[2])
	elif sys.argv[1] == '-d':
		# remove attribute from all found elements
		# -d name path filename
		if argc<5: help()
		d = xmlopen(sys.argv[4])
		for element in d.elements(sys.argv[3]):
			element.removeattr(sys.argv[2])
		d.save()
	return 0

if __name__ == "__main__":
	sys.exit(main())
