Diego
Diego

Reputation: 133

Python lxml finding element by id-tag

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:

  1. Check if the id exist (the id-value is a variable in my python program piped from the content in a txt-file)

  2. 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

Answers (2)

alecxe
alecxe

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

alecxe
alecxe

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

Related Questions