LXML + Python: How to find and work with parameters at the same parent-child level

I’m not sure how to approach this issue – so I don’t have much code yet on the matter I’m afraid.

I’m working with lxml for reading and writing XML files. I have a scenario where some XML I’m needing to read has some components like the below. What I need to do is to identify whether a Setting whose Property has a Value_1 of a particular variety and then work with the Value_1. I’ll also need to be able to set that Value_1 to something else.

Given the examples below: let’s say I wanted to test the value of Setting Name 3, and if True set it to False, how would I do that?

<?xml version="1.0" standalone="yes"?>
<ProjectDataSet>

   ... Many other bits here

  <Setting>
    <Property>Setting Name 1</Property>
    <Value_1>5</Value_1>
    <Comments>Allows values between 1 and 10, 5 is default</Comments>
  </Setting>
  <Setting>
    <Property>Setting Name 2</Property>
    <Value_1>False</Value_1>
  </Setting>
  <Setting>
    <Property>Setting Name 3</Property>
    <Value_1>True</Value_1>
    <Comments>Setting enables a True or False</Comments>
  </Setting>
  <Setting>
    <Property>Setting Name 4</Property>
    <Value_1>True</Value_1>
    <Comments>This example sets True</Comments>
  </Setting>
</ProjectDataSet>

I can work out how to find just the Property and modify it per example below, but cannot work out how I would identify Value_1 of the same Setting and change it from True to False:

import lxml

#import the xml
tree = etree.parse('C:/temp/myxml.xml')
root = tree.getroot()

#Change the current name to add "My New Property" at the end.
setNameText = root.xpath('//Setting/Property/text()')
setName = root.xpath('//Setting/Property')
     if setName:
          setName[0].text = setNameText[0] + " My New Property"

Thank you

Answer

In order to “test the value of Setting Name 3, and if True set it to False”, I believe you need something like this:

targets = root.xpath("//Setting[./Property[.='Setting Name 3']]")
for target in targets:
    val = target.xpath('./Value_1')[0]
    if val.text=="True":
        val.text="False"
print(etree.tostring(root).decode())

Based on your sample xml above, the output should be:

<ProjectDataSet>
  <Setting>
    <Property>Setting Name 1</Property>
    <Value_1>5</Value_1>
    <Comments>Allows values between 1 and 10, 5 is default</Comments>
  </Setting>
  <Setting>
    <Property>Setting Name 2</Property>
    <Value_1>False</Value_1>
  </Setting>
  <Setting>
    <Property>Setting Name 3</Property>
    <Value_1>False</Value_1>
    <Comments>Setting enables a True or False</Comments>
  </Setting>
  <Setting>
    <Property>Setting Name 4</Property>
    <Value_1>True</Value_1>
    <Comments>This example sets True</Comments>
  </Setting>
</ProjectDataSet>