Find and Replace Values in XML using Python
The basics:
from xml.etree import ElementTree as et
tree = et.parse(datafile)
tree.find('idinfo/timeperd/timeinfo/rngdates/begdate').text = '1/1/2011'
tree.find('idinfo/timeperd/timeinfo/rngdates/enddate').text = '1/1/2011'
tree.write(datafile)
You can shorten the path if the tag name is unique. This syntax finds the first node at any depth level in the tree.
tree.find('.//begdate').text = '1/1/2011'
tree.find('.//enddate').text = '1/1/2011'
Also, read the documentation, esp. the XPath support for locating nodes.
How to find, read and replace a value in XML file with Python
I found the solution, I only had to first read the value, turn it in an integer, add 1 and replace the value turning it again into a string:
import xml.etree.ElementTree as ET
tree = ET.parse('test.xml')
root = tree.getroot()
newTimes = int(root[0][7].text) + 1
root[1][6].text = str(newTimes)
tree.write('test.xml')
That's all.
How to search and replace text in an XML file using Python?
Caveats:
- I have never worked with the
xml.etree.ElementTree
library - I have never worked with it because I never find myself manipulating XML
- I don't know if this is the "best" way compared to someone that knows the library in and out
- Commentors seem set on judging you instead of helping you out
This is a modification from this excellent answer. The thing is, you need to read the XML file in and parse it.
import xml.etree.ElementTree as ET
with open('xmlfile.xml', encoding='latin-1') as f:
tree = ET.parse(f)
root = tree.getroot()
for elem in root.getiterator():
try:
elem.text = elem.text.replace('FEATURE NAME', 'THIS WORKED')
elem.text = elem.text.replace('FEATURE NUMBER', '123456')
except AttributeError:
pass
tree.write('output.xml', encoding='latin-1')
Note that you can change the encoding
parameter to something else such as: utf-8
, cp1252
, ISO-8859-1
, etc. Really depends on your system and file.
Find an replace in xml file using python
If you want to replace occurrences, why don't you just treat it as string?
with open('/usr/src/sample3.xml') as f:
xml_str = f.read()
xml_str = xml_str.replace('10.10.10.75', '10.10.10.100')
with open('/usr/src/sample3.xml', "w") as f:
f.write(xml_str)
replace string in XML file python
If you want to replace ALL occurrences of "bicycle" it can be easily done with 'replace':
input_file = "example.xml"
output_file = "output.xml"
with open(input_file) as f:
xml_content = f.readlines()
with open(output_file, 'w+') as f:
for line in xml_content:
f.write(line.replace('bicycle', 'bike'))
However, if you want to keep the structure of your xml intact (in case an element or attribute name would be bicycle) you might wanna take a look at elementTree or lxml.
Edit: after the edit of your question here a cleaner solution with elementTree:
import xml.etree.ElementTree as ET
input_file = "example.xml"
output_file = "output.xml"
tree = ET.parse(input_file)
root = tree.getroot()
name_elts = root.findall(".//name") # we find all 'name' elements
for elt in name_elts:
elt.text = elt.text.replace("bicycle", "bike")
tree.write(output_file)
replace xml values with python
You have several problems. The element you are looking for has a namespace inherited from the default namespace in <OrdSet xmlns="..."
and that needs to be included in the find. Then, findall
only looks at children unless you add ElementTree's "pseudo-xsl" subtree search pattern. And finally, you need to change the text
attribute, not `txt.
Abbreviated XML for test...
<?xml version="1.0" encoding="UTF-8"?>
<OrdSet xmlns="tfs">
<Msg>
<MsgCreate>
<ActnCode>NEW</ActnCode>
<SrcID>64698602107101</SrcID>
<RepCode>0000</RepCode>
<OrdDtl>
<AcctLookup>
<MgmtCode>ABC</MgmtCode>
<FundAcctID>984575</FundAcctID>
<AcctDesig>2</AcctDesig>
</AcctLookup>
</OrdDtl>
</MsgCreate>
</Msg>
</OrdSet>
And your code becomes
import xml.etree.ElementTree as ET
tree = ET.parse("input.xml")
root = tree.getroot()
elems = tree.findall('.//{http://abc}ActnCode')
print('elems', elems)
for elem in elems:
elem.text = 'CAN'
tree.write("output.xml")
EDIT
You can do more complicated XPATH queries with lxml
than with ElementTree
. If you want to limit which <ActnCode>
elements you process, this predicate will look at other elements to refine the selection. The stuff inside the angle brackets is essentially a filter that will remove non-matching nodes. Here I limit to nodes with a sibling OrdDtl/AcctLookup/FundAcctID of 984575
import lxml.etree
tree = lxml.etree.parse('input.xml')
elems = tree.xpath('//tfs:ActnCode[../tfs:OrdDtl/tfs:AcctLookup/tfs:FundAcctID/text()="984575"]',
namespaces={'tfs':'tfs'})
elems2 = tree.xpath('.//tfs:ActnCode[../tfs:OrdDtl]',
namespaces={'tfs':'tfs'})
print('elems', elems)
for elem in elems:
elem.text = 'CAN'
tree.write("output.xml")
Find and replace specific text within an attribute in XML using Python
I know this might be oversimplifying the problem, but wouldn't it be easier to just:
with open(filepath, 'r') as f:
res = f.read().replace('http://stag', 'http://prod')
with open(filepath,'w') as f:
f.write(res)
If you insist on parsing it as XML, you can do the following:
import xml.etree.ElementTree as ET
with open(filepath, 'r') as f:
tree = ET.parse(f)
for n in tree.findall(".//"):
for a in n.attrib:
n.attrib[a] = n.attrib[a].replace("stag", "prod")
with open(filepath, 'w') as f:
tree.write(f)
Find and Replace XML Attributes by Indexing - Python
Consider elementwise loop, zip
, on list of your needed values and iterfind
generator. Run a nested loop for aligning sets of elements and values. Also there is no need to check if elem.text
since every XML element has an underlying text node (empty or not). And if entire string contains text
simply assign rather than replace
. Do note: zip
stops elementwise looping on shorter list:
# LIST OF VALUES
new_vals = [float(100/202), float(200/500), float(4/44), float(4/1000)]
# SUBLIST OF VALUES BY 2 (ADJUST 2 FOR ANY OTHER NUMBER)
sub_new_vals = [new_vals[i:i+2] for i in range(0, len(new_vals), 2)]
for nvs, el in zip(sub_new_vals, tree.iterfind('./*')):
# Find and replace first and second attribute values
for nv, elem in zip(nvs, el.iterfind('./*')):
#elem.attrib["key"] = str(round(nv, 3)) # UPDATE ATTRIBUTE VALUE
elem.text = str(round(nv, 3)) # UPDATE ELEMENT TEXT
print(elem.text)
output = ET.tostring(tree,
encoding="UTF-8",
method="xml",
xml_declaration=True,
pretty_print=True)
print(output.decode("utf-8"))
Output
0.495
0.4
0.091
0.004
<?xml version='1.0' encoding='UTF-8'?>
<Overlay>
<foo_1>
<bar key="value">0.495</bar>
<bar key="value">0.4</bar>
<bar key="value">text_3</bar>
</foo_1>
<foo_2>
<bar key="value">0.091</bar>
<bar key="value">0.004</bar>
<bar key="value">text_6</bar>
</foo_2>
</Overlay>
Replace values in XML file with values of a vector using python
Try it this way:
from lxml import etree
doc = etree.fromstring(model)
v = [7, 8, 9]
targets = doc.xpath('//Model/Function/param[.="type"]')
for target in targets:
chn = target.xpath('following-sibling::*[1]')[0]
chn.text = str(v.pop(0))
print(etree.tostring(doc).decode())
Output:
<Model>
<Function>
<param>x</param>
<param>type</param>
<param>7</param>
<param>5</param>
</Function>
<Function>
<param>y</param>
<param>type</param>
<param>8</param>
<param>2</param>
</Function>
<Function>
<param>z</param>
<param>type</param>
<param>9</param>
<param>9</param>
</Function>
</Model>
Related Topics
How to Compare Dates in Django Templates
Can You Give a Django App a Verbose Name for Use Throughout the Admin
Python Regular Expression Re.Match, Why This Code Does Not Work
Saving Upload in Flask Only Saves to Project Root
How to Re Import an Updated Package While in Python Interpreter
Error Running Basic Tensorflow Example
Replace Nth Occurrence of Substring in String
Truncate to Three Decimals in Python
Why Can't Environmental Variables Set in Python Persist
Calculating Pearson Correlation and Significance in Python
Python "Extend" for a Dictionary
Differencebetween an Opencv Bgr Image and Its Reverse Version Rgb Image[:,:,::-1]
Python Progression Path - from Apprentice to Guru