Replacing files in a zip archive

Дамјан Георгиевски gdamjan at
Fri May 1 01:37:18 CEST 2009

> I'm writing a script that should modify ODF files. ODF files are just
> .zip archives with some .xml files, images etc.
> So far I open the zip file and play with the xml with lxml.etree, but
> I can't replace the files in it.
> Is there some recipe that does this ?

I ended writing this, pretty specific subclass of ZipFile.
I've added 3 methods, one for getting the .xml content from the document, the other for setting (notifying) back the 
changes, and the third to save a copy of the ZipFile to another file (or in memory/StringIO).

class ODFFile(ZipFile):
    def __init__(self, file, mode='r', compression=0, allowZip64=False):
        ZipFile.__init__(self, file, mode='r', compression=0, allowZip64=False)
        self.__unchanged = self.namelist()
        self.__updated = {}

    def get_xml(self, name):
        fp  ='%s.xml' % name)
        return lxml.etree.parse(fp)

    def set_xml(self, name, tree):
        name = '%s.xml' % name
        if name in self.__unchanged:
        if tree is not None:
            self.__updated[name] = tree

    def save_changes(self, fp=None):
        if fp is None:
            fp = StringIO()
        zo = ZipFile(fp, mode='w')
        updated = dict(self.__updated)
        for zinfo in self.infolist():
            name = zinfo.filename
            # just copy the unchanged
            if name in self.__unchanged:
            # write the changed in the same order
            elif name in updated:
                s = lxml.etree.tostring(updated.pop(name))
                zo.writestr(name, s)
        # append the possible remaining (new?)
        for name, tree in updated.items():
            s = lxml.etree.tostring(tree)
            zo.writestr(name, s)
        return fp

дамјан ( )

Religion ends and philosophy begins, 
just as alchemy ends and chemistry begins 
and astrology ends, and astronomy begins.

More information about the Python-list mailing list