-4

I am days trying to change a value in an XML file I found some things and I was adapting but I still didn't have success I need to change the value of the TAG showLockNotifications from 0 to 1 but when running the script it changes all lines .

could someone help me?

<?xml version="1.0"?>
<useroptions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <useroption name="showLockNotifications" value="0" /> <-- ** I'd like to change only this value to 1**
  <useroption name="showLowBatteryNotifications" value="1" />
  <useroption name="showBacklightingAdjustments" value="1" />
  <useroption name="automaticCheckForUpdates" value="1" />
  <useroption name="collectAnonymousData" value="0" />
  <useroption name="isAutoBackupEnabled" value="1" />
  <useroption name="HideAnalytics" value="0" />
  <useroption name="showFlowNotificationIcon" value="1" />
</useroptions>

I have tried this code but it replaces all lines in the file...

@echo off
setlocal EnableDelayedExpansion

set anotherVariable=1

(for /F "delims=" %%a in (options.xml) do (
   set "line=%%a"
   set "newLine=!line:name="showLockNotifications">=!"
   if "!newLine!" neq "!line!" (
      set "newLine=  <useroption name="showLockNotifications" value="%anotherVariable%" />"
   )
   echo !newLine!
)) > newFile.xml

Output:

<?xml version="1.0"?>
<useroptions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <useroption name="showLockNotifications" value="1" />
  <useroption name="showLockNotifications" value="1" />
  <useroption name="showLockNotifications" value="1" />
  <useroption name="showLockNotifications" value="1" />
  <useroption name="showLockNotifications" value="1" />
  <useroption name="showLockNotifications" value="1" />
  <useroption name="showLockNotifications" value="1" />
  <useroption name="showLockNotifications" value="1" />
</useroptions>
Squashman
  • 13,649
  • 5
  • 27
  • 36
Morgan
  • 1
  • 1
  • 4
    You would be better off using a language that has a native method to read and write xml then trying to brute force it with a batch file. – Squashman May 01 '21 at 17:06
  • Does [Batch script to find and replace a string in text file without creating an extra output file for storing the modified file](https://stackoverflow.com/questions/23075953/batch-script-to-find-and-replace-a-string-in-text-file-without-creating-an-extra/23076141) help? – Andrew Morton May 01 '21 at 17:28
  • It can be done, but it's not wise. Batch files do not contain modules or packages that can interpret xml format. When you try and do it with a batch file, your are reading it as plain text and brute force re-writing it, hoping you'll get a proper result.. Just wait until you experience some sudden special characters and suddenly your xml turns upside down like a flapjack in a cast iron pan. – Gerhard May 01 '21 at 20:15
  • Morgan, there are multiple answers to your question now, and I have noted that you have visited this site since they were provided. Please can you review those answers, and provide relevant feedback to their authors. _You could also, optionally, reconsider your accepted answer based upon your testing of those too_. – Compo May 03 '21 at 12:33

3 Answers3

0

As already mentioned in the comments, this is much safer and better done using something which has support for xml file handling.

The following gets such support from :

@powershell.exe -NoProfile "[xml]$xml = Get-Content 'options.xml' -Raw;"^
 "$xml.SelectSingleNode(\"//useroption[@name='showLockNotifications']\").SetAttribute('value','1');"^
 "$xml.Save('newFile.xml')"
Compo
  • 36,585
  • 5
  • 27
  • 39
0

To save yourself a lot of headache I'd recommend an XML-parser like or instead.

xmlstarlet.exe ed -u "//useroption[@name='showLockNotifications']/@value" -v 1 options.xml
xidel.exe -s options.xml -e "x:replace-nodes(//useroption[@name='showLockNotifications']/@value,function($x){attribute {name($x)} {'1'}})" --output-format=xml --output-declaration='^<?xml version="1.0"?^>'

xidel.exe -s options.xml -e ^"^
  x:replace-nodes(^
    //useroption[@name='showLockNotifications']/@value,^
    function($x){attribute {name($x)} {'1'}}^
  )^
" --output-format=xml --output-declaration='^<?xml version="1.0"?^>'
Reino
  • 3,203
  • 1
  • 13
  • 21
-1

I hope you like this solution :-)

Edited with more clear code optimization:

@echo off
cls
setlocal EnableDelayedExpansion

set anotherVariable=1

(for /F "delims=" %%a in (options.xml) do (
   set "line=%%a"
   set "newLine=!line:showLockNotification=!"

   if "!newLine!" neq "!line!" (
      set "newLine=  <useroption name="showLockNotifications" value="%anotherVariable%" />"
      > con echo !newLine!
      echo !newLine!
   )
   if "!newLine!" equ "!line!" (
      > con echo !line!
      echo !line!
   )
 )
) > newFile.xml

pause

Explaination of mistakes in your code:

  • The string substitution format was not propertly used
  • the loop print only the "newLine" but not the old lines
aschipfl
  • 33,626
  • 12
  • 54
  • 99
Acca Emme
  • 356
  • 2
  • 11
  • 2
    @Acca Emma Why one loop for display and a second loop to change the file ? You can use, for example, the stderr stream to do both in one loop. – Zilog80 May 01 '21 at 19:24
  • Well, I don't really like this, because repeated code is never a good idea (which could be avoided by just using the second loop with inserted commands like `> con echo !newline!` and `> con echo !line!` at the proper locations); but what I miss most is an explanation of what is going on in your code… – aschipfl May 02 '21 at 14:59
  • @aschipfl: I cleared the code and I text an explaination about mistakes, I hope now can be more clear for the community :-) – Acca Emme May 03 '21 at 07:13
  • Removing the `echo` commands without the `> con` prefix will result in an empty output file… – aschipfl May 03 '21 at 10:54