SyntaxError: invalid predicate when parsing a xml file in Python

37 views Asked by At

I am writting a python script which goal is to change the value of a xml tag when matching a given criteria : here I'd like to change the active tag from true to false if the id is 'Pikachu'

When I run my python script, I get SyntaxError: invalid predicate error.

Here is my python sample code

import xml.etree.ElementTree as ET

def engineXmlCleaning(bs):
     enginePath = "Engine.xml"
     tree = ET.parse(enginePath)
     root = tree.getroot()
     
     id_to_check='pikachu'

     # Search for the element with specified ID
     matching_elements = root.findall(".//tototiti.engine.BestMatchingConfig[bestMatchingDataID/id='" + id_to_check + "']")

     # Check if element exists 
     if matching_elements:
          print("The element with id " + id_to_check + " exists.")

     for element in matching_elements:
          active_element = element.find('.//active')
          if active_element is not None:
               print('... Amending the Active value ...')
               active_element.text = 'false'

     tree.write(enginePath)

Here is a sample of xml file I'd like to amend via my script

<Engine id="1">
<bestMatchingConfigs id="50">
        <tototiti.engine.BestMatchingConfig id="51">
            <ParsingTypeName>alex_ordinate</ParsingTypeName>
            <bestMatchingDataID id="52">
                <id>pikachu</id>
            </bestMatchingDataID>
            <scriptID id="53">
                <id>pika_js</id>
            </scriptID>
            <active>true</active>
        </tototiti.engine.BestMatchingConfig>
        <tototiti.engine.BestMatchingConfig id="54">
            <ParsingTypeName>don_pillar</ParsingTypeName>
            <bestMatchingDataID id="55">
                <id>don</id>
            </bestMatchingDataID>
            <scriptID id="56">
                <id>don_js</id>
            </scriptID>
            <active>true</active>
        </tototiti.engine.BestMatchingConfig>
</bestMatchingConfigs>
</Engine>

When I run my python script, I get SyntaxError: invalid predicate error.

2

There are 2 answers

0
Daniel Haley On BEST ANSWER

Like I mentioned in the comments, the xpath support in ElementTree is limited.

If you're able to switch to lxml, you can do a more complex xpath which reduces the number of find/findall/if that need to be used (see the other answer for an example).

Example using lxml...

from lxml import etree


def engineXmlCleaning(id_to_check):
    enginePath = "engine.xml"
    tree = etree.parse(enginePath)

    for active_element in tree.xpath(f".//tototiti.engine.BestMatchingConfig[bestMatchingDataID/id='{id_to_check}']/active"):
        active_element.text = "false"

    tree.write("engine.xml")


engineXmlCleaning("pikachu")
0
Hermann12 On

You can use an if condition and the find():

import xml.etree.ElementTree as ET

root = ET.parse('engine.xml').getroot()

for toto in root.findall('.//tototiti.engine.BestMatchingConfig'):
    if toto.find('bestMatchingDataID/id').text == 'pikachu':
        toto.find('active').text = 'false'

ET.indent(root, space="  ")
ET.dump(root)

Output:

<Engine id="1">
  <bestMatchingConfigs id="50">
    <tototiti.engine.BestMatchingConfig id="51">
      <ParsingTypeName>alex_ordinate</ParsingTypeName>
      <bestMatchingDataID id="52">
        <id>pikachu</id>
      </bestMatchingDataID>
      <scriptID id="53">
        <id>pika_js</id>
      </scriptID>
      <active>false</active>
    </tototiti.engine.BestMatchingConfig>
    <tototiti.engine.BestMatchingConfig id="54">
      <ParsingTypeName>don_pillar</ParsingTypeName>
      <bestMatchingDataID id="55">
        <id>don</id>
      </bestMatchingDataID>
      <scriptID id="56">
        <id>don_js</id>
      </scriptID>
      <active>true</active>
    </tototiti.engine.BestMatchingConfig>
  </bestMatchingConfigs>
</Engine>

For your xpath search you can use the part in xml.etree.ElementTree:

# Search for the element with specified ID
matching_elements = root.findall('.//*[id="pikachu"]/id')

# Check if element exists
if id_to_check == matching_elements[0].text:
    print("The element with id " + id_to_check + " exists.")