I need help to find and replace an attribute "parentid" that has "00000000-0000-0000-0000-000000000000" in each XML file in a folder. The actual filename of each file without the extension should replace the "parentid" attribute in XML. (Powershell or Batch file)
For example: C:\Folder\
4de6d1b4-b014-4cb3-bb61-649737a8217b.xml
4d2345b4-b415-5656-12dv-832jnm89234n.xml
...
Content of the XML:
<comment id="4de6d1b4-b014-4cb3-bb61-649737a8217b" parentid="00000000-0000-0000-0000-000000000000" approved="True">
<date>2014-12-20 22:23:40</date>
<author>Joe Doe</author>
<email>test@example.com</email>
<country />
<ip>0.0.0.0</ip>
<avatar />
<content>Test</content>
</comment>
I appreciate everyone's help!
This is what I have so far however it replaces the whole line not the actual value of the attribute.
@echo off &setlocal
setlocal enabledelayedexpansion
set "search=00000000-0000-0000-0000-000000000000"
set "replace=%%~nP"
set "textfile=%%~nxP"
set "newfile=%%~nP"
for /r %%P in (*) do (
(for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
set "line=!line:%search%=%replace%!"
echo(!line!))>"%newfile%"
)
)
endlocal
@ECHO ON
The basic problem is that you are referring to a for
variable, namely %%P
, outside of the loop scope, which I do not recommend.
With pure batch scripting, I would change your code to this:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SEARCH=00000000-0000-0000-0000-000000000000"
for %%P in ("*.xml") do (
for /F "delims=" %%I in ('
findstr /N /R "^" "%%~P" ^& ^> "%%~fP" break
') do (
set "LINE=%%I"
setlocal EnableDelayedExpansion
set "LINE=!LINE:*:=!"
if defined LINE set "LINE=!LINE:%SEARCH%=%%~nP!"
>> "%%~fP" echo(!LINE!
endlocal
)
)
endlocal
exit /B
This is capable of modifying the enumerated *.xml
files in the current directory directly, so no interim file is required to do the replacement of the attribute parentid
.
Each file is read by findstr
which precedes every line with a line number and a colon temporarily in order not to lose empty lines (remember that for /F
ignores such). The command line set "LINE=!LINE:*:=!"
removes the prefix afterwards. Note that delayed expansion is toggled in the for /F
in order not to lose any exclamation marks occurring within the files. These measures ensure that the original *.xml
file contents are not altered, except the replaced portion of course.
There are lots of examples of loading/parsing an XML file in PowerShell, but the fastest solution in such a simple case as this one would be to use a plain text search/replace on a string that holds the entire file:
$searchFor = 'parentid="00000000-0000-0000-0000-000000000000"'
Get-ChildItem -Literal 'c:\folder' -Filter '*.xml' -Recurse |
Where {
Select-String $searchFor -Path $_ -CaseSensitive -SimpleMatch
} |
ForEach {
$text = [IO.File]::ReadAllText($_.FullName)
$text.replace($searchFor, 'parentid="' + $_.BaseName + '"') |
Out-File (Join-Path $_.Directory "$($_.BaseName)-new.xml") -Encoding utf8
}