1

I am very new one here, I am searching here for more than our, but I can not find answer.

I need to edit xml file using python. I have current structure:

<?xml version="1.0" encoding="windows-1250"?>
<MoneyData ICAgendy="46501401" KodAgendy="" HospRokOd="2016-01-01" HospRokDo="2016-12-31" description="všetky skladové doklady" ExpZkratka="_S" ExpDate="2016-05-19" ExpTime="00:01:00" VyberZaznamu="0"><SeznamDLPrij><DLPrij><CisloDokla>DLP16010</CisloDokla><KPFromOdb>0</KPFromOdb><Datum>2016-05-19</Datum><SouhrnDPH><Zaklad0>0</Zaklad0><Zaklad5>0</Zaklad5><Zaklad22>18.03</Zaklad22><DPH5>0</DPH5><DPH22>3.61</DPH22></SouhrnDPH><Celkem>21.64</Celkem><DRada>DLPrr</DRada><Vystavil>Filip Kotian</Vystavil><Nadpis>Dodací list</Nadpis><PorizCena>18.03</PorizCena><PopisX>Easy-Fix rám na hodváb 94 x 94 cm</PopisX><Fiskal>0</Fiskal><FisDoklad>0</FisDoklad><DatSkPoh>2016-05-19</DatSkPoh><SazbaDPH1>10</SazbaDPH1><SazbaDPH2>20</SazbaDPH2><DodOdb><ObchNazev>Čarovné farby s.r.o.</ObchNazev><ObchAdresa><Ulice>Montážna 15</Ulice><Misto>Prievidza</Misto><PSC>97104</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></ObchAdresa><FaktNazev>Čarovné farby s.r.o.</FaktNazev><FaktAdresa><Ulice>Montážna 15</Ulice><Misto>Prievidza</Misto><PSC>97104</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></FaktAdresa><ICO>50232240</ICO><DIC>SK2120235865</DIC><GUID>{FB837366-4B25-4E71-BB0E-856F60DDA187}</GUID><Nazev>Čarovné farby s.r.o.</Nazev><PlatceDPH>1</PlatceDPH><FyzOsoba>0</FyzOsoba><DICSK>2120235865</DICSK></DodOdb><DopravTuz>0</DopravTuz><DopravZahr>0</DopravZahr><Sleva>0</Sleva><Polozka><Nazev>Easy-Fix rám na hodváb 94 x 94 cm</Nazev><PocetMJ>1</PocetMJ><Cena>18.03</Cena><Valuty>0</Valuty><DPH>20</DPH><CenaTyp>0</CenaTyp><Sleva>0</Sleva><Vratka>0</Vratka><UcetMD>000000</UcetMD><UcetD>000000</UcetD><Hmotnost>0</Hmotnost><PorizCena>18.03</PorizCena><CenaPoSleve>1</CenaPoSleve><Sklad><Nazev>Pebeo</Nazev><KodSkladu>pebeo</KodSkladu><GUID>{786852E7-1ED4-4547-A941-C8F3320E726D}</GUID><CenikSklad>0</CenikSklad></Sklad><KmKarta><Popis>Easy-Fix rám na hodváb 94 x 94 cm</Popis><MJ>ks</MJ><GUID>{403D74BD-935B-4486-8A56-71272CB215CD}</GUID><Katalog>ASF1</Katalog><TypZarDoby>N</TypZarDoby><ZarDoba>0</ZarDoba><DesMist>0</DesMist><Obrazek>P:\ASF1.jpg</Obrazek><Hmotnost>0</Hmotnost><Objem>0</Objem><TypKarty>jednoducha</TypKarty></KmKarta></Polozka><MojeFirma><Nazev>creActive s.r.o.</Nazev><Adresa><Ulice>SNP 634/52</Ulice><Misto>Jalovec</Misto><PSC>97231</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></Adresa><ObchNazev>creActive s.r.o.</ObchNazev><ObchAdresa><Ulice>SNP 634/52</Ulice><Misto>Jalovec</Misto><PSC>97231</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></ObchAdresa><FaktNazev>creActive s.r.o.</FaktNazev><FaktAdresa><Ulice>SNP 634/52</Ulice><Misto>Jalovec</Misto><PSC>97231</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></FaktAdresa><Tel><Pred></Pred><Cislo></Cislo><Klap></Klap></Tel><Fax><Pred></Pred><Cislo></Cislo><Klap></Klap></Fax><Mobil><Pred></Pred><Cislo>0915818465</Cislo></Mobil><EMail>info@creactive.sk</EMail><WWW>www.creActive.sk</WWW><ICO>46501401</ICO><DIC>SK2023486278</DIC><DanIC>2023486278</DanIC><Banka>Fio banka, a.s., pobočka zahraničnej banky</Banka><Ucet>2500373646</Ucet><KodBanky>8330</KodBanky><KodPartn></KodPartn><FyzOsoba>0</FyzOsoba><MenaSymb>€</MenaSymb><MenaKod>EUR</MenaKod></MojeFirma></DLPrij></SeznamDLPrij></MoneyData>

I need to replace word DLPrij with DLVyd and save as new file.

Can anybody help me how to do it? I will need to run it then ask task schedule on my Synology NAS server.

I forgot to mention, the file will be located in folder: /volume1/Temp/DLPrij.xml and the output file should be named as DLVyd.xml in a same folder. Is it possible to include it in you help? :)

Thank you!

  • 1
    Possible duplicate of [How to update/modify a XML file in python?](http://stackoverflow.com/questions/1591579/how-to-update-modify-a-xml-file-in-python) – Serenity May 30 '16 at 21:54

1 Answers1

3

Just find the nodes and change tag:

from xml.etree import ElementTree as et

x="""<?xml version="1.0" encoding="windows-1250"?>
<MoneyData ICAgendy="46501401" KodAgendy="" HospRokOd="2016-01-01" HospRokDo="2016-12-31" description="všetky skladové doklady" ExpZkratka="_S" ExpDate="2016-05-19" ExpTime="00:01:00" VyberZaznamu="0"><SeznamDLPrij><DLPrij><CisloDokla>DLP16010</CisloDokla><KPFromOdb>0</KPFromOdb><Datum>2016-05-19</Datum><SouhrnDPH><Zaklad0>0</Zaklad0><Zaklad5>0</Zaklad5><Zaklad22>18.03</Zaklad22><DPH5>0</DPH5><DPH22>3.61</DPH22></SouhrnDPH><Celkem>21.64</Celkem><DRada>DLPrr</DRada><Vystavil>Filip Kotian</Vystavil><Nadpis>Dodací list</Nadpis><PorizCena>18.03</PorizCena><PopisX>Easy-Fix rám na hodváb 94 x 94 cm</PopisX><Fiskal>0</Fiskal><FisDoklad>0</FisDoklad><DatSkPoh>2016-05-19</DatSkPoh><SazbaDPH1>10</SazbaDPH1><SazbaDPH2>20</SazbaDPH2><DodOdb><ObchNazev>Čarovné farby s.r.o.</ObchNazev><ObchAdresa><Ulice>Montážna 15</Ulice><Misto>Prievidza</Misto><PSC>97104</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></ObchAdresa><FaktNazev>Čarovné farby s.r.o.</FaktNazev><FaktAdresa><Ulice>Montážna 15</Ulice><Misto>Prievidza</Misto><PSC>97104</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></FaktAdresa><ICO>50232240</ICO><DIC>SK2120235865</DIC><GUID>{FB837366-4B25-4E71-BB0E-856F60DDA187}</GUID><Nazev>Čarovné farby s.r.o.</Nazev><PlatceDPH>1</PlatceDPH><FyzOsoba>0</FyzOsoba><DICSK>2120235865</DICSK></DodOdb><DopravTuz>0</DopravTuz><DopravZahr>0</DopravZahr><Sleva>0</Sleva><Polozka><Nazev>Easy-Fix rám na hodváb 94 x 94 cm</Nazev><PocetMJ>1</PocetMJ><Cena>18.03</Cena><Valuty>0</Valuty><DPH>20</DPH><CenaTyp>0</CenaTyp><Sleva>0</Sleva><Vratka>0</Vratka><UcetMD>000000</UcetMD><UcetD>000000</UcetD><Hmotnost>0</Hmotnost><PorizCena>18.03</PorizCena><CenaPoSleve>1</CenaPoSleve><Sklad><Nazev>Pebeo</Nazev><KodSkladu>pebeo</KodSkladu><GUID>{786852E7-1ED4-4547-A941-C8F3320E726D}</GUID><CenikSklad>0</CenikSklad></Sklad><KmKarta><Popis>Easy-Fix rám na hodváb 94 x 94 cm</Popis><MJ>ks</MJ><GUID>{403D74BD-935B-4486-8A56-71272CB215CD}</GUID><Katalog>ASF1</Katalog><TypZarDoby>N</TypZarDoby><ZarDoba>0</ZarDoba><DesMist>0</DesMist><Obrazek>P:\ASF1.jpg</Obrazek><Hmotnost>0</Hmotnost><Objem>0</Objem><TypKarty>jednoducha</TypKarty></KmKarta></Polozka><MojeFirma><Nazev>creActive s.r.o.</Nazev><Adresa><Ulice>SNP 634/52</Ulice><Misto>Jalovec</Misto><PSC>97231</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></Adresa><ObchNazev>creActive s.r.o.</ObchNazev><ObchAdresa><Ulice>SNP 634/52</Ulice><Misto>Jalovec</Misto><PSC>97231</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></ObchAdresa><FaktNazev>creActive s.r.o.</FaktNazev><FaktAdresa><Ulice>SNP 634/52</Ulice><Misto>Jalovec</Misto><PSC>97231</PSC><Stat>Slovensko</Stat><KodStatu>SK</KodStatu></FaktAdresa><Tel><Pred></Pred><Cislo></Cislo><Klap></Klap></Tel><Fax><Pred></Pred><Cislo></Cislo><Klap></Klap></Fax><Mobil><Pred></Pred><Cislo>0915818465</Cislo></Mobil><EMail>info@creactive.sk</EMail><WWW>www.creActive.sk</WWW><ICO>46501401</ICO><DIC>SK2023486278</DIC><DanIC>2023486278</DanIC><Banka>Fio banka, a.s., pobočka zahraničnej banky</Banka><Ucet>2500373646</Ucet><KodBanky>8330</KodBanky><KodPartn></KodPartn><FyzOsoba>0</FyzOsoba><MenaSymb>€</MenaSymb><MenaKod>EUR</MenaKod></MojeFirma></DLPrij></SeznamDLPrij></MoneyData>"""


tree = et.fromstring(x)

for node in tree.findall(".//DLPrij"):
    node.tag = "DLVyd"

print et.tostring(tree)

So to parse from a file and create the new output file:

from xml.etree import ElementTree as et


tree = et.parse("/volume1/Temp/DLPrij.xml ")

for node in tree.findall(".//DLPrij"):
    node.tag = "DLVyd"
tree.write('/volume1/Temp/DLVyd.xml')

To add the encoding you just need to specify in write:

tree.write('/volume1/Temp/DLVyd.xml',encoding="windows-1250")

To change the node text for the KPFromOdb nodes if it is equal to 0:

for node in tree.findall(".//DLPrij"):
    node.tag = "DLVyd"
for node in tree.findall(".//KPFromOdb"):
    if node.text == "0":
        node.text = "1"

Then again just write:

tree.write('/volume1/Temp/DLVyd.xml',encoding="windows-1250")

If you plan on doing a lot of work with xml then lxml would be worth installing and using, xml has limited xpath support but lxml has comprehensive support and it is very efficient. The same code using lxml:

import lxml.etree as et
tree = et.parse("in.xml")

for node in tree.xpath("//DLPrij"):
    node.tag = "DLVyd"
for node in tree.xpath("//KPFromOdb[text()='0']"):
        node.text = "1"
tree.write("new.xml", encoding="windows-1250")
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Hi Padraic, Thank you for your answer. I forgot to mention, the file will be located in folder: /volume1/Temp/DLPrij.xml and the output file should be named as DLVyd.xml in a same folder. Is it possible to include it in you help? :) thank you! – Filip Kotian May 30 '16 at 21:58
  • Sure you could import and use ElementTree or even MiniDom but it would be faster and less memory intensive to use string mutation (not noticeable at this size). `xml_string.replace("DLPrij ", "DLVyd")` and the same with the closing tag. – TheLazyScripter May 30 '16 at 22:06
  • Works great! thank you. I only need to fix one thing, the program which creates xml uses and I need to add it on a first line and also use windows-1250 encoding, is it possible? – Filip Kotian May 30 '16 at 22:12
  • @TheLazyScripter, try that and see what happens. `"DLPrij "` would not actually replace anything, `"DLPrij"` would replace more than it should – Padraic Cunningham May 30 '16 at 22:13
  • Works great! Many thanks! I need to replace there some other words, so I will try to do it by myself, in case of any questions I will get back :) many thanks again. – Filip Kotian May 30 '16 at 22:24
  • No prob, you're welcome, once the names you want to replace are tags names then the logic will be exactly the same, any modifications to the tree will persist so once you have all the changes made it is simply a matter of writing to the file – Padraic Cunningham May 30 '16 at 22:25
  • Only one more thing I hope 0 I need to chage to 1 – Filip Kotian May 30 '16 at 22:56
  • Only if it is `0`? – Padraic Cunningham May 30 '16 at 22:58
  • Yes please, only 0 – Filip Kotian May 30 '16 at 23:00
  • @PadraicCunningham In the case that more than one tag contains the value you wish to replace then you would simply become more specific. `xml.read().replace('', '').replace('', '')` – TheLazyScripter May 30 '16 at 23:07
  • @TheLazyScripter, what happens if there is a stray space inside a tag? – Padraic Cunningham May 30 '16 at 23:08
  • @PadraicCunningham Then the same issue would occur with finding the tag in etree, minidom, and string mutation. – TheLazyScripter May 30 '16 at 23:11
  • @TheLazyScripter, nope, it wouldn't. There is a good reason people use xml parsers as there is for using html parsers over a regex. – Padraic Cunningham May 30 '16 at 23:11
  • @PadraicCunningham I found out that the value could be only 0 or 1 and I need to replace 0 with 1. Other way will not happen. – Filip Kotian May 30 '16 at 23:14
  • @PadraicCunningham Maybe you are correct, I could try and make an argument about using re but my original intention was simplicity, speed, and allocation so i'll agree with you. – TheLazyScripter May 30 '16 at 23:15
  • @PadraicCunningham thank you very much for your help. Everything works great. I have one more question, is it possible somehow to stop the script if output file already exist? I have scheduled the script to run every x minutes and it is alway overwriting the file. I would prefer if it can stop if output file already exist. If I delete it than it will be generated again :) Thank you! – Filip Kotian May 31 '16 at 00:09
  • Yes, there are a lot of ways but the simplest is probably `if os.path.exists("path_to_file"):...` either return if the code is in a function or sys.exit depending on how you have the code structured, that is subject to a race condition but probably not really an issue in your case – Padraic Cunningham May 31 '16 at 00:14
  • @PadraicCunningham thank you for your help. I currently have working script, but dont know how to end this condition at the beginning of script: import os if os.path.exists("/volume1/creActive/Prevod_skladu/Vydajka_CF.xml") – Filip Kotian May 31 '16 at 09:05
  • That should be the first thing you check for if you want the script to end if the file exists – Padraic Cunningham May 31 '16 at 10:11
  • But I dont know how the syntax works :( what should then follow? would it be possible for you to add it on the top code? many thanks – Filip Kotian May 31 '16 at 10:15