Add XML element and save the file? - python

I'm pretty new to XML parsing with Python with minidom.
I have got this XML:
<filelist>
<file id="1.jpg"></file>
</filelist>
I would like to add and then save to the same file the following row for example:
<file id="2.jpg"></file>
I am doing the parsing using:
doc = minidom.parse('filelist.xml')
files = doc.getElementsByTagName('file')
for file in files:
idFile = file.getAttribute("id")
print(idFile)
How I can add that "element" and then save to same file?

Starting with your original code, the following additions were added to your code to accomplish adding an element and saving it back to the original file:
Create a new 'file' element
Set the new 'file' element 'id' attribute
Retrieve the document root ('filelist') node
Append the new 'file' element to the 'filelist' node
Write updated XML back to original file
See updated code following with comments to match this list of additions.
from xml.dom import minidom
doc = minidom.parse('filelist.xml')
# 1. Create a new 'file' element
new_file_element = doc.createElement('file')
# 2. Set the new 'file' element 'id' attribute
new_file_element.setAttribute('id', '2.jpg')
# 3. Retrieve the document root ('filelist') node
filelist_element = doc.documentElement
# 4. Append the new 'file' element to the 'filelist' node
filelist_element.appendChild(new_file_element)
files = doc.getElementsByTagName('file')
for file in files:
idFile = file.getAttribute('id')
print(idFile)
# 5. Write updated XML back to original file
with open('filelist.xml', 'w') as xml_file:
doc.writexml(xml_file, encoding='utf-8')

Related

Write edited xml that replaced hypen with underscore

So I am trying to write a new xml file that I edited from the original by replacing the hyphen with an underscore and then start working on that xml file for the rest of the code.
This is my code:
import xml.etree.ElementTree as ET
from lxml import etree
#attaching xml file
xmlfile = "hook_zap.xml"
tree = ET.parse(xmlfile)
root = tree.getroot()
#replace hypen with underscore within the xml
doc = etree.parse(xmlfile)
for e in doc.xpath('//*[contains(local-name(),"-")]'):
e.tag = e.tag.replace('-','_')
refracted = etree.tostring(doc, method='xml')
#create a new xml file with refracted file
refracted.write('base.xml')
#print (refracted)
And I keep getting this error:
AttributeError: 'bytes' object has no attribute 'write'
Write refracted like any other kind data into a file:
with open('base.xml', 'w') as f:
f.write(refracted.decode('utf-8'))

Why did I insert the element to a xml file without line splitter using python?

I am using python to deal with xml file, I need to insert one line to the xml file, and the code is like this:
xobj = ET.parse('/src/xxx.xml')
xroot = xobj.getroot()
filename = ET.Element("filename")
filename.text = xmlname
xroot.insert(0, filename)
tree = ET.ElementTree(xroot)
tree.write('/dst/xxx.xml')
It did insert one line of contents to the original xml file, but it was not a line. My xml file becomes:
<filename>004228.xml</filename><object>
....
</object>
There should be a \n between </filename> and <object>, but this method does not have that line spliter, how could I make the format look nice ?

How to write attributes from an xml file to a text file

I am using ElementTree to get the attributes and elements I need from an xml file. The xml file is queried from mySQL
I want to write out all the attributes and elements into a new text file using python
root = tree.getroot()
name = root.attrib['name']
country = root.find("country").text
I can see the results when I print them out
I want to write to a file the list of all the names and countries in the xml file
So if you generate an array with all your XML name's, you can use this few line of code to create/write a .txt file and write all names on a new line.
list_names = ["OLIVIA", "RUBY", "EMILY", "GRACE", "JESSICA"]
with open('listName.txt', 'w') as filehandle:
# filehandle.writelines("%s\n" % name for name in list_names)
filehandle.writelines("".join("{0}\n".format(name) for name in list_names))
As #Parfait suggested, here is a solution without % to concatenate string.
Source : https://stackabuse.com/reading-and-writing-lists-to-a-file-in-python/

Beautifulsoup xml

I am trying to use this code to add into an xml tree a simple info, which I have in a table. Each file has its id which I need to add into it. the corresp dictionary has file name and id couples. there is already an empty element in the xml, called idno[#type='TM'] in which I need to enter the corresponding id number.
from bs4 import BeautifulSoup
DIR = 'files/'
corresp = {"00100004":"362375", "00100005":"362376", "00100006":"362377", "00100007":"362378"}
for fileName, tm in corresp.iteritems():
soup = BeautifulSoup(open(DIR + fileName + ".xml"))
tmid = soup.find("idno", type="TM")
tmid.append(tm)
print soup
My first problem is that some time it works, some time it says
tmid.append(tm)
AttributeError: 'NoneType' object has no attribute 'append'
I have no idea why. yesterday evening I run the same sample code and now it complains in this way.
I have also tried etree
import xml.etree.ElementTree as ET
DIR = 'files/'
corresp = {"00100004":"362375", "00100005":"362376", "00100006":"362377", "00100007":"362378"}
for fileName, tm in corresp.iteritems():
f = open(DIR + fileName + ".xml")
tree = ET.parse(f)
tmid = tree.findall("//idno[#type='TM']")
tmid.append(tm)
tree.write('output.xml', encoding='utf-8', xml_declaration=True)
But it says "no element found: line 1, column 0"
My second, probably related problem is that when it did work, I was not able to write the output to a file. Ideally I would like to simply write it back to the file I am modifying.
Thank you very much for any advise on this.
For your first question:
find() just returns the result. If find() can’t find anything, it returns None. both result and None are not a python list, so it does not have append() method.
check the doc:
http://www.crummy.com/software/BeautifulSoup/bs4/doc/

Add tag to an XML file with Dom (minidom)

I want to add one tag to an XML file, do as follows:
xmlFile = parse(paths)
tag = xmlFile.createElement("tag")
print "creado elemento materias"
tag.setAttribute("tagname" , listaString)
xmlFile.childNodes[0].appendChild( tag)
xmlFile.toprettyxml()
My goal is to add a string.
The problem is that the code did not return errors but does not create the tag.
I have used as reference the question:
add element with attributes in minidom python
xmlFile.toprettyxml() returns the pretty xml as a string, it does not directly save the pretty xml to file. You would manually need to do the saving.
Example -
xmlFile = parse(paths)
tag = xmlFile.createElement("tag")
print "creado elemento materias"
tag.setAttribute("tagname" , listaString)
xmlFile.childNodes[0].appendChild( tag)
with open('<newpath to file>','w') as f:
f.write(xmlFile.toprettyxml())

Categories