Source Code for DOMSORT.PY

#!/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()
python_dom_sort.txt · Last modified: 2007/03/27 03:10 by scott
chimeric.de = chi`s home Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0