W praktyce korporacyjnej bardzo częstym problemem jest sporządzanie raportu na podstawie otrzymanych danych. Problemem jest to, że dane te - niestety - nie są najczęściej przesłane nam w formacie, który by ułatwiał to zadanie i nie mamy na to żadnego wpływu.
Typowym przykładem może być sytuacja następująca. Trzeba sporządzić sprawozdanie, plan, czy coś innego w tym rodzaju. W tym celu koordynator projektu rozsyła do wszystkich komórek jakiś formularz, który jest zwykłym plikiem, na nieszczęście jeszcze w formacie M$ Worda, który komórki te mają odesłać wypełniony.
Tekst w pliku ma strukturę pytanie - odpowiedź, np:
1. Nazwa przedsięwzięcia
.......................................................
2. Podaj budżet przedsięwzięcia bla bla bla
...........................................................
3. Zasoby konieczne do realizacji
.........................................................
4. Termin rozpoczęcia
..........................................................
5. Termin zakończenia
etc, etc.
I teraz szef mówi, że trzeba z nadesłanych odpowiedzi zrobić tabelę. Jeśli w każdym pliku pytań jest kilkanaście, a plików setki albo dziesiątki, to zwykłe "kopiuj - wklej" do Excela, jako rozwiązanie problemu zdecydowanie odpada. Trzeba do tego podejść systemowo.
W moim przypadku było jeszcze gorzej, bo pliki były w różnych formatach. Część w "doc", a część w "odt", czyli format Open Document. Postanowiłem zaprząc do pracy pythona, a pierwszą rzeczą było skonwertowanie wszystkiego na format Open Document. Wrzuciłem wszystkie pliki "doc" do jednego katalogu o nazwie doc. Wynalazłem (google) taki przepis na konwersję: http://www.artofsolving.com/files/DocumentConverter.py. Wymaga on uruchomienia OpenOffice jako serwisu. Na szczęście jest to banalne, wystarczy w linii poleceń wpisać soffice -accept="socket,port=8100;urp;" (działa to pod linuksem, ale pod windowsem powinno być podobnie).
Potem wystarczy wykonanie następującego skryptu powłoki (bash):
#!/bin/bash licznik=1 for nazwa in doc/* do python DocumentConverter.py $nazwa odt/plan_$licznik.odt let licznik=licznik+1 done
#!/usr/bin/env python import zipfile, re rx_stripxml = re.compile("<[^>]*?>", re.DOTALL|re.MULTILINE) def convert_OO(filename): zf=zipfile.ZipFile(filename, "r") data = zf.read("content.xml") zf.close() data = " ".join(rx_stripxml.sub(" ", data).split()) return data if __name__=="__main__": import sys if len(sys.argv) > 1: for docname in sys.argv[1:]: print convert_OO(docname) else: print 'nalezy podac pliki do skonwersowania jako argumenty'
#!/bin/bash licznik=1 for nazwa in odt/* do echo "<item>" >> raport.xml python odt2txt.py $nazwa >> raport.xml echo "</item>" >> raport.xml let licznik=licznik+1 done
W ten sposób powstał jeden plik tekstowy, który będziemy dalej przekształcać, żeby stał się plikiem xml. Poszczególne dokumenty powinny już być zawarte w znacznikach
Teraz wystarczy pozamieniać teksty typu "1. Nazwa przedsięwzięcia" na znaczniki xml. Robimy to za pomocą programu:
# -*- coding:utf-8 -*- #!/usr/bin/env python import codecs, sys zrodlo = codecs.open('raport.xml', 'r', 'utf-8') cel = codecs.open('raport1.xml', 'w','utf-8') zmiany={ u'1. Nazwa przedsięwzięcia':u'<nazwa_przedsiewziecia>', u'2. Podaj budżet przedsięwzięcia bla bla bla':u'</nazwa_przedsiewziecia><budzet_przedsiewziecia>', # i tak dalej aż do końca } for s in zrodlo: for zmiana in zmiany.keys(): s = s.replace(zmiana, zmiany[zmiana]) print(s) cel.write(s) cel.close()
I to w zasadzie wszystko. Teoria jednak w tym miejscu nieco się z praktyką rozmija, bo autorzy plików mają bardzo różne pomysły, które powodują, że plik xml trzeba bedzie zapewne w kilku miejscach poprawić ręcznie. Pomoże nam w tym zapewne parser xml.
Kiedy już utworzymy poprawny plik xml, możemy z nim zrobić w zasadzie wszystko :)