How to extract single particular tag value in xml using python and modify

Viewed 57

I want to read IntakeFanSpeedMax, IntakeFanSpeedMin tag value and update using python in below xml, tried many tutorials but not able to read and update it. Please help me on this, Thanks in advance.

        <?xml version="1.0"?>
        <RobotManager Checksum="CCA4FBB2C307EBE537BDCEAFB340F5F22ABE178951B0F7FDDFBDC8939D0A3CAC">
          <Setup>
            <AddressHostName>192.168.2.1</AddressHostName>
            <PowerStateMonitor>
              <PowerStateMonitor1>
                <CommPort>2</CommPort>
              </PowerStateMonitor1>
              <PowerStateMonitor2>
                <Pmu>
                  <!-- in seconds (minimum: 90; maximum: 150) -->
                  <AcNotPresentShutdownTime>120</AcNotPresentShutdownTime>
                  <!-- in degrees Celsius (minimum: 0; maximum: 100) -->
                  <BatteryTemperatureDifferential>6</BatteryTemperatureDifferential>
                  <!-- in RPMs (minimum: 3000; maximum: 5000) -->
                  <IntakeFanSpeedMax>4000</IntakeFanSpeedMax>
                  <!-- in RPMs (minimum: 750; maximum: 1300) -->
                  <IntakeFanSpeedMin>1000</IntakeFanSpeedMin>
</Pmu>
    </RobotManager>


my code:

import xml.etree.ElementTree as ET

fileXml = "C://Users//...//Documents//RobotManagerSettings.xml"
tree = ET.parse(fileXml)
root = tree.getroot()
IntakeFanSpeedMax = root.find('IntakeFanSpeedMax').text
print(IntakeFanSpeedMax)



getting below error:
"C:\Users\Sagar Hosamath\AppData\Local\Programs\Python\Python39\python.exe" "C:/Users/Sagar Hosamath/PycharmProjects/Coord/venv/Scripts/xmlPath.py"
Traceback (most recent call last):
  File "C:\Users\Sagar Hosamath\PycharmProjects\Coord\venv\Scripts\xmlPath.py", line 6, in <module>
    IntakeFanSpeedMax = root.find('IntakeFanSpeedMax').text
AttributeError: 'NoneType' object has no attribute 'text'

Process finished with exit code 1
2 Answers

The easiest way to accomplish this would be by using pyquery with the xml text, you can apply this as follows (this will also replace the tag values with the updated ones):

    from pyquery import PyQuery as pq

xml_text = '''        <?xml version="1.0"?>
        <RobotManager Checksum="CCA4FBB2C307EBE537BDCEAFB340F5F22ABE178951B0F7FDDFBDC8939D0A3CAC">
        <Setup>
            <AddressHostName>192.168.2.1</AddressHostName>
            <PowerStateMonitor>
            <PowerStateMonitor1>
                <CommPort>2</CommPort>
            </PowerStateMonitor1>
            <PowerStateMonitor2>
                <Pmu>
                <!-- in seconds (minimum: 90; maximum: 150) -->
                <AcNotPresentShutdownTime>120</AcNotPresentShutdownTime>
                <!-- in degrees Celsius (minimum: 0; maximum: 100) -->
                <BatteryTemperatureDifferential>6</BatteryTemperatureDifferential>
                <!-- in RPMs (minimum: 3000; maximum: 5000) -->
                <IntakeFanSpeedMax>4000</IntakeFanSpeedMax>
                <!-- in RPMs (minimum: 750; maximum: 1300) -->
                <IntakeFanSpeedMin>1000</IntakeFanSpeedMin>
</Pmu>
    </RobotManager>'''

d = pq(xml_text)

max_obj = d('IntakeFanSpeedMax')
min_obj = d('IntakeFanSpeedMin')

print('Intake Speed Max: {}'.format(max_obj.text()))
print('Intake Speed Min: {}'.format(min_obj.text()))

new_max_value = '3000'
new_min_value = '300'

max_obj.replaceWith('<IntakeFanSpeedMax>{}</IntakeFanSpeedMax>'.format(new_max_value))
min_obj.replaceWith('<IntakeFanSpeedMin>{}</IntakeFanSpeedMin>'.format(new_min_value))

print(d)

When looking for nested tags, you need the following format

>>> root.findall(".//IntakeFanSpeedMax")
[<Element 'IntakeFanSpeedMax' at 0x000001E40DBE8D60>]
>>> root.findall(".//IntakeFanSpeedMax")[0].text
'4000'

It works if you have just one instance of this tag. If you have several, you'll need to find list of parent tags, and look inside them one by one.

Update per comment question: It seems like you have to assign a text, not integer, like below

import xml.etree.ElementTree as ET
fileXml = "C://Users//..//Documents//RobotManagerSettings.xml"
tree = ET.parse(fileXml)
root = tree.getroot()
value = root.findall(".//IntakeFanSpeedMax")[0].text
if value == "4000":
    root.findall(".//IntakeFanSpeedMax")[0].text = "8000"
tree.write('output.xml',encoding='UTF-8',xml_declaration=True)
Related