Donnerstag, 4. Juli 2013

 

XML Datei aus einer ZIP-Datei mit Python ändern und wieder zurückschreiben (Hack für Probleme mit K3B und diversen MP3-Playern)

Der Titel sagt's bereits. Dieses kleine Script ändert den Inhalt einer XML-Datei in einer ZIP-Datei. Konkret handelt es sich um eine Projektdatei des Linux-Brennprogrammes k3b. Ich erstelle damit CDs für's Autoradio mit MP3s. Allerdings enthält die CD die Dateien in alphabetischer Reihenfolge und das Autoradio spielt das in der Reihenfolge ab. Ich habe keinen anderen Weg gefunden, als die Dateinamen entsprechend zu ändern. Das ist natürlich in einer grafischen Oberfläche mühsam.

Mit k3b erzeuge ich ein neues Projekt, in dem ich die Songs in der Reihenfolge, die ich haben will hinzufüge. Dann speichere ich das Projekt und lasse die Dateinamen durch das Script in der Projektdatei ändern. Dann lade ich das Projekt und brenne die CD. Die Lieder sind dann in der richtigen Reihenfolge, weil die Namen mit einer Nummer wie hier 001 - Lied.mp3 versehen werden.

#!/usr/bin/env python
"""
change entries so that they are sorted by name used with k3b-data CDs (mp3
CDs).

Procedure:
    1. make k3p project and add files.
    2. save this project
    3. close the project (leave k3b open)
    4. run this script: numbermymp3.py your_project_name.k3p
    4. load the project again.
    5. as you can see, the files ar starting with 3-digit numbers preserving
       the original order when adding the files.

2013-07-04, Harald R. Haberstroh
"""
import sys
import codecs
import zipfile
from xml.dom import minidom

def getfiles(zipfilename):
    """get dictionary filename:data with all files in zipfile"""
    zf = zipfile.ZipFile(zipfilename)
    files = {}
    for info in zf.infolist():
        files[info.filename] = zf.read(info.filename)
    return files

def process(xmlstr):
    """process xml with file entries and change 'name' attribute according
    to number of file (starting with 001)."""
    xmldoc = minidom.parseString(xmlstr)
    names = xmldoc.getElementsByTagName('file')
    num = 1
    for name in names:
        numstr = "%03d" % num
        name.attributes['name'].value = numstr + ' - ' + \
                name.attributes['name'].value
        num += 1
    return xmldoc.toprettyxml().encode('utf-8')

def genzipfile(zipfilename, files):
    """generate new zipfile (k3b-file) with dict 'files' which has file name as
    key and the content as data"""
    zf = zipfile.ZipFile(zipfilename, mode='w')
    try:
        for name in files:
            zf.writestr(name, files[name])
    finally:
        zf.close()

def main():
    """all to gether now"""
    if len(sys.argv) != 2:
        print "usage: " + sys.argv[0] + " k3b_project_name.k3b"
        print "renames files so that the order is the same as in the project"
        sys.exit(1)
    fname = sys.argv[1]
    files = getfiles(fname)
    text = process(files['maindata.xml'])
    files['maindata.xml'] = text
    genzipfile(fname, files)

if __name__ == '__main__':
    main()

Labels: ,


Kommentare:

Kommentar veröffentlichen

Abonnieren Kommentare zum Post [Atom]





<< Startseite

This page is powered by Blogger. Isn't yours?

Abonnieren Posts [Atom]