Hi, I'm trying to replace some characters within a lyrx file.
In this example I need to replace "570" with "560"
The problem I have is that two lines are identical but I only need to replace one (highlighted in yellow in the image below) and not the one a few lines above the highlighted one.
The code I'm using:
for i, line in enumerate(fileinput.input(OUT_workspace + "\\" + "AE000S560_005M5001P01M041.lyrx", inplace=1)):
sys.stdout.write(line.replace('"max" : 570', '"max" : 560'))
I would really appreciate any help. I'm not sure how to target a specific line within the file. Many thanks.
Solved! Go to Solution.
Thanks Brian. Does not seem to work unfortunately as the values don't change. Please see the code.
import arcpy
import os
import string
import sys
import fileinput
from arcpy import env
arcpy.env.overwriteOutput=True
from arcpy.sa import*
env.workspace = r"H:\PROGRAMMES\10_OTHER_PROJECTS\26_04072022_KEV"
OUT_workspace = r"H:\PROGRAMMES\10_OTHER_PROJECTS\26_04072022_KEV_NEW"
Lyrx = "AE000S570_005M5001P01M041.lyrx"
# Copy new file into new folder
arcpy.Copy_management(Lyrx, OUT_workspace + "\\" + "AE000S570_005M5001P01M041.lyrx")
arcpy.Copy_management(Lyrx, OUT_workspace + "\\" + "AE000S560_005M5001P01M041.lyrx")
with open(OUT_workspace + "\\" + "AE000S560_005M5001P01M041.lyrx") as fp:
lyrx = fp.read()
lyrx.replace('570,\n"max"', '560,\n"max"')
You need to write the changed string back out to a file, you could do this, and avoid loading all those libraries you don't need too. Loading "arcpy" takes forever.
import os
IN_workspace = r"H:\PROGRAMMES\10_OTHER_PROJECTS\26_04072022_KEV"
OUT_workspace = r"H:\PROGRAMMES\10_OTHER_PROJECTS\26_04072022_KEV_NEW"
Lyrx = "AE000S570_005M5001P01M041.lyrx"
with open(os.path.join(IN_workspace, Lyrx), "r") as fp:
lyrx = fp.read()
fixed = lyrx.replace('570,\n"max"', '560,\n"max"')
if lyrx == fixed:
print("WARNING, NOTHING CHANGED!")
with open(os.path.join(OUT_workspace, Lyrx), "w") as fp:
fp.write(fixed)
I used "os.path.join" to build up the file paths just because it is tidier, sometimes that avoids problems with missed slashes and stuff like that. It's OS independent too.
I avoid relying on the arcgis "workspace" because about 1/2 the Esri tools just ignore it.
Hi @anTonialcaraz,
I assume that you are using python. If that is the case, another option instead of using replace would be to create a dictionary so that the set values in the dictionary are overwritten to the value that you specify.
maxvalue = {"max": 560}
for i, line in enumerate(fileinput.input(OUT_workspace + "\\" + "AE000S560_005M5001P01M041.lyrx", inplace=1)):
#insert line exception below for specific line to update
if i ==(line number to change):
maxvalue["max"] = 570
sys.stdout.write(maxvalue["max"])
Without knowing the code specifics, this is the only suggestion I can come up with at the moment.
Thanks very much @RPGIS, I appreciate.
Yes, I'm using Python. I've tried this:
maxvalue = {"max": 570}
for i, line in enumerate(fileinput.input(OUT_workspace + "\\" + "AE000S560_005M5001P01M041.lyrx", inplace=1)):
#insert line exception below for specific line to update
if i ==(706):
maxvalue["max"] = "560"
sys.stdout.write(maxvalue["max"])
But the result I'm getting is simply "560". All the rest of the contents in the .lyrx file are gone.
Any suggestions?
You would need to access the activeSlice dictionary(wherever that is being stored), then access the rangeDimensionValue dictionary to set the max within that dictionary. To do that, you would simply need to find where the activeSlice is the key and then access the values within that key. Then access the rangeDimensionValue values to then set the max to the specified value.
You may be able to access that particular value as such:
"activeSlice"["rangeDimensionValue"]["max"]= maxvalue["max"]
I can't tell (based on the png) if those values are in both lists and dictionaries, or a combination of sorts. If you can find the activeSlice key, then you should be able to use the suggestion above to change the max value.
Thanks again @RPGIS.
I'm not very familiar with the activeSlice dictionary concept unfortunately. Must admit I'm a bit lost now.
Please let me pass you the .lyrx file see if that makes things easier. I just need to replace the rangeDimensionValue of several files. For example, from 570 to 560. I was initially using line.replace but that would change the "customFullExtent" part as well and I need that to keep the same values.
The activeSlice is a specific key storing all other values that are assigned to that key.
Hi, why don’t you parse the lyrx and then you can address the “rangeDimensionValue” directly?
Couple things here- fileinput will basically create an list of lines from the text file so I don't think you can access the 'keys' as structured in the png or python dictionary. Enumerate creates an inplace tuple containing the index number and value (line).
Meaning line 706 will just look like '"max": 570' when you are iterating over it. To replace it, use '"max": 560'. Also, if you don't put anything back to the file if it doesn't match in the if, fileinput erases it which is probably why you only ended up with 560.
for i, line in enumerate(fileinput.input(OUT_workspace + "\\" + "AE000S560_005M5001P01M041.lyrx", inplace=1)):
#insert line exception below for specific line to update
if i == 760:
sys.stdout.write("max": 560) # or '"max": 560', im not sure which would work
else:
sys.stdout.write(line)
Treat the entire file as one string with newlines embedded in it, then use "replace".
lyrx is the string containing the entire file
Line 3 looks for the pattern of 560 on a line and "max" on the next line then replaces that with the new value
with open("file.lyrx") as fp:
lyrx = fp.read()
lyrx.replace('560,\n"max"', '570,\n"max"'))
If you want a more general approach that deals with random whitespace you could use the re.sub instead, you can go down a real rabbit hole with regex though so use plain old replace unless you are getting fancy.
import re
fixed = re.sub('560,\s*"max"','570,\n"max"',lyrx)
Thanks Brian. Does not seem to work unfortunately as the values don't change. Please see the code.
import arcpy
import os
import string
import sys
import fileinput
from arcpy import env
arcpy.env.overwriteOutput=True
from arcpy.sa import*
env.workspace = r"H:\PROGRAMMES\10_OTHER_PROJECTS\26_04072022_KEV"
OUT_workspace = r"H:\PROGRAMMES\10_OTHER_PROJECTS\26_04072022_KEV_NEW"
Lyrx = "AE000S570_005M5001P01M041.lyrx"
# Copy new file into new folder
arcpy.Copy_management(Lyrx, OUT_workspace + "\\" + "AE000S570_005M5001P01M041.lyrx")
arcpy.Copy_management(Lyrx, OUT_workspace + "\\" + "AE000S560_005M5001P01M041.lyrx")
with open(OUT_workspace + "\\" + "AE000S560_005M5001P01M041.lyrx") as fp:
lyrx = fp.read()
lyrx.replace('570,\n"max"', '560,\n"max"')