0

I am trying to create a python script that will iterate through a folder structure, find folders named 'bravo', and modify the xml files contained within them.

In the xml files, I want to modify the 'location' attribute of a tag, called 'file'. Such as:

<file location="e:\one\two"/>

I just need to change the drive letter of the file path from ‘e’ to ‘f’. So that it will read:

<file location="f:\one\two"/>

However...

The name of these xml files are unique, so I cannot search for the exact xml file name. Instead I am searching by the xml file type.

Also, there are other xml files in my folder structure, without the ‘file’ tag reference, that I wish to ignore.

The only constant is that the xml files I want to modify are all stored in folders named, ‘bravo’.

I also wish to create a log file that lists all the xml files and their filepaths which have successfully been updated (and preferably the ones that failed).

Using answers to similar questions on this site, I have cobbled together the following script.

In its current state, the script trys to modify every xml files it finds. I have not been able to successfully add code that only searches folders called, ‘bravo'.

When the script modifies an xml file, not in a 'bravo' folder, it errors because these files do not contain a 'file' tag.

Please could someone help me to correct my script (or create a new one).

Here is an example of the folder structure...

My folder structure

And my script so far...

from xml.dom import minidom
   import os

   # enter the directory where to start search for xml files...

   for root, dirs, files in os.walk("c:/temp"):
       for file in files:
           #search for xml files...
           if file.endswith(".xml"):
               xml_file = file

               xmldoc = minidom.parse(os.path.join(root, xml_file))

               # in the xml file look for tag called "file"...
               file_location = xmldoc.getElementsByTagName("file")
               # i don't understand the next line of code, but it's needed
               file_location = file_location[0]

               # 'location_string' is a variable for the 'location' path of the file tag in the xml document
               location_string = (file_location.attributes["location"].value)

               # the new drive letter is added to the location_string to create 'new_location'
               new_location = "f" + location_string[1:]

               # replace the 'location' value of the file tag with the new location...
               file_location.attributes["location"].value = new_location

               # write the change to the original file
               with open((os.path.join(root, xml_file)),'w') as f:
               f.write(xmldoc.toxml())
               print "%s has been updated!" % (os.path.join(root, xml_file))
               # add updated file name to log...
               log_file = open("filepath_update_log.txt", "a")
               log_file.write("%s\n" % (os.path.join(root, xml_file)))
               log_file.close
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Ant78
  • 1
  • 1

1 Answers1

0
  1. Test if the directory name fits, before your second loop. You'd have to get the last directory in the path first. As in: How to get only the last part of a path in Python?

    if os.path.basename(os.path.normpath(root)) == "bravo":
    
  2. You could use the https://docs.python.org/3/library/logging.html module for logging.

  3. If you only want to replace a single letter, then maybe you can directly replace it instead of parsing xml. As suggested in: https://stackoverflow.com/a/17548459/7062162

    def inplace_change(filename, old_string, new_string):
        # Safely read the input filename using 'with'
        with open(filename) as f:
            s = f.read()
            if old_string not in s:
                print('"{old_string}" not found in  {filename}.'.format(**locals()))
                return
    
        # Safely write the changed content, if found in the file
        with open(filename, 'w') as f:
            print('Changing "{old_string}" to "{new_string}" in {filename}'.format(**locals()))
            s = s.replace(old_string, new_string)
            f.write(s)
    
Community
  • 1
  • 1
seenorth
  • 17
  • 1
  • 9