#!/usr/bin/env python import sys import os import EasyDialogs as mac def SortIMoviePList(fileName,DEBUG=0): """SortIMoviePList: This function opens an iMovie xml file (a plist file) and looks for video clips in the trash. It then sorts these clips and returns the xmldoc. The main module should dump this document to a file OR just send it to stdout to be trapped. fileName = name of file to sort. DEBUG: 1 - print messages as we look for things to sort. 0 - don't print anything, just work. """ from xml.dom import minidom # need to add command line parsing but for now just roll with it. sock = open(fileName) xmldoc = minidom.parse(sock) sock.close() #now the xmldoc contains the parsed document in Document Object Model Format xArrayList = xmldoc.getElementsByTagName('array') # list of array tags # okay only grab the FIRST array that has children. To handle multiple arrays # just turn this into a loop to go through all the non-empty arrays sortRoot = ([a for a in xArrayList if a.childNodes])[0] #Sanity Check - only sort stuff in the trash rootKey = sortRoot.previousSibling if rootKey.nodeType == 3: #it's an empty text node rootKey = rootKey.previousSibling if rootKey.firstChild.data != u'videoTrashClips': print 'We found the wrong node!' print rootKey.toxml() return None # okay if we get here we have the array for the videoTrashClips # now find the slots we will replace slots = [ s for s in range(len(sortRoot.childNodes)) if sortRoot.childNodes[s].nodeType == 1] dlist = [ d for d in sortRoot.childNodes if d.nodeType == 1] # now find the names to sort on dtList = [] # empty list of tuples pb = mac.ProgressBar(title='Finding Nodes',maxval=len(dlist)) for d in dlist: # for every dict in the array pb.inc(1) pb.label(str(d)) for k in d.childNodes: # and for every child, in that dict if k.nodeName == 'key': # see if the child is a 'key' if k.firstChild.data == u'name': # and if the key is 'name' then... # we found the name - now go to next child node and get the data v = k.nextSibling if v.nodeType == 3: v = v.nextSibling # skip dumb/empty children. should this be a loop? if DEBUG: print v.firstChild.data # <--- this is the name! dtList = dtList + [(v.firstChild.data, d,d.previousSibling,d.nextSibling)] del pb # The list of nodes we want, and the names of those nodes are now in dtList if DEBUG: for t in dtList: print t print "="*10, "Sort Them", "="*10 # Sort the list of dict's by name! dtList.sort() if DEBUG: for t in dtList: print t #Now put the lists back into the tree # the trick here of course is that we also have to patch up all the pointers # note - do I have to preserve the pointers of the "sorted sibling"? # it's very possible I do. Otherwise, those pointers get lost. # perhaps what I really have to do is SWAP the objects preserving their pointers. # or SAVE them in a larger tuple before they get lost. for i in range(len(dtList)): exchNode = sortRoot.childNodes[slots[i]] # get the current node #Note: This node's pointers may be invalid because we've started moving #things around (at some moment in time there may be TWO references to a node # and when you replace the second reference it's pointers will be updated as if # it's in the first position. So use the references we archived when we built # the tuple list. # # next part is a tad tricky - go through the entire list looking for a tuple # with ONE element true. Not sure of a quick way to do this without a loop, # but using filtering and list assignment to get the stuff we want. # because this list iterator always returns a list, we dereference it to # the first item to get our multi-var assignment. (name, node, prev,next) = [(n1,n2,n3,n4) for (n1,n2,n3,n4) in \ dtList if n2 == exchNode][0] sortedNode = dtList[i][1] # now get the sorted node sortedNode.previousSibling = prev # set it's pointers accordingly sortedNode.nextSibling= next # make sure it points to the right things prev.nextSibling = sortedNode # set up siblings next.previousSibling = sortedNode sortRoot.childNodes[slots[i]] = sortedNode # finally swap it out. if DEBUG: print "="*10,"Sorted Items","="*10 if DEBUG: print xmldoc.toxml() return xmldoc def main(): fileName = mac.AskFileForOpen(message="File to Sort") if fileName: doc = SortIMoviePList(fileName) if doc: (pathStr,fileStr) = os.path.split(fileName) fileName = mac.AskFileForSave(message="Save Sorted File", savedFileName=fileStr,defaultLocation=pathStr) if fileName: f = open(fileName,'w') print doc.writexml(f) if __name__=="__main__": main()