Reputation: 133
I am working on a python program for keeping an inventory of a storage room. In a XML-document the amount of toners will be kept and I want my python program to be able to add, remove and display the amount of toners for different printers and different colors.
My XML looks like this:
<?xml version="1.0"?>
<printer>
<t id="095205615111"> <!-- 7545 Magenta -->
<toner>7545 Magenta Toner</toner>
<amount>3</amount>
</t>
<t id="095205615104"> <!-- 7545 Yellow -->
<toner>7545 Yellow Toner</toner>
<amount>7</amount>
</t>
</printer>
The id is the number from the barcode that we use for inventory.
So far I have these steps that I would like my program to use:
Check if the id exist (the id-value is a variable in my python program piped from the content in a txt-file)
Change the value of amount in the xml-document to +1 or -1
Whatever I try it never works fully. Do you have any suggestions of what I could use?
Upvotes: 3
Views: 18233
Reputation: 473753
You can also approach it with lxml.objectify
which would make handling the data types easier:
from lxml import objectify, etree
data = """<?xml version="1.0"?>
<printer>
<t id="095205615111"> <!-- 7545 Magenta -->
<toner>7545 Magenta Toner</toner>
<amount>3</amount>
</t>
<t id="095205615104"> <!-- 7545 Yellow -->
<toner>7545 Yellow Toner</toner>
<amount>7</amount>
</t>
</printer>"""
root = objectify.fromstring(data)
toner_id = "095205615111"
# find a toner
results = root.xpath("//t[@id = '%s']" % toner_id)
if not results:
raise Exception("Toner does not exist")
toner = results[0]
# change the amount
toner.amount += 1
# dump the tree object back to XML string
objectify.deannotate(root)
etree.cleanup_namespaces(root)
print(etree.tostring(root))
Note, how the amount change is implemented:
toner.amount += 1
Upvotes: 4
Reputation: 473753
Check if the id exist
You can solve this by constructing an XPath expression checking the @id
attribute value.
Change the value of amount in the xml-document to +1 or -1
Once you locate the t
node by a specific id
, you can use find()
to locate the inner amount
node. Then, you can get the .text
, convert it into an integer, change it, convert back to string and set the .text
property.
The working example:
from lxml import etree
data = """<?xml version="1.0"?>
<printer>
<t id="095205615111"> <!-- 7545 Magenta -->
<toner>7545 Magenta Toner</toner>
<amount>3</amount>
</t>
<t id="095205615104"> <!-- 7545 Yellow -->
<toner>7545 Yellow Toner</toner>
<amount>7</amount>
</t>
</printer>"""
root = etree.fromstring(data)
toner_id = "095205615111"
# find a toner
results = root.xpath("//t[@id = '%s']" % toner_id)
if not results:
raise Exception("Toner does not exist")
toner = results[0]
# change the amount
amount = toner.find("amount")
amount.text = str(int(amount.text) + 1)
print(etree.tostring(root))
Upvotes: 8