Find and Replace Values in Xml Using Python

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



Leave a reply



Submit